Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough앱에 다국어(Language) 컨텍스트를 추가해 AppContent를 LanguageProvider로 감싸고 로컬스토리지 기반 언어 초기화/저장을 도입했으며, 여러 UI 컴포넌트에 번역 훅과 시간 포맷을 적용하고 버스 위치 폴링을 20s → 5s로 단축하고 일부 오버레이/버튼 스타일을 조정했습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App
participant LangProv as LanguageProvider
participant Comp as Component
participant API as BusAPI
User->>App: 언어 선택 / 설정 열기
App->>LangProv: language, setLanguage 전달
LangProv->>LangProv: t(key), formatTime 제공
LangProv->>Comp: AppContent 렌더링 (컨텍스트 사용 가능)
Note over Comp: 컴포넌트에서 useTranslation() 호출
Comp->>LangProv: t(key) / formatTime 호출
LangProv-->>Comp: 번역 문자열 / 포맷된 시간 반환
Comp->>User: 번역된 UI 렌더링
loop 폴링(5s)
App->>API: useBusLocations 요청 (refetchInterval=5000ms)
API-->>App: 최신 버스 위치 응답
App->>Comp: 위치 업데이트 렌더링
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
시
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/App.tsx (1)
38-46: 타입 안전성을 개선하기 위해 language 상태의 타입을 명시하세요.현재
language상태가string타입으로 선언되어 있고, LanguageProvider에 전달할 때"ko" | "en"으로 캐스팅하고 있습니다. 이는 런타임에 유효하지 않은 언어 값이 저장될 수 있는 타입 안전성 문제를 야기할 수 있습니다.Based on learnings (사용자는 TypeScript에서 타입 안전한 코드를 선호합니다).
다음과 같이 수정하는 것을 권장합니다:
+type Language = "ko" | "en"; + function App() { const mapId = useId(); const langId = useId(); - const [language, setLanguage] = useState(() => { + const [language, setLanguage] = useState<Language>(() => { try { + const stored = typeof window !== "undefined" && window.localStorage + ? localStorage.getItem("wtb:lang") + : null; - return typeof window !== "undefined" && window.localStorage - ? (localStorage.getItem("wtb:lang") ?? "ko") - : "ko"; + return stored === "en" ? "en" : "ko"; } catch { return "ko"; } });그리고 LanguageProvider 사용 시 캐스팅 제거:
<LanguageProvider - language={language as "ko" | "en"} + language={language} setLanguage={setLanguage} >Also applies to: 67-69
🧹 Nitpick comments (2)
src/components/SettingsPanel.tsx (1)
106-115: 레이블과 링크 텍스트에 서로 다른 번역 키를 사용하는 것을 고려하세요.라인 106과 114 모두 동일한 번역 키
"settings.contact"를 사용하고 있습니다. 향후 레이블과 링크 텍스트를 다르게 표시하고 싶을 수 있으므로, 별도의 키를 사용하는 것이 좋습니다.다음과 같이 수정할 수 있습니다:
<div style={{ fontSize: 14, color: "#111827" }}> {t("settings.contact")} </div> <a href="https://forms.gle/your-google-form-id" target="_blank" rel="noopener noreferrer" style={{ color: "#0ea5e9", textDecoration: "none" }} > - {t("settings.contact")} + {t("settings.contactLink")} </a>그리고 LanguageContext.tsx에 번역 추가:
"settings.contactLink": "문의하기", // ko "settings.contactLink": "Contact Us", // ensrc/components/Bubble.tsx (1)
151-151: 하드코딩된 시간 텍스트를 번역 키로 변경하는 것을 고려하세요."5min"과 "15min" 텍스트가 하드코딩되어 있어, 다른 UI 요소들이 번역되는 것과 일관성이 없습니다. 다국어 지원을 위해 번역 시스템을 사용하는 것이 좋습니다.
예를 들어:
- | 5min + | {t("common.minutes", { count: 5 })}그리고 LanguageContext.tsx에 다음을 추가:
// ko "common.minutes": "{{count}}분 남음", // en "common.minutes": "{{count}}min",또는 더 간단하게 분 단위만 번역:
// ko "common.min": "분 남음", // en "common.min": "min",Also applies to: 179-179
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/App.tsx(2 hunks)src/api/bus.ts(1 hunks)src/components/Bubble.tsx(7 hunks)src/components/BusStops.tsx(6 hunks)src/components/SettingsButton.tsx(1 hunks)src/components/SettingsPanel.tsx(8 hunks)src/contexts/LanguageContext.tsx(1 hunks)src/utils/mapOverlays.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (4)
src/components/Bubble.tsx (1)
src/contexts/LanguageContext.tsx (1)
useTranslation(101-107)
src/components/SettingsPanel.tsx (1)
src/contexts/LanguageContext.tsx (1)
useTranslation(101-107)
src/App.tsx (1)
src/contexts/LanguageContext.tsx (1)
LanguageProvider(85-99)
src/components/BusStops.tsx (1)
src/contexts/LanguageContext.tsx (1)
useTranslation(101-107)
🪛 GitHub Check: Build and Test
src/contexts/LanguageContext.tsx
[warning] 101-101:
Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
🔇 Additional comments (8)
src/utils/mapOverlays.ts (1)
1-1: LGTM!import 문의 위치 조정만 있으며, 기능적인 변경사항은 없습니다.
src/components/BusStops.tsx (1)
4-4: LGTM!번역 시스템이 올바르게 적용되었습니다. useTranslation 훅을 사용하여 UI 텍스트와 정류장 이름을 현지화하고 있습니다.
Also applies to: 22-22, 106-106, 138-138, 173-173
src/components/Bubble.tsx (1)
60-70: LGTM! 번역 로직이 올바르게 구현되었습니다.정류장 이름과 방향 정보를 번역하는 로직이 잘 구현되었고, useEffect의 의존성 배열에
t를 추가한 것도 적절합니다.Also applies to: 240-240
src/contexts/LanguageContext.tsx (3)
10-67: 번역 데이터 구조가 잘 설계되었습니다.번역 객체가 체계적으로 구성되어 있고, 한국어와 영어 모두에 대해 필요한 모든 키가 정의되어 있습니다. 정류장 이름, UI 레이블, 공통 메시지 등이 명확하게 분류되어 있습니다.
85-99: LGTM! LanguageProvider 구현이 올바릅니다.번역 함수
t가 적절하게 구현되어 있으며, 존재하지 않는 키에 대한 폴백 처리도 잘 되어 있습니다.
101-107: Fast Refresh 경고는 Context 파일에서는 무시해도 됩니다.정적 분석 도구가 컴포넌트가 아닌 항목(useTranslation 훅)을 내보내는 것에 대해 경고하고 있지만, Context 및 훅 파일에서는 이것이 표준 패턴입니다. 이 경고는 무시해도 안전합니다.
원한다면 훅과 Provider를 별도 파일로 분리할 수 있지만, 현재 구조도 일반적이고 허용됩니다.
src/components/SettingsButton.tsx (1)
22-23: SettingsButton의 z-index 감소로 인한 레이어 순서 변경 확인 필요확인 결과, 프로젝트의 모든 z-index 값은 다음과 같습니다:
- BusStopsPanel: 50
- SettingsButton: 1000 (변경됨)
- Bubble: 1001, 10001
- use-toast: 9999
- SettingsPanel: 10000
SettingsButton의 z-index가 10000에서 1000으로 변경되면서 SettingsPanel(10000)과의 레이어 관계가 역전되었습니다. 이 변경이 의도된 것인지, 그리고 두 컴포넌트가 동시에 표시될 때 올바른 순서로 렌더링되는지 확인하세요.
src/api/bus.ts (1)
13-13: 폴링 주기 변경 검증 완료 — 개발팀의 백엔드 영향 평가 확인 요청변경 사항 검증 결과:
- 폴링 간격 변경 확인됨: 20초 → 5초 (4배 빈도 증가) ✓
- 실시간 버스 위치 조회 애플리케이션 목적 확인: README에 "실시간 위치 조회" 명시
- 의도적 리팩토링: 커밋 메시지 "refactor: 폴링 주기 5000으로 수정"
현재 코드베이스에서 백엔드 용량 평가, API 비용 분석, 또는 성능 테스트 결과에 관한 문서를 찾을 수 없습니다. 실시간 버스 위치 추적 용도상 5초 폴링이 필요할 수 있으나, 백엔드 시스템이 이 증가된 요청 빈도를 처리할 수 있는지 개발팀이 검토하고 확인했는지 확인해주세요.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/components/SettingsPanel.tsx (1)
4-4: Language 타입 중복 정의
Language타입이 여러 파일에서 중복 정의되고 있습니다 (src/App.tsx, src/components/SettingsPanel.tsx). 타입 일관성과 유지보수성을 위해 src/contexts/LanguageContext.tsx에서 export하여 공유하는 것을 권장합니다.src/contexts/LanguageContext.tsx에 다음과 같이 export를 추가하세요:
-type Language = "ko" | "en"; +export type Language = "ko" | "en";그런 다음 이 파일에서 import하여 사용하세요:
+import { useTranslation, type Language } from "../contexts/LanguageContext"; -import { useTranslation } from "../contexts/LanguageContext"; - -type Language = "ko" | "en";src/contexts/LanguageContext.tsx (2)
10-67: 번역 데이터를 별도 파일로 분리하는 것을 고려하세요.translations 객체가 크고 계속 증가할 가능성이 있습니다. 유지보수성과 가독성 향상을 위해 별도의 파일(예:
src/locales/translations.ts)로 분리하는 것을 권장합니다.예시 구조:
src/locales/translations.ts:export const translations = { ko: { /* ... */ }, en: { /* ... */ } };그런 다음 이 파일에서 import:
import { translations } from "../locales/translations";
106-112: Fast refresh 경고 해결 고려정적 분석 도구가 지적한 것처럼, 이 파일은 컴포넌트(
LanguageProvider)와 훅(useTranslation)을 함께 export하고 있어 React Fast Refresh가 제대로 작동하지 않을 수 있습니다.Based on learnings
개발 경험 개선을 위해 다음 중 하나를 고려하세요:
옵션 1: 훅을 별도 파일로 분리
// src/contexts/LanguageContext.tsx export function LanguageProvider({ ... }) { ... } // src/hooks/useTranslation.ts export function useTranslation() { ... }옵션 2: 현재 구조 유지
Fast refresh 이슈가 개발 중 실제로 문제가 되지 않는다면 현재 구조를 유지해도 됩니다. 이는 작은 context 파일에서는 일반적인 패턴입니다.어느 접근을 선호하시나요?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/App.tsx(3 hunks)src/components/Bubble.tsx(7 hunks)src/components/SettingsPanel.tsx(7 hunks)src/contexts/LanguageContext.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/Bubble.tsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (2)
src/components/SettingsPanel.tsx (1)
src/contexts/LanguageContext.tsx (1)
useTranslation(106-112)
src/App.tsx (1)
src/contexts/LanguageContext.tsx (1)
LanguageProvider(86-104)
🪛 GitHub Check: Build and Test
src/contexts/LanguageContext.tsx
[warning] 106-106:
Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
🔇 Additional comments (7)
src/App.tsx (3)
40-49: localStorage 초기화 로직이 안전하게 구현되었습니다.try-catch로 localStorage 접근 실패를 처리하고, 기본값을 "ko"로 설정하는 방어적 코딩이 잘 되어 있습니다.
54-62: 언어 변경 시 localStorage 동기화 확인언어가 변경될 때마다 localStorage에 저장하는 로직이 올바르게 구현되어 있습니다. 다만, 실제로 값이 변경되었을 때만 저장하도록 조건을 추가한 점이 좋습니다.
70-87: LanguageProvider 통합 확인LanguageProvider로 AppContent를 감싸고 있어 전역 언어 상태 관리가 가능합니다. DevTools도 Provider 내부에 위치하여 context에 접근할 수 있습니다.
src/components/SettingsPanel.tsx (2)
88-88: 타입 단언(type assertion)이 안전합니다.select 엘리먼트가 "ko"와 "en" 옵션만 가지고 있으므로,
as Language타입 단언이 안전합니다.
108-117: 번역 키 중복 사용 확인 필요line 108과 line 116에서 동일한 번역 키
"settings.contact"를 사용하고 있습니다. 라벨과 링크 텍스트가 같은 의도라면 문제없지만, 다른 텍스트가 필요한 경우 별도의 키(예:"settings.contactLink")를 사용하는 것이 좋습니다.src/contexts/LanguageContext.tsx (2)
91-93: 번역 fallback 로직이 적절합니다.번역 키를 찾지 못한 경우 키 자체를 반환하는 것은 디버깅과 개발 과정에서 누락된 번역을 쉽게 발견할 수 있게 해주는 합리적인 접근입니다.
95-97: formatTime 함수의 단순한 구현현재 구현은 단순하지만 충분히 작동합니다. 향후 더 복잡한 시간 형식(예: 시간/분, 복수형 처리 등)이 필요한 경우 국제화 라이브러리(예:
date-fns또는Intl.RelativeTimeFormat)를 고려해볼 수 있습니다.
src/contexts/LanguageContext.tsx
Outdated
| @@ -0,0 +1,112 @@ | |||
| import { createContext, type ReactNode, useContext } from "react"; | |||
|
|
|||
| type Language = "ko" | "en"; | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Language 타입을 export하여 공유하세요.
Language 타입이 여러 파일에서 중복 정의되고 있습니다. 이 타입을 export하여 다른 파일에서 import하도록 하면 타입 일관성을 유지할 수 있습니다.
다음과 같이 수정하세요:
-type Language = "ko" | "en";
+export type Language = "ko" | "en";📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| type Language = "ko" | "en"; | |
| export type Language = "ko" | "en"; |
🤖 Prompt for AI Agents
In src/contexts/LanguageContext.tsx around line 3, the Language type is
currently declared locally ("ko" | "en") and duplicated across the repo; export
this type from this file (e.g., export type Language = "ko" | "en") so other
modules can import it, and update/replace duplicate local declarations in other
files to import this exported Language type to ensure a single source of truth.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/SettingsPanel.tsx (1)
21-21: 접근성 레이블을 번역 가능하게 만들어야 합니다.
aria-label이 한국어로 하드코딩되어 있습니다. 영어 사용자가 스크린 리더를 사용할 때 한국어 레이블이 읽힙니다. 번역 키를 추가하고aria-label={t("settings.dialogLabel")}과 같이 사용하세요.동일한 문제가 Line 56의 닫기 버튼에도 적용됩니다.
🧹 Nitpick comments (1)
src/contexts/LanguageContext.tsx (1)
10-67: 번역 객체를 불변으로 만드는 것을 권장합니다.현재
translations객체는 변경 가능한 상태입니다. 런타임에 의도치 않은 수정을 방지하기 위해as const를 사용하거나Object.freeze()를 적용하는 것을 고려해보세요.-const translations: Translations = { +const translations = { ko: { // BusStops "busStops.selectStop": "버스 정류장 선택하기", ... }, en: { ... }, -}; +} as const satisfies Translations;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/App.tsx(3 hunks)src/components/SettingsPanel.tsx(7 hunks)src/contexts/LanguageContext.tsx(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (2)
src/App.tsx (1)
src/contexts/LanguageContext.tsx (2)
Language(3-3)LanguageProvider(86-104)
src/components/SettingsPanel.tsx (1)
src/contexts/LanguageContext.tsx (2)
Language(3-3)useTranslation(106-112)
🔇 Additional comments (8)
src/contexts/LanguageContext.tsx (3)
3-3: Language 타입이 올바르게 export되었습니다.과거 리뷰 피드백이 적절히 반영되었습니다. 이제 다른 파일에서 이 타입을 import하여 사용할 수 있습니다.
86-104: LGTM! LanguageProvider 구현이 적절합니다.컨텍스트 프로바이더가 올바르게 구현되었습니다:
- 번역 함수(
t)가 적절한 fallback을 제공합니다formatTime함수가 언어별 시간 포맷을 제공합니다- 타입이 안전하게 정의되어 있습니다
106-112: useTranslation 훅이 올바르게 구현되었습니다.컨텍스트 사용 여부를 적절히 검증하고 명확한 에러 메시지를 제공합니다.
src/App.tsx (3)
38-47: 언어 상태 초기화가 안전하게 구현되었습니다.localStorage 접근이 안전하게 처리되었고, 적절한 타입 검증과 폴백이 제공됩니다. 타입 안전성도 잘 유지되고 있습니다.
52-60: localStorage 동기화가 효율적으로 구현되었습니다.불필요한 쓰기를 방지하는 최적화와 적절한 에러 처리가 포함되어 있습니다.
68-86: LanguageProvider 통합이 올바르게 완료되었습니다.프로바이더가 적절한 위치에 배치되었고, 모든 props가 타입 안전하게 전달되고 있습니다.
src/components/SettingsPanel.tsx (2)
2-9: 타입 정의가 안전하게 구현되었습니다.
Language타입을 사용하여 props가 타입 안전하게 정의되었습니다. 이는 학습된 선호사항(any 타입 회피)에 부합합니다.Based on learnings
17-17: 번역 시스템이 일관되게 적용되었습니다.
useTranslation훅과t()함수가 모든 UI 문자열에 올바르게 적용되었습니다. Line 86의 타입 단언도 select 요소의 제한된 값으로 인해 안전합니다.Also applies to: 52-135
Summary by CodeRabbit
새로운 기능
개선 사항