95bef976a5
- 여러 문서의 내용을 업데이트하여 최신 정보를 반영하였습니다. - 컴포넌트 개발 가이드와 관련된 문서의 목차를 재구성하고, V2 및 Zod 레이아웃 시스템에 대한 내용을 추가하였습니다. - 화면 컴포넌트 개발 가이드를 개선하여 핵심 원칙과 패턴을 명확히 설명하였습니다. - 불필요한 문서 및 가이드를 삭제하고, 통합된 가이드를 통해 개발자들이 쉽게 참고할 수 있도록 하였습니다.
30 KiB
30 KiB
다국어 관리 시스템 개선 계획서
1. 개요
1.1 현재 시스템 분석
현재 ERP 시스템의 다국어 관리 시스템은 기본적인 기능은 갖추고 있으나 다음과 같은 한계점이 있습니다.
| 항목 | 현재 상태 | 문제점 |
|---|---|---|
| 회사별 다국어 | company_code 컬럼 존재하나 *(공통)만 사용 |
회사별 커스텀 번역 불가 |
| 언어 키 입력 | 수동 입력 (button.add 등) |
명명 규칙 불일치, 오타, 중복 위험 |
| 카테고리 분류 | 없음 (menu_name 텍스트만 존재) |
체계적 분류/검색 불가 |
| 권한 관리 | 없음 | 모든 사용자가 모든 키 수정 가능 |
| 조회 우선순위 | 없음 | 회사별 오버라이드 불가 |
1.2 개선 목표
- 회사별 다국어 오버라이드 시스템: 공통 키를 기본으로 사용하되, 회사별 커스텀 번역 지원
- 권한 기반 접근 제어: 공통 키는 최고 관리자만, 회사 키는 해당 회사만 수정
- 카테고리 기반 분류: 2단계 계층 구조로 체계적 분류
- 자동 키 생성: 카테고리 선택 + 의미 입력으로 규칙화된 키 자동 생성
- 실시간 중복 체크: 키 생성 시 중복 여부 즉시 확인
2. 데이터베이스 스키마 설계
2.1 신규 테이블: multi_lang_category (카테고리 마스터)
CREATE TABLE multi_lang_category (
category_id SERIAL PRIMARY KEY,
category_code VARCHAR(50) NOT NULL, -- BUTTON, FORM, MESSAGE 등
category_name VARCHAR(100) NOT NULL, -- 버튼, 폼, 메시지 등
parent_id INT4 REFERENCES multi_lang_category(category_id),
level INT4 DEFAULT 1, -- 1=대분류, 2=세부분류
key_prefix VARCHAR(50) NOT NULL, -- 키 생성용 prefix
description TEXT,
sort_order INT4 DEFAULT 0,
is_active CHAR(1) DEFAULT 'Y',
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50),
updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_by VARCHAR(50),
UNIQUE(category_code, COALESCE(parent_id, 0))
);
-- 인덱스
CREATE INDEX idx_lang_category_parent ON multi_lang_category(parent_id);
CREATE INDEX idx_lang_category_level ON multi_lang_category(level);
2.2 기존 테이블 수정: multi_lang_key_master
-- 카테고리 연결 컬럼 추가
ALTER TABLE multi_lang_key_master
ADD COLUMN category_id INT4 REFERENCES multi_lang_category(category_id);
-- 키 의미 컬럼 추가 (자동 생성 시 사용자 입력값)
ALTER TABLE multi_lang_key_master
ADD COLUMN key_meaning VARCHAR(100);
-- 원본 키 참조 (오버라이드 시 원본 추적)
ALTER TABLE multi_lang_key_master
ADD COLUMN base_key_id INT4 REFERENCES multi_lang_key_master(key_id);
-- menu_name을 usage_note로 변경 (사용 위치 메모)
ALTER TABLE multi_lang_key_master
RENAME COLUMN menu_name TO usage_note;
-- 인덱스 추가
CREATE INDEX idx_lang_key_category ON multi_lang_key_master(category_id);
CREATE INDEX idx_lang_key_company_category ON multi_lang_key_master(company_code, category_id);
CREATE INDEX idx_lang_key_base ON multi_lang_key_master(base_key_id);
2.3 테이블 관계도
multi_lang_category (1) ◀────────┐
├── category_id (PK) │
├── category_code │
├── parent_id (자기참조) │
└── key_prefix │
│
multi_lang_key_master (N) ────────┘
├── key_id (PK)
├── company_code ('*' = 공통)
├── category_id (FK)
├── lang_key (자동 생성)
├── key_meaning (사용자 입력)
├── base_key_id (오버라이드 시 원본)
└── usage_note (사용 위치 메모)
│
▼
multi_lang_text (N)
├── text_id (PK)
├── key_id (FK)
├── lang_code (FK → language_master)
└── lang_text
3. 카테고리 체계
3.1 대분류 (Level 1)
| category_code | category_name | key_prefix | 설명 |
|---|---|---|---|
| COMMON | 공통 | common | 범용 텍스트 |
| BUTTON | 버튼 | button | 버튼 텍스트 |
| FORM | 폼 | form | 폼 라벨, 플레이스홀더 |
| TABLE | 테이블 | table | 테이블 헤더, 빈 상태 |
| MESSAGE | 메시지 | message | 알림, 경고, 성공 메시지 |
| MENU | 메뉴 | menu | 메뉴명, 네비게이션 |
| MODAL | 모달 | modal | 모달/다이얼로그 |
| VALIDATION | 검증 | validation | 유효성 검사 메시지 |
| STATUS | 상태 | status | 상태 표시 텍스트 |
| TOOLTIP | 툴팁 | tooltip | 툴팁, 도움말 |
3.2 세부분류 (Level 2)
BUTTON 하위
| category_code | category_name | key_prefix |
|---|---|---|
| ACTION | 액션 | action |
| NAVIGATION | 네비게이션 | nav |
| TOGGLE | 토글 | toggle |
FORM 하위
| category_code | category_name | key_prefix |
|---|---|---|
| LABEL | 라벨 | label |
| PLACEHOLDER | 플레이스홀더 | placeholder |
| HELPER | 도움말 | helper |
MESSAGE 하위
| category_code | category_name | key_prefix |
|---|---|---|
| SUCCESS | 성공 | success |
| ERROR | 에러 | error |
| WARNING | 경고 | warning |
| INFO | 안내 | info |
| CONFIRM | 확인 | confirm |
TABLE 하위
| category_code | category_name | key_prefix |
|---|---|---|
| HEADER | 헤더 | header |
| EMPTY | 빈 상태 | empty |
| PAGINATION | 페이지네이션 | pagination |
MENU 하위
| category_code | category_name | key_prefix |
|---|---|---|
| ADMIN | 관리자 | admin |
| USER | 사용자 | user |
MODAL 하위
| category_code | category_name | key_prefix |
|---|---|---|
| TITLE | 제목 | title |
| DESCRIPTION | 설명 | description |
3.3 키 자동 생성 규칙
형식: {대분류_prefix}.{세부분류_prefix}.{key_meaning}
예시:
| 대분류 | 세부분류 | 의미 입력 | 생성 키 |
|---|---|---|---|
| BUTTON | ACTION | save | button.action.save |
| BUTTON | ACTION | delete_selected | button.action.delete_selected |
| FORM | LABEL | user_name | form.label.user_name |
| FORM | PLACEHOLDER | search | form.placeholder.search |
| MESSAGE | SUCCESS | save_complete | message.success.save_complete |
| MESSAGE | ERROR | network_fail | message.error.network_fail |
| TABLE | HEADER | created_date | table.header.created_date |
| MENU | ADMIN | user_management | menu.admin.user_management |
4. 회사별 다국어 시스템
4.1 조회 우선순위
다국어 텍스트 조회 시 다음 우선순위를 적용합니다:
- 회사 전용 키 (
company_code = 'COMPANY_A') - 공통 키 (
company_code = '*')
-- 조회 쿼리 예시
WITH ranked_keys AS (
SELECT
km.lang_key,
mt.lang_text,
km.company_code,
ROW_NUMBER() OVER (
PARTITION BY km.lang_key
ORDER BY CASE WHEN km.company_code = $1 THEN 1 ELSE 2 END
) as priority
FROM multi_lang_key_master km
JOIN multi_lang_text mt ON km.key_id = mt.key_id
WHERE km.lang_key = ANY($2)
AND mt.lang_code = $3
AND km.is_active = 'Y'
AND km.company_code IN ($1, '*')
)
SELECT lang_key, lang_text
FROM ranked_keys
WHERE priority = 1;
4.2 오버라이드 프로세스
- 회사 관리자가 공통 키에서 "이 회사 전용으로 복사" 클릭
- 시스템이
base_key_id에 원본 키를 참조하는 새 키 생성 - 기존 번역 텍스트 복사
- 회사 관리자가 번역 수정
- 이후 해당 회사 사용자는 회사 전용 번역 사용
4.3 권한 매트릭스
| 작업 | 최고 관리자 (*) |
회사 관리자 | 일반 사용자 |
|---|---|---|---|
| 공통 키 조회 | O | O | O |
| 공통 키 생성 | O | X | X |
| 공통 키 수정 | O | X | X |
| 공통 키 삭제 | O | X | X |
| 회사 키 조회 | O | 자사만 | 자사만 |
| 회사 키 생성 (오버라이드) | O | O | X |
| 회사 키 수정 | O | 자사만 | X |
| 회사 키 삭제 | O | 자사만 | X |
| 카테고리 관리 | O | X | X |
5. API 설계
5.1 카테고리 API
| 엔드포인트 | 메서드 | 설명 | 권한 |
|---|---|---|---|
/multilang/categories |
GET | 카테고리 목록 조회 | 인증 필요 |
/multilang/categories/tree |
GET | 계층 구조로 조회 | 인증 필요 |
/multilang/categories |
POST | 카테고리 생성 | 최고 관리자 |
/multilang/categories/:id |
PUT | 카테고리 수정 | 최고 관리자 |
/multilang/categories/:id |
DELETE | 카테고리 삭제 | 최고 관리자 |
5.2 다국어 키 API (개선)
| 엔드포인트 | 메서드 | 설명 | 권한 |
|---|---|---|---|
/multilang/keys |
GET | 키 목록 조회 (카테고리/회사 필터) | 인증 필요 |
/multilang/keys |
POST | 키 생성 | 공통: 최고관리자, 회사: 회사관리자 |
/multilang/keys/:keyId |
PUT | 키 수정 | 공통: 최고관리자, 회사: 해당회사 |
/multilang/keys/:keyId |
DELETE | 키 삭제 | 공통: 최고관리자, 회사: 해당회사 |
/multilang/keys/:keyId/override |
POST | 공통 키를 회사 전용으로 복사 | 회사 관리자 |
/multilang/keys/check |
GET | 키 중복 체크 | 인증 필요 |
/multilang/keys/generate-preview |
POST | 키 자동 생성 미리보기 | 인증 필요 |
5.3 API 요청/응답 예시
키 생성 요청
POST /multilang/keys
{
"categoryId": 11, // 세부분류 ID (BUTTON > ACTION)
"keyMeaning": "save_changes",
"description": "변경사항 저장 버튼",
"usageNote": "사용자 관리, 설정 화면",
"texts": [
{ "langCode": "KR", "langText": "저장하기" },
{ "langCode": "US", "langText": "Save Changes" },
{ "langCode": "JP", "langText": "保存する" }
]
}
키 생성 응답
{
"success": true,
"message": "다국어 키가 생성되었습니다.",
"data": {
"keyId": 175,
"langKey": "button.action.save_changes",
"companyCode": "*",
"categoryId": 11
}
}
오버라이드 요청
POST /multilang/keys/123/override
{
"texts": [
{ "langCode": "KR", "langText": "등록하기" },
{ "langCode": "US", "langText": "Register" }
]
}
6. 프론트엔드 UI 설계
6.1 다국어 관리 페이지 리뉴얼
┌─────────────────────────────────────────────────────────────────────────┐
│ 다국어 관리 │
│ 다국어 키와 번역 텍스트를 관리합니다 │
├─────────────────────────────────────────────────────────────────────────┤
│ [언어 관리] [다국어 키 관리] [카테고리 관리] │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────┐ ┌───────────────────────────────────────────────┤
│ │ 카테고리 필터 │ │ │
│ │ │ │ 검색: [________________] 회사: [전체 ▼] │
│ │ ▼ 버튼 (45) │ │ [초기화] [+ 키 등록] │
│ │ ├ 액션 (30) │ │───────────────────────────────────────────────│
│ │ ├ 네비게이션 (10)│ │ ☐ │ 키 │ 카테고리 │ 회사 │ 상태 │
│ │ └ 토글 (5) │ │───────────────────────────────────────────────│
│ │ ▼ 폼 (60) │ │ ☐ │ button.action.save │ 버튼>액션 │ 공통 │ 활성 │
│ │ ├ 라벨 (35) │ │ ☐ │ button.action.save │ 버튼>액션 │ A사 │ 활성 │
│ │ ├ 플레이스홀더(15)│ │ ☐ │ button.action.delete │ 버튼>액션 │ 공통 │ 활성 │
│ │ └ 도움말 (10) │ │ ☐ │ form.label.user_name │ 폼>라벨 │ 공통 │ 활성 │
│ │ ▶ 메시지 (40) │ │───────────────────────────────────────────────│
│ │ ▶ 테이블 (20) │ │ 페이지: [1] [2] [3] ... [10] │
│ │ ▶ 메뉴 (9) │ │ │
│ └────────────────────┘ └───────────────────────────────────────────────┤
└─────────────────────────────────────────────────────────────────────────┘
6.2 키 등록 모달
┌─────────────────────────────────────────────────────────────────┐
│ 다국어 키 등록 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ① 카테고리 선택 │
│ ┌───────────────────────────────────────────────────────────────┤
│ │ 대분류 * │ 세부 분류 * │
│ │ ┌─────────────────────────┐ │ ┌─────────────────────────┐ │
│ │ │ 공통 │ │ │ (대분류 먼저 선택) │ │
│ │ │ ● 버튼 │ │ │ ● 액션 │ │
│ │ │ 폼 │ │ │ 네비게이션 │ │
│ │ │ 테이블 │ │ │ 토글 │ │
│ │ │ 메시지 │ │ │ │ │
│ │ └─────────────────────────┘ │ └─────────────────────────┘ │
│ └───────────────────────────────────────────────────────────────┤
│ │
│ ② 키 정보 입력 │
│ ┌───────────────────────────────────────────────────────────────┤
│ │ 키 의미 (영문) * │
│ │ [ save_changes ] │
│ │ 영문 소문자, 밑줄(_) 사용. 예: save, add_new, delete_all │
│ │ │
│ │ ───────────────────────────────────────────────────────── │
│ │ 자동 생성 키: │
│ │ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ button.action.save_changes │ │
│ │ └─────────────────────────────────────────────────────────┘ │
│ │ ✓ 사용 가능한 키입니다 │
│ └───────────────────────────────────────────────────────────────┤
│ │
│ ③ 설명 및 번역 │
│ ┌───────────────────────────────────────────────────────────────┤
│ │ 설명 (선택) │
│ │ [ 변경사항을 저장하는 버튼 ] │
│ │ │
│ │ 사용 위치 메모 (선택) │
│ │ [ 사용자 관리, 설정 화면 ] │
│ │ │
│ │ ───────────────────────────────────────────────────────── │
│ │ 번역 텍스트 │
│ │ │
│ │ 한국어 (KR) * [ 저장하기 ] │
│ │ English (US) [ Save Changes ] │
│ │ 日本語 (JP) [ 保存する ] │
│ └───────────────────────────────────────────────────────────────┤
│ │
├─────────────────────────────────────────────────────────────────┤
│ [취소] [등록] │
└─────────────────────────────────────────────────────────────────┘
6.3 공통 키 편집 모달 (회사 관리자용)
┌─────────────────────────────────────────────────────────────────┐
│ 다국어 키 상세 │
│ button.action.save (공통) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 카테고리: 버튼 > 액션 │
│ 설명: 저장 버튼 │
│ │
│ ───────────────────────────────────────────────────────────── │
│ 번역 텍스트 (읽기 전용) │
│ │
│ 한국어 (KR) 저장 │
│ English (US) Save │
│ 日本語 (JP) 保存 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ 공통 키는 수정할 수 없습니다. │
│ 이 회사만의 번역이 필요하시면 아래 버튼을 클릭하세요. │
│ │
│ [이 회사 전용으로 복사] │
├─────────────────────────────────────────────────────────────────┤
│ [닫기] │
└─────────────────────────────────────────────────────────────────┘
6.4 회사 전용 키 생성 모달 (오버라이드)
┌─────────────────────────────────────────────────────────────────┐
│ 회사 전용 키 생성 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 원본 키: button.action.save (공통) │
│ │
│ 원본 번역: │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 한국어: 저장 │ │
│ │ English: Save │ │
│ │ 日本語: 保存 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ───────────────────────────────────────────────────────────── │
│ │
│ 이 회사 전용 번역 텍스트: │
│ │
│ 한국어 (KR) * [ 등록하기 ] │
│ English (US) [ Register ] │
│ 日本語 (JP) [ 登録 ] │
│ │
├─────────────────────────────────────────────────────────────────┤
│ 회사 전용 키를 생성하면 공통 키 대신 사용됩니다. │
│ 원본 키가 변경되어도 회사 전용 키는 영향받지 않습니다. │
├─────────────────────────────────────────────────────────────────┤
│ [취소] [생성] │
└─────────────────────────────────────────────────────────────────┘
7. 구현 계획
7.1 Phase 1: 데이터베이스 마이그레이션
예상 소요 시간: 2시간
- 카테고리 테이블 생성
- 기본 카테고리 데이터 삽입 (대분류 10개, 세부분류 약 20개)
- multi_lang_key_master 스키마 변경
- 기존 174개 키 카테고리 자동 분류 (패턴 매칭)
마이그레이션 파일: db/migrations/075_multilang_category_system.sql
7.2 Phase 2: 백엔드 API 개발
예상 소요 시간: 4시간
- 카테고리 CRUD API
- 키 조회 로직 수정 (우선순위 적용)
- 권한 검사 미들웨어
- 오버라이드 API
- 키 중복 체크 API
- 키 자동 생성 미리보기 API
관련 파일:
backend-node/src/controllers/multilangController.tsbackend-node/src/services/multilangService.tsbackend-node/src/routes/multilangRoutes.ts
7.3 Phase 3: 프론트엔드 UI 개발
예상 소요 시간: 6시간
- 카테고리 트리 컴포넌트
- 키 등록 모달 리뉴얼 (단계별 입력)
- 키 편집 모달 (권한별 UI 분기)
- 오버라이드 모달
- 카테고리 관리 탭 추가
관련 파일:
frontend/app/(main)/admin/systemMng/i18nList/page.tsxfrontend/components/multilang/LangKeyModal.tsx(리뉴얼)frontend/components/multilang/CategoryTree.tsx(신규)frontend/components/multilang/OverrideModal.tsx(신규)
7.4 Phase 4: 테스트 및 마이그레이션
예상 소요 시간: 2시간
- API 테스트
- UI 테스트
- 기존 데이터 마이그레이션 검증
- 권한 테스트 (최고 관리자, 회사 관리자)
8. 상세 구현 일정
| 단계 | 작업 | 예상 시간 | 의존성 |
|---|---|---|---|
| 1.1 | 마이그레이션 SQL 작성 | 30분 | - |
| 1.2 | 카테고리 기본 데이터 삽입 | 30분 | 1.1 |
| 1.3 | 기존 키 카테고리 자동 분류 | 30분 | 1.2 |
| 1.4 | 스키마 변경 검증 | 30분 | 1.3 |
| 2.1 | 카테고리 API 개발 | 1시간 | 1.4 |
| 2.2 | 키 조회 로직 수정 (우선순위) | 1시간 | 2.1 |
| 2.3 | 권한 검사 로직 추가 | 30분 | 2.2 |
| 2.4 | 오버라이드 API 개발 | 1시간 | 2.3 |
| 2.5 | 키 생성 API 개선 (자동 생성) | 30분 | 2.4 |
| 3.1 | 카테고리 트리 컴포넌트 | 1시간 | 2.5 |
| 3.2 | 키 등록 모달 리뉴얼 | 2시간 | 3.1 |
| 3.3 | 키 편집/상세 모달 | 1시간 | 3.2 |
| 3.4 | 오버라이드 모달 | 1시간 | 3.3 |
| 3.5 | 카테고리 관리 탭 | 1시간 | 3.4 |
| 4.1 | 통합 테스트 | 1시간 | 3.5 |
| 4.2 | 버그 수정 및 마무리 | 1시간 | 4.1 |
총 예상 시간: 약 14시간
9. 기대 효과
9.1 개선 전후 비교
| 항목 | 현재 | 개선 후 |
|---|---|---|
| 키 명명 규칙 | 불규칙 (수동 입력) | 규칙화 (자동 생성) |
| 카테고리 분류 | 없음 | 2단계 계층 구조 |
| 회사별 다국어 | 미활용 | 오버라이드 지원 |
| 조회 우선순위 | 없음 | 회사 전용 > 공통 |
| 권한 관리 | 없음 | 역할별 접근 제어 |
| 중복 체크 | 저장 시에만 | 실시간 검증 |
| 검색/필터 | 키 이름만 | 카테고리 + 회사 + 키 |
9.2 사용자 경험 개선
- 일관된 키 명명: 자동 생성으로 규칙 준수
- 빠른 검색: 카테고리 기반 필터링
- 회사별 커스터마이징: 브랜드에 맞는 번역 사용
- 안전한 수정: 권한 기반 보호
9.3 유지보수 개선
- 체계적 분류: 어떤 텍스트가 어디에 사용되는지 명확
- 변경 영향 파악: 오버라이드 추적으로 영향 범위 확인
- 권한 분리: 공통 키 보호, 회사별 자율성 보장
10. 참고 자료
10.1 관련 파일
| 파일 | 설명 |
|---|---|
frontend/hooks/useMultiLang.ts |
다국어 훅 |
frontend/lib/utils/multilang.ts |
다국어 유틸리티 |
frontend/app/(main)/admin/systemMng/i18nList/page.tsx |
다국어 관리 페이지 |
backend-node/src/controllers/multilangController.ts |
API 컨트롤러 |
backend-node/src/services/multilangService.ts |
비즈니스 로직 |
docs/다국어_시스템_가이드.md |
기존 시스템 가이드 |
10.2 데이터베이스 테이블
| 테이블 | 설명 |
|---|---|
language_master |
언어 마스터 (KR, US, JP) |
multi_lang_key_master |
다국어 키 마스터 |
multi_lang_text |
다국어 번역 텍스트 |
multi_lang_category |
다국어 카테고리 (신규) |
11. 변경 이력
| 버전 | 날짜 | 작성자 | 변경 내용 |
|---|---|---|---|
| 1.0 | 2026-01-13 | AI | 최초 작성 |