Conversation
## Walkthrough
이번 변경에서는 프로젝트의 번역(i18n) 데이터 관리 방식을 개선하고, 라우트별로 필요한 번역 네임스페이스만 초기 렌더링 시 내려주도록 SSR 로직을 수정했습니다. 또한, 라우트 변수(네임스페이스) 관리를 중앙화하기 위해 상수 배열을 도입하였고, URL에 따라 필요한 네임스페이스를 동적으로 추출하는 유틸리티 함수가 추가되었습니다. README와 package.json의 일부 스크립트 및 문서도 함께 업데이트되었습니다.
## Changes
| 파일/경로 | 변경 요약 |
|-------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|
| README.md | 프로젝트 구조 설명에서 route.tsx를 routes/ 디렉터리로 변경 |
| package.json | "postinstall" 스크립트(npx prisma generate) 추가, scripts에 trailing comma 추가 |
| server/i18nNamespaces.ts | 번역 네임스페이스 상수 배열(I18N_APP_NAMESPACES) 추가 |
| server/i18n.ts, src/i18n.ts | i18next 초기화 시 네임스페이스를 상수 배열에서 동적으로 불러오도록 변경, 네임스페이스 preload |
| server/utils/getNameSpace.ts | URL 기반으로 필요한 번역 네임스페이스를 반환하는 getNameSpace 함수 신규 추가 |
| server/main.ts | SSR 시 getNameSpace로 필요한 네임스페이스만 내려주도록 변경, 에러 로깅 활성화 |
| .github/workflows/vitest.yml | CI 워크플로우에서 pnpm 대신 yarn 사용하도록 변경 |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant Client
participant Server
participant getNameSpace
participant i18n
Client->>Server: SSR 요청 (URL 포함)
Server->>getNameSpace: URL로 네임스페이스 추출
getNameSpace-->>Server: 필요한 네임스페이스 배열 반환
Server->>i18n: 해당 언어+네임스페이스 번역 데이터 준비
Server-->>Client: 필요한 번역 데이터만 포함된 SSR 응답Assessment against linked issues
Poem
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
package.json (1)
16-16: Prisma Client 자동 생성 스크립트 최적화 제안
postinstall단계에npx prisma generate를 추가하여 설치 후 자동으로 Prisma Client를 생성하도록 한 것은 적절합니다.
다만, 이 스크립트는 프로덕션 환경(Docker 빌드, CI/CD)에서도 실행되므로 불필요한 재생성으로 인한 성능 저하를 방지하기 위해 다음과 같은 보완을 고려해 보세요:
NODE_ENV !== 'production'조건 하에서만 실행- 혹은
prepare혹은build스크립트 단계로 이동server/main.ts (1)
153-156: 디버깅을 위한 로그 추가 적절함요청에 필요한 네임스페이스를 로그로 출력하는 것은 개발 중 디버깅에 도움이 됩니다. 다만, 프로덕션 환경에서는 이러한 로그를 조건부로 출력하거나 제거하는 것을 고려해 볼 수 있습니다.
- console.log('requiredNamespaces', requiredNamespaces) + if (process.env.NODE_ENV !== 'production') { + console.log('requiredNamespaces', requiredNamespaces) + }server/utils/getNameSpace.ts (1)
20-29: 동적 세그먼트를 와일드카드로 변환하는 정규식 로직이 잘 구현되어 있습니다.PATH에 정의된 경로 패턴을 정규식으로 변환하는 로직이 복잡할 수 있지만, 명확한 주석과 함께 잘 구현되어 있습니다. 하지만 이 정규식 변환 로직이 복잡해질 경우를 대비하여 별도의 유틸리티 함수로 분리하는 것도 고려해볼 수 있습니다.
다음과 같이 정규식 변환 로직을 분리하는 것을 고려해보세요:
+ /** + * 라우트 패턴을 정규식 패턴으로 변환합니다. + */ + function patternToRegex(pattern: string): RegExp { + return new RegExp( + '^' + + pattern + .replace(/:[^/]+/g, '[^/]+') + .replace(/\//g, '\\/') + + '$', + ) + } for (const [key, pattern] of routeEntries) { - // Replace ':xxx' dynamic segments with wildcard '[^/]+' - const regex = new RegExp( - '^' + - pattern - .replace(/:[^/]+/g, '[^/]+') // dynamic segment -> wildcard - .replace(/\//g, '\\/') + // escape '/' characters - '$', - ) + const regex = patternToRegex(pattern)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
README.md(1 hunks)package.json(1 hunks)server/i18n.ts(2 hunks)server/i18nNamespaces.ts(1 hunks)server/main.ts(3 hunks)server/utils/getNameSpace.ts(1 hunks)src/i18n.ts(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
server/i18n.ts (1)
server/i18nNamespaces.ts (1)
I18N_APP_NAMESPACES(1-7)
src/i18n.ts (1)
server/i18nNamespaces.ts (1)
I18N_APP_NAMESPACES(1-7)
server/main.ts (1)
server/utils/getNameSpace.ts (1)
getNameSpace(11-36)
server/utils/getNameSpace.ts (1)
src/routes/path.ts (1)
PATH(1-14)
🔇 Additional comments (16)
package.json (1)
15-15: 테스트 커버리지 스크립트 쉼표 추가 검토
"coverage": "vitest run --coverage",구문에 쉼표를 추가해 스크립트 간 구분을 명확히 한 것은 JSON 유효성 유지에 필요한 조치입니다.README.md (1)
56-56: 디렉토리 구조 업데이트 적절함프로젝트 디렉토리 구조에서 단일 파일
route.tsx가routes/디렉토리로 변경된 것이 README에 정확히 반영되었습니다. 이는 라우트 객체들이 이제 단일 파일이 아닌 폴더로 구성되어 관리된다는 것을 명확히 보여줍니다.server/i18nNamespaces.ts (1)
1-7: 국제화 네임스페이스 중앙화 구현 좋습니다네임스페이스를 상수 배열로 중앙화하여 관리하는 방식은 유지보수성을 높이는 좋은 접근법입니다.
as const사용으로 타입 안정성도 확보되었습니다. 이는 여러 파일에서 일관된 네임스페이스 참조를 가능하게 합니다.server/i18n.ts (2)
5-5: 중앙화된 네임스페이스 가져오기 적절함새로 생성된
I18N_APP_NAMESPACES상수를 가져와 사용하는 것은 국제화 관리를 중앙화하는 좋은 접근 방식입니다.
14-14: 하드코딩 제거 및 동적 네임스페이스 로딩 구현 좋습니다네임스페이스 배열을 하드코딩하는 대신
I18N_APP_NAMESPACES에서 동적으로 가져오는 방식으로 변경한 것은 일관성과 유지보수성을 높이는 훌륭한 개선입니다. 이를 통해 클라이언트와 서버 간 네임스페이스 동기화 오류를 방지할 수 있습니다.server/main.ts (3)
21-21: URL 기반 네임스페이스 결정 유틸리티 추가 적절함
getNameSpace유틸리티 함수를 가져오는 것은 URL 경로에 따라 필요한 번역 네임스페이스를 동적으로 결정하기 위한 좋은 접근 방식입니다.
96-96: 오류 로깅 활성화 적절함이전에 주석 처리되었던
console.error(error)호출을 활성화하는 것은 디버깅과 모니터링을 위해 중요합니다. 오류가 발생했을 때 로그를 남기는 것은 문제 해결에 도움이 됩니다.
151-162: 지연 로딩 구현으로 성능 최적화 좋습니다번역 데이터를 지연 로딩하는 방식으로 변경한 것은 훌륭한 최적화입니다. 이전에는 모든 번역 데이터를 한 번에 로드했지만, 이제는 현재 URL에 필요한 네임스페이스만 선택적으로 로드합니다. 이는 다음과 같은 이점이 있습니다:
- 초기 로딩 시간 단축
- 네트워크 트래픽 감소
- 메모리 사용량 최적화
getNameSpace함수와의 통합도 잘 이루어졌습니다.src/i18n.ts (3)
5-5: I18N_APP_NAMESPACES 임포트가 추가되었습니다.중앙화된 네임스페이스 배열을 통해 클라이언트와 서버 간의 일관된 설정을 보장하는 좋은 리팩토링입니다.
7-7: 주석이 명확하게 최초 렌더링 시 로드되는 네임스페이스를 설명합니다.주석이 코드 변경 사항을 정확히 반영하고 있어 이후 개발자가 이해하기 쉽습니다.
15-15:Details
✅ Verification successful
네임스페이스 목록에 I18N_APP_NAMESPACES가 추가되었습니다.
초기 렌더링 시 필요한 모든 네임스페이스를 포함하도록 설정이 개선되었습니다. 그러나 이렇게 하면 모든 페이지에서 모든 네임스페이스를 로드하게 되어 초기 번들 크기가 커질 수 있습니다.
🏁 Script executed:
#!/bin/bash # 초기 번들 크기에 미치는 영향을 확인하기 위해 번역 파일 크기 확인 echo "번역 파일 크기 확인:" fd -t f -e json "translation" public/locales -x du -h {}Length of output: 93
🏁 Script executed:
#!/bin/bash echo "번역 파일 크기 확인:" find public/locales -type f -name '*.json' -print0 | xargs -0 du -h | sort -h echo echo "Locale 별 총 크기:" for dir in public/locales/*; do if [ -d "$dir" ]; then total=$(find "$dir" -type f -name '*.json' -print0 | xargs -0 du -ch | tail -1) echo "$(basename "$dir"): $total" fi doneLength of output: 1694
번역 네임스페이스 로딩 크기 검증 결과
초기 렌더링 시 로드되는 네임스페이스 JSON 파일의 총 용량은 locale별로 최대 약 28 KB로, 번들 증가 폭이 크지 않은 것으로 확인되었습니다.• en: 24 KB
• ja: 8 KB
• ko: 28 KB
• zh: 8 KB필요 시 react-i18next의 loadNamespaces나 dynamic import를 활용해 네임스페이스를 페이지별로 로드하도록 최적화할 수 있습니다.
server/utils/getNameSpace.ts (5)
3-10: 함수에 대한 명확한 JSDoc 설명이 포함되어 있습니다.함수의 목적과 기능을 이해하기 쉽게 설명해주는 주석이 잘 작성되어 있습니다.
11-14: getNameSpace 함수의 기본 구조가 잘 설계되었습니다.URL을 입력으로 받아 필요한 네임스페이스 배열을 반환하는 함수의 기본 구조가 명확합니다. 기본 네임스페이스를 항상 포함하는 것도 좋은 접근법입니다.
15-19: PATH 객체에서 문자열 기반 경로만 필터링하는 로직이 효율적입니다.함수형 엔트리를 제외하고 문자열 경로만 필터링하는 로직이 잘 구현되어 있습니다. 타입 단언을 사용한 부분도 적절합니다.
30-33: 매칭된 경로에 대한 네임스페이스 반환 로직이 명확합니다.매칭된 경로가 있을 경우 해당 키를 소문자로 변환하여 네임스페이스로 사용하는 로직이 잘 구현되어 있습니다. Set을 사용해 중복을 제거하는 것도 좋은 접근법입니다.
35-36: 기본 폴백 네임스페이스 설정이 적절합니다.매칭되는 경로가 없을 경우 'home' 네임스페이스로 폴백하는 로직이 잘 구현되어 있습니다. Set을 사용해 중복을 제거하는 것이 일관되게 적용되어 있습니다.
다만, 매칭되지 않는 URL이 들어왔을 때의 로깅이나 모니터링도 고려해보면 좋을 것 같습니다.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/vitest.yml (1)
23-23: 고정된 록파일로 일관된 설치 보장
yarn install --frozen-lockfile로 록파일 변경 시 오류를 발생시켜 의존성 일관성을 확보하였습니다.
cache-dependency-path를 명시하여 캐시 유효성 검사 경로를 명확히 지정할 수 있습니다:with: node-version: '20' cache: 'yarn' + cache-dependency-path: 'yarn.lock'
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
.github/workflows/vitest.yml(1 hunks)README.md(4 hunks)package.json(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- README.md
- package.json
🔇 Additional comments (2)
.github/workflows/vitest.yml (2)
20-20: Yarn 캐시 설정으로 의존성 재사용 최적화
actions/setup-node v4의cache: 'yarn'옵션으로yarn.lock을 기반으로 자동으로 캐시가 관리됩니다.
26-26: 테스트 명령 실행 및 커버리지 경로 확인 요청
yarn test가 Vitest 실행 및 커버리지 수집(예:yarn test --coverage)을 포함하도록 설정되었는지, 그리고 결과물이coverage/디렉터리에 정상 생성되는지 확인해주세요.
Summary by CodeRabbit
문서화
Chores
신규 기능
버그 수정