뱁새 다리찢기

들어가며

리포트 에디터 다국어 기능 비즈니스 요구사항이 좀 애매했습니다.

  • 지금: 한국 사용자만 한국어/영어 선택 가능 (백엔드 API 개발 중)
  • 1달 뒤: 불어 추가 예정

이럴 때 하드코딩을 하면...

// 한국 사용자만 언어 설정 보여주기
const isKorean = user.country === "KR";

// 기본 언어 결정
const language = user?.country === "KR" ? "kr" : "en";

문제는 이런 임시 하드코딩이 15개 파일에 퍼진다는 것입니다.
1달 뒤 불어 추가할 때 TODO 주석, JIRA 백로그만 믿고 찾아다니다가 하나라도 놓치면 버그가....
 
그래서 생각했습니다.
불어 지원까지 시간 많이 남았는데, TODO주석 + JIRA백로그 + 하드코딩을 순수 함수로 빼서 관리포인트 줄이기로요.
그럼 디펜던시 걸려서 휴먼에러가 원천봉쇄될 테니까요
 

문제 상황

초기 개발

// ❌ 설정 페이지
const showLanguageOption = user.country === "KR";
if (showLanguageOption) {
  // 언어 설정 UI 표시
}

// ❌ 문서 생성 A
const lang = user?.country === "KR" ? "kr" : "en";
const template = lang === "kr" ? koreanTemplate : englishTemplate;

// ❌ 문서 생성 B
const lang = user?.country === "KR" ? "kr" : "en";
const content = lang === "kr" ? koreanContent : englishContent;

// ❌ 편집 페이지
<Dropdown
  items={[
    { id: "kr", name: "한국어" },
    { id: "en", name: "English" }
  ]}
/>

비즈니스 일정 맞추려고 일단 한영만 되게 하드코딩하면....

1달 뒤 불어 추가해야 할 때

// TODO: 불어 추가 - 파일 A
const showLanguageOption = user.country === "KR";

// TODO: 불어 추가 - 파일 B
const lang = user?.country === "KR" ? "kr" : "en";

// TODO: 불어 추가 - 파일 C
const lang = user?.country === "KR" ? "kr" : "en";

// TODO: 불어 추가 - 파일 D
<Dropdown items={[...]} />
  • TODO 주석으로 찾아야 함 (귀찮음)
  • 15개 파일 하나씩 고쳐야 함 (노가다)
  • 하나라도 빼먹으면 런타임 에러 (위험함)

해결

비즈니스 일정 맞추려고 임시로 하드코딩하는 건 어쩔 수 없습니다.
근데 어디에 두느냐가 중요합니다.

순수 함수로 캡슐화

// 비즈니스로직 덜어내고 제너럴하게 바꾼 예시
export type ReportLanguage = "kr" | "en";
// 👆 불어 추가 시: "kr" | "en" | "fr"

/**
 * 사용 가능한 언어 목록
 *
 * @history
 * - 2024-10-19: 초기 구현 (한/영만 지원)
 * - 2024-11-XX: TODO - 불어 지원 추가 예정
 *
 * @caution
 * 현재 한국어/영어만 하드코딩되어 있음
 * 백엔드 API 준비 완료 후 불어 추가 필요
 */
export const AVAILABLE_LANGUAGES : Array<{
  label: string;
  value: ReportLanguage;
} = [
  { label: "Korean", value: "kr" },
  { label: "English", value: "en" }
  // 👇 불어 추가 시 주석 해제
  // { label: "French", value: "fr" }
];

/**
 * 사용자의 국가 정보를 기반으로 언어 설정 UI를 표시할지 결정합니다.
 *
 * @param userCountry - 사용자의 국가 정보
 * @returns 언어 설정을 표시해야 하면 true, 아니면 false
 *
 * @history
 * - 2024-10-19: 초기 구현 (한국만)
 * - 2024-11-XX: TODO - 모든 국가로 확대 예정
 *
 * @caution
 * 현재는 한국 사용자에게만 언어 설정을 표시합니다.
 * 불어(French) 지원 완료 후 항상 true를 반환하도록 변경 필요
 */
export function shouldShowLanguageSetting(userCountry?: string): boolean {
  return userCountry === "KR";
  // 👇 불어 추가 시 변경
  // return true; // 모든 국가에 표시
}

/**
 * 사용자 정보를 기반으로 언어를 결정합니다.
 *
 * @history
 * - 2024-10-19: 초기 구현 (한/영만 지원)
 * - 2024-11-XX: TODO - 불어 지원 추가 예정
 *
 * @caution
 * 현재 한국만 체크하고 나머지는 영어로 처리
 * 불어 추가 시 프랑스 조건 추가 필요
 */
export function getLanguage(
  user?: User,
  savedLanguage?: ReportLanguage
): Language {
  if (savedLanguage) return savedLanguage;

  if (user?.country === "KR") return "kr";
  // 👇 불어 추가 시 추가
  // if (user?.country === "FR") return "fr";

  return "en";
}

/**
 * 언어 코드에 맞는 템플릿 데이터를 반환합니다.
 *
 * @history
 * - 2024-10-19: 초기 구현 (한/영만 지원)
 * - 2024-11-XX: TODO - 불어 템플릿 추가 예정
 *
 * @caution
 * frenchTemplate 준비 후 case "fr" 추가 필요
 */
export function getTemplateByLanguage(language: ReportLanguage) {
  switch (language) {
    case "kr": return koreanTemplate;
    case "en": return englishTemplate;
    // 👇 불어 추가 시 추가
    // case "fr": return frenchTemplate;
    default: return englishTemplate;
  }
}

Before vs After

Before: 15개 파일에 하드코딩 산재

// ❌ 파일마다 임시 하드코딩
const language = user?.country === "KR" ? "kr" : "en";
// TODO: 불어 추가 시 수정

After: 함수 안에 하드코딩 집중

// ✅ 모든 파일에서 함수 호출
const language = getLanguage(user, savedLanguage);

// 하드코딩은 함수 안에만 있어 코드 이해에 방해되지 않음
// 불어 추가할 때 함수 5개만 고치면 끝

1달 뒤, 불어 일괄 반영하기

백엔드 API 준비됐고 불어 추가할 때가 왔습니다.
순수 함수로 모아뒀으니까 5개 함수만 고치면 됩니다.

// 1. 타입 정의
export type Language = "kr" | "en" | "fr";

// 2. 언어 옵션
export const AVAILABLE_LANGUAGES = [
  { label: "Korean", value: "kr" },
  { label: "English", value: "en" },
  { label: "French", value: "fr" }  // ✅ 주석 해제
];

// 3. UI 표시 조건
export function shouldShowLanguageSetting(userCountry?: string): boolean {
  return true; // ✅ 모든 국가 표시
}

// 4. 언어 결정 로직
export function getLanguage(user?: User, savedLanguage?: Language): Language {
  if (savedLanguage) return savedLanguage;
  if (user?.country === "KR") return "kr";
  if (user?.country === "FR") return "fr"; // ✅ 추가
  return "en";
}

// 5. 템플릿 데이터
export function getTemplateByLanguage(language: Language) {
  switch (language) {
    case "kr": return koreanTemplate;
    case "en": return englishTemplate;
    case "fr": return frenchTemplate; // ✅ 추가
    default: return englishTemplate;
  }
}

// 6. 컨텐츠 데이터
export function getContentByLanguage(language: Language) {
  switch (language) {
    case "kr": return koreanContent;
    case "en": return englishContent;
    case "fr": return frenchContent; // ✅ 추가
    default: return englishContent;
  }
}

15개 파일 찾아다니며 수정5개 함수만 수정

타입스크립트가 알아서 체크해 줌

만약 switch문에서 case "fr" 빼먹었으면?

function getTemplateByLanguage(language: Language) {
  switch (language) {
    case "kr": return koreanTemplate;
    case "en": return englishTemplate;
    // ❌ Error
  }
}

컴파일할 때 에러 뜹니다. TODO 주석은 안 봐도 그만이지만 타입 에러는 무시 못하죠.

결론

TODO 주석, jira 백로그는 그냥 메모지만 타입과 함수는 실제로 돌아가는 명세서 입니다.
1달 뒤 불어 리포트 일괄 반영할 때 실수 하고 싶어도 못하게 될 것입니다!

profile

뱁새 다리찢기

@donghyk2-eric

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!