로케일 식별자가 유효한지 확인하는 방법
로케일 식별자를 날짜, 숫자, 통화 포맷에 사용하기 전에 미리 검증하세요
소개
애플리케이션에서 사용자 입력, API 응답, 또는 설정 파일로부터 로케일 식별자를 받을 때, 사용하기 전에 반드시 유효한 값인지 확인해야 합니다. 유효하지 않은 로케일 식별자를 사용하면 포맷팅 함수에서 오류가 발생하거나 예상치 못한 결과가 나올 수 있습니다.
유효성 검사를 통해 en-US와 같은 문자열이 국제 표준에 따라 구조적으로 올바른지 확인할 수 있습니다. 이를 통해 Intl API나 기타 국제화 라이브러리에 로케일 식별자를 전달할 때 런타임 오류를 예방할 수 있습니다.
JavaScript에는 로케일 식별자의 유효성을 검증할 수 있는 내장 메서드가 두 가지 있습니다. 두 방법 모두 BCP 47 표준을 기준으로 식별자의 형식을 검사합니다. BCP 47은 언어 태그의 포맷을 정의합니다.
로케일 식별자가 유효하려면
로케일 식별자는 언어 태그를 위한 BCP 47 표준을 따릅니다. 이 표준은 언어, 스크립트, 지역, 확장 요소를 어떻게 조합할지 구조와 규칙을 정의합니다.
유효한 로케일 식별자는 컴포넌트별로 하이픈(-)으로 구분하며, 언더스코어나 다른 문자는 사용할 수 없습니다. 언어 코드는 반드시 인식 가능한 ISO 639 코드여야 하며, 지역 코드는 인식 가능한 ISO 3166-1 코드여야 합니다.
유효한 로케일 식별자 예시:
en(영어)en-US(미국식 영어)zh-Hans(간체 중국어)zh-Hans-CN(중국에서 사용하는 간체 중국어)en-US-u-ca-gregory(그레고리력 달력을 사용하는 미국식 영어)
유효하지 않은 로케일 식별자 예시:
en_US(하이픈 대신 언더스코어 사용)english(인식되지 않는 언어 코드)en-USA(지역 코드는 세 글자가 아닌 두 글자여야 함)EN-us(언어 코드는 반드시 소문자여야 함)abc-XY(존재하지 않는 언어 코드)
유효성 검사 메서드는 이러한 구조적 규칙을 확인하고 코드가 인식되는 표준인지 검증합니다.
Intl.getCanonicalLocales로 유효성 검사하기
Intl.getCanonicalLocales() 메서드는 로케일 식별자의 유효성을 검사하고 이를 표준 형태로 반환합니다. 이 메서드는 하나의 로케일 식별자나 여러 개의 식별자 배열을 받을 수 있습니다.
const result = Intl.getCanonicalLocales("en-US");
console.log(result);
// Output: ["en-US"]
이 메서드는 입력값을 표준 형식으로 변환하여 정규화합니다. 대소문자가 틀린 로케일 식별자를 전달해도, 올바른 표준 형태로 반환해줍니다:
const result = Intl.getCanonicalLocales("EN-us");
console.log(result);
// Output: ["en-US"]
잘못된 로케일 식별자를 전달하면, 메서드는 RangeError 오류를 발생시킵니다:
try {
Intl.getCanonicalLocales("en_US");
} catch (error) {
console.error(error.name);
// Output: "RangeError"
console.error(error.message);
// Output: "en_US is not a structurally valid language tag"
}
이 오류는 식별자가 BCP 47 표준 구조를 따르지 않음을 알려줍니다. 오류를 캐치하여 유효하지 않은 입력을 적절히 처리할 수 있습니다.
여러 로케일 식별자 유효성 검사하기
Intl.getCanonicalLocales() 메서드는 여러 개의 로케일 식별자 배열을 한 번에 검사할 수 있습니다. 모든 유효한 식별자에 대해 표준 형태의 배열을 반환합니다.
const locales = ["en-US", "fr-FR", "es-MX"];
const result = Intl.getCanonicalLocales(locales);
console.log(result);
// Output: ["en-US", "fr-FR", "es-MX"]
이 메서드는 결과에서 중복된 로케일 식별자도 제거합니다:
const locales = ["en-US", "EN-us", "en-US"];
const result = Intl.getCanonicalLocales(locales);
console.log(result);
// Output: ["en-US"]
세 입력값 모두 같은 로케일을 의미하므로, 메서드는 표준 형태 하나만을 반환합니다.
배열 내에 하나라도 잘못된 로케일이 있으면 전체 메서드가 오류를 발생시킵니다:
try {
Intl.getCanonicalLocales(["en-US", "invalid", "fr-FR"]);
} catch (error) {
console.error(error.message);
// Output: "invalid is not a structurally valid language tag"
}
사용자가 입력한 목록을 검증할 때는 각 로케일을 개별적으로 검사하여 어떤 식별자가 잘못됐는지 파악하는 것이 좋습니다.
Intl.Locale 생성자를 이용한 유효성 검사
Intl.Locale 생성자는 로케일 식별자를 검증하는 또 다른 방법을 제공합니다. 잘못된 식별자로 로케일 객체를 생성할 경우, 생성자는 RangeError 오류를 발생시킵니다.
try {
const locale = new Intl.Locale("en-US");
console.log("Valid locale");
} catch (error) {
console.error("Invalid locale");
}
// Output: "Valid locale"
생성자는 잘못된 식별자에 대해 다음과 같이 오류를 발생시킵니다:
try {
const locale = new Intl.Locale("en_US");
console.log("Valid locale");
} catch (error) {
console.error("Invalid locale");
console.error(error.message);
}
// Output: "Invalid locale"
// Output: "invalid language subtag: en_US"
Intl.getCanonicalLocales()와 달리, Intl.Locale 생성자는 대소문자를 정규화하지 않습니다. 식별자가 올바른 대소문자를 사용해야 합니다:
const locale1 = new Intl.Locale("en-US");
console.log(locale1.baseName);
// Output: "en-US"
const locale2 = new Intl.Locale("EN-US");
console.log(locale2.baseName);
// Output: "en-US"
대소문자 구분 없이 언어 코드를 입력할 수 있으며, 생성자는 이를 표준 형태로 자동 변환합니다.
검증 방식 선택하기
두 가지 검증 방식은 각기 다른 목적과 기능을 제공합니다.
다음과 같은 경우에는 Intl.getCanonicalLocales()를 사용하세요:
- 로케일 식별자를 표준 형식으로 통일
- 로케일 식별자 목록을 검증 및 중복 제거
- 일관성 없는 대소문자를 표준 형태로 변환
- 오브젝트를 생성하지 않고 로케일 식별자만 검증
다음과 같은 경우에는 Intl.Locale 생성자를 사용하세요:
- 로케일 식별자를 검증하고 즉시 그 속성을 활용해야 할 때
- 식별자에서 언어, 지역, 스크립트 등의 구성 요소를 추출할 때
- 다른 Intl API와 함께 사용할 로케일 오브젝트를 생성할 때
- 로케일 식별자를 검증하고 동시에 조작해야 할 때
Intl.Locale 생성자는 오브젝트를 생성하여 속성을 조회하거나 수정할 수 있으므로 더 강력합니다. 하지만 검증과 표준화만 필요하다면 Intl.getCanonicalLocales()가 더 간단합니다.
사용자 입력값 검증하기
사용자 입력으로 로케일 식별자를 받을 때는, 실제 사용 전에 반드시 이를 검증하세요. 이를 통해 오류를 방지하고, 잘못된 값을 입력했을 때 명확한 안내를 제공할 수 있습니다.
function validateUserLocale(input) {
try {
const canonicalLocales = Intl.getCanonicalLocales(input);
return {
valid: true,
locale: canonicalLocales[0]
};
} catch (error) {
return {
valid: false,
error: "Please enter a valid locale identifier like en-US or fr-FR"
};
}
}
const result1 = validateUserLocale("en-US");
console.log(result1);
// Output: { valid: true, locale: "en-US" }
const result2 = validateUserLocale("english");
console.log(result2);
// Output: { valid: false, error: "Please enter a valid locale..." }
이 함수는 입력값을 검증하여, 표준 로케일 값이나 사용자에게 보여줄 수 있는 오류 메시지를 반환합니다.
설정 데이터 검증하기
애플리케이션은 주로 설정 파일이나 환경 변수에서 로케일 식별자를 불러옵니다. 앱이 시작될 때 이러한 값들을 검증하면 설정 오류를 미리 발견할 수 있습니다.
function loadLocaleConfig(configLocales) {
const validLocales = [];
const invalidLocales = [];
for (const locale of configLocales) {
try {
const canonical = Intl.getCanonicalLocales(locale);
validLocales.push(canonical[0]);
} catch (error) {
invalidLocales.push(locale);
}
}
if (invalidLocales.length > 0) {
console.warn("Invalid locale identifiers found:", invalidLocales);
}
return validLocales;
}
const config = ["en-US", "fr-FR", "invalid", "es_MX", "de-DE"];
const locales = loadLocaleConfig(config);
console.log(locales);
// Output: ["en-US", "fr-FR", "de-DE"]
// Warning: Invalid locale identifiers found: ["invalid", "es_MX"]
이 함수는 잘못된 로케일 식별자를 걸러내고 경고를 남기며, 유효한 로케일만으로 애플리케이션이 계속 동작할 수 있게 해줍니다.
API 응답값 검증하기
외부 API로부터 받은 로케일 식별자는 실제로 사용하기 전에 반드시 검증해야 합니다. API에서는 표준에 맞지 않거나 오류가 있는 식별자가 반환될 수도 있기 때문입니다.
function processApiLocale(apiResponse) {
const locale = apiResponse.preferredLocale;
try {
const validated = new Intl.Locale(locale);
return {
success: true,
language: validated.language,
region: validated.region,
baseName: validated.baseName
};
} catch (error) {
console.error("API returned invalid locale:", locale);
return {
success: false,
fallback: "en-US"
};
}
}
const response1 = { preferredLocale: "fr-CA" };
console.log(processApiLocale(response1));
// Output: { success: true, language: "fr", region: "CA", baseName: "fr-CA" }
const response2 = { preferredLocale: "invalid_locale" };
console.log(processApiLocale(response2));
// Output: { success: false, fallback: "en-US" }
이 함수는 API 응답을 검증하고 로케일에 대한 구조화된 정보를 추출하거나, 로케일이 유효하지 않은 경우 대체 값을 제공합니다.