프로젝트 내 다국어(i18n)를 관리하다 보면, 기능이 변경되거나 삭제될 때마다 사용하지 않는 번역 키가 남게 됩니다.
이번에는 WiniLogis 프로젝트에서 점점 쌓여가던 불필요한 다국어 키를 정리한 과정을 공유하려고 합니다.
❗️ 문제 상황
WiniLogis에서는 Google Cloud Sheet를 기반으로 다국어를 관리하고 있습니다. 개발 환경에서는 스크립트를 통해 Sheet에 작성된 다국어 데이터를 public/locales/{언어}/translation.json 형태로 변환하여 저장합니다.
public/
└─ locales/
├─ en/translation.json
├─ es/translation.json
└─ ru/translation.json
그러나 프로젝트가 커지고 여러 기능이 추가 및 삭제되면서, 점점 사용되지 않는 번역 키들이 누적되기 시작했습니다. 그 결과, Google Sheet에는 실제로 사용되지 않는 다국어가 계속 남게 되었습니다.
🔍 문제 분석
i18n 시스템 자체에는 “이 키가 실제로 사용 중인지”를 자동으로 알려주는 기능이 없습니다. 즉, 개발자가 직접 프로젝트 코드를 모두 뒤져서 확인해야 하는데, 이는 현실적으로 많이 힘들 것 같습니다.
그래서 다음과 같은 접근으로 문제를 해결하기로 했습니다:
- translation.json 파일에서 모든 다국어 키 추출
- src 폴더 내 모든 코드 파일을 탐색하며 해당 키가 실제로 사용되는지 확인
- 사용되지 않는 키만 별도로 출력하여 정리
✅ 해결 방법
이 과정을 최적화하기 위해, GitHub Copilot의 도움을 받아 사용되지 않는 i18n 키를 찾아주는 스크립트를 작성했습니다.
// 스크립트: 사용되지 않는 i18n 키 찾기
import fs from 'fs';
import path from 'path';
const LOCALES_DIR = './public/locales/en/translation.json';
// JSON 파일 읽기
const translationData = JSON.parse(fs.readFileSync(LOCALES_DIR, 'utf8'));
// 모든 키 추출 (중첩된 키도 점(.)으로 연결)
const getAllKeys = (obj, prefix = '') => {
let keys = [];
for (const key in obj) {
const fullKey = prefix ? `${prefix}.${key}` : key;
if (typeof obj[key] === 'object' && obj[key] !== null) {
keys = keys.concat(getAllKeys(obj[key], fullKey));
} else {
keys.push(fullKey);
}
}
return keys;
};
// src 폴더 내 재귀적으로 특정 확장자 파일 모두 찾기 (node_modules 제외)
const getFilesRecursive = (dir, extensions) => {
let results = [];
const list = fs.readdirSync(dir, { withFileTypes: true });
for (const file of list) {
const fullPath = path.join(dir, file.name);
if (file.isDirectory()) {
if (file.name === 'node_modules') continue;
results = results.concat(getFilesRecursive(fullPath, extensions));
} else {
if (extensions.includes(path.extname(file.name))) {
results.push(fullPath);
}
}
}
return results;
};
// 프로젝트 파일에서 특정 키가 사용 중인지 확인
const checkKeyUsage = (keyToCheck) => {
const files = getFilesRecursive('src', ['.ts', '.tsx', '.js', '.jsx']);
for (const file of files) {
try {
const content = fs.readFileSync(file, 'utf8');
// 다양한 패턴으로 키 사용 여부 체크
const patterns = [
`'${keyToCheck}'`,
`"${keyToCheck}"`,
`\`${keyToCheck}\``,
`t('${keyToCheck}')`,
`t("${keyToCheck}")`,
];
if (patterns.some((pattern) => content.includes(pattern))) {
return true; // 사용 중
}
} catch (error) {
console.error(`Error reading file ${file}:`, error.message);
}
}
return false; // 사용 안 함
};
// 메인 함수: 사용하지 않는 키 출력
const findUnusedKeys = () => {
const allKeys = getAllKeys(translationData);
const unusedKeys = [];
for (const key of allKeys) {
const isUsed = checkKeyUsage(key);
if (!isUsed) {
unusedKeys.push(key);
}
}
console.log('Unused i18n Keys:', unusedKeys.length);
unusedKeys.forEach((key) => console.log(key));
};
// 실행
findUnusedKeys();
💡 느낀 점
스크립트 실행 결과, 총 69개의 사용되지 않는 다국어 키를 발견했습니다.
이 키들은 Google Cloud Sheet에서도 동일하게 제거했으며, 이후 자동 동기화 스크립트를 다시 실행해 translation.json 파일이 정리된 상태로 유지되도록 했습니다.
GitHub Copilot 덕분에 반복적인 탐색 로직을 빠르게 작성할 수 있었고, 앞으로는 이 스크립트를 정기적으로 실행해 다국어 데이터를 항상 깨끗한 상태로 유지할 계획입니다.
'지식 정리 📝' 카테고리의 다른 글
| React i18n 다국어 처리 빌드 크기 최적화 2 (0) | 2025.12.30 |
|---|---|
| Autowini 프론트엔드 분리 프로젝트 CI/CD 파이프라인 구축 (Bitbucket 기반) 1 (1) | 2025.11.27 |
| Autowini WEB 통합 프로젝트 Vitest 테스트 시스템 도입 (1) | 2025.10.17 |
| 확장자는 JPG인데 Windows에서 열리지 않는 이미지 문제 해결한 방법 (0) | 2025.09.02 |
| iframe으로 인한 width 드래그 조절 문제 해결한 방법 (0) | 2025.08.22 |