Skip to content

feat: 언어 설정 영어 추가 및 폴링 주기 5초로 변경#29

Merged
KwonDeaGeun merged 4 commits intomainfrom
feat/language-add-English
Nov 12, 2025
Merged

feat: 언어 설정 영어 추가 및 폴링 주기 5초로 변경#29
KwonDeaGeun merged 4 commits intomainfrom
feat/language-add-English

Conversation

@KwonDeaGeun
Copy link
Owner

@KwonDeaGeun KwonDeaGeun commented Nov 12, 2025

Summary by CodeRabbit

  • 새로운 기능

    • 한국어/영어 전역 언어 지원 추가 — UI 텍스트와 시간 표기가 선택한 언어로 표시됩니다.
    • 언어 선택 상태가 저장되어 앱 재실행 시 유지됩니다.
  • 개선 사항

    • 버스 위치 갱신 빈도 증가로 실시간 정보 반응성 향상.
    • 오버레이 및 설정 버튼의 위치·레이어링 조정으로 레이아웃 안정성 개선.

@KwonDeaGeun KwonDeaGeun self-assigned this Nov 12, 2025
@vercel
Copy link

vercel bot commented Nov 12, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
what-the-bus-web Ready Ready Preview Comment Nov 12, 2025 5:18am

@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Walkthrough

앱에 다국어(Language) 컨텍스트를 추가해 AppContent를 LanguageProvider로 감싸고 로컬스토리지 기반 언어 초기화/저장을 도입했으며, 여러 UI 컴포넌트에 번역 훅과 시간 포맷을 적용하고 버스 위치 폴링을 20s → 5s로 단축하고 일부 오버레이/버튼 스타일을 조정했습니다.

Changes

코호트 / 파일(s) 변경 요약
언어 컨텍스트 및 제공자
src/contexts/LanguageContext.tsx
Language 타입(`"ko"
앱 초기화 및 Provider 적용
src/App.tsx
App에 로컬스토리지(wtb:lang) 기반 초기 언어 읽기/저장 로직 추가 및 AppContentLanguageProvider로 래핑; language 상태를 강타입으로 변경.
컴포넌트 번역 적용
src/components/Bubble.tsx, src/components/BusStops.tsx, src/components/SettingsPanel.tsx
하드코딩된 한국어 문자열을 useTranslation().t()formatTime()으로 대체. SettingsPanel Props에서 language/setLanguage 타입을 Language로 좁힘(시그니처 변경). 표시명/방향 텍스트에 번역 적용.
스타일/레이아웃 조정
src/components/Bubble.tsx, src/components/SettingsButton.tsx
오버레이·패널·버튼의 right 오프셋 및 z-index 조정(예: 48/12 → 16, z-index 변경).
API 폴링 변경
src/api/bus.ts
useBusLocations 쿼리의 refetchInterval을 20000ms → 5000ms로 단축.
경미한 정리
src/utils/mapOverlays.ts
busIconSvg import 위치 이동(동작 변경 없음).

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • 집중 검토 대상:
    • src/contexts/LanguageContext.tsx — 번역 맵, 타입 안전성, formatTime 로직
    • src/App.tsx — 로컬스토리지 초기화/동기화와 Provider 적용 위치
    • src/components/SettingsPanel.tsx — Props 타입 변경(Language)으로 인한 호출부 영향
    • src/api/bus.ts — 폴링 간격 단축의 네트워크/성능 영향
    • UI 영향 확인: Bubble.tsx/BusStops.tsx의 의존성 배열(번역/포맷 반영) 및 스타일 z-index/오프셋 변경

Possibly related PRs

Suggested reviewers

  • guroking

🐰
토끼가 말하네, "언어를 심고, 시간을 재고,"
"ko"와 "en"이 손을 잡고 춤추네.
버스는 더 자주 와서 빛나고,
UI는 조용히 노래하네. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 변경 사항의 주요 내용을 명확하게 반영합니다. 영어 언어 지원 추가 및 폴링 주기를 5초로 변경하는 두 가지 핵심 기능 변경사항을 정확하게 설명합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/language-add-English

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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",  // en
src/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

📥 Commits

Reviewing files that changed from the base of the PR and between 00eed94 and 2c71e07.

📒 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초 폴링이 필요할 수 있으나, 백엔드 시스템이 이 증가된 요청 빈도를 처리할 수 있는지 개발팀이 검토하고 확인했는지 확인해주세요.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2c71e07 and 0878483.

📒 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)를 고려해볼 수 있습니다.

@@ -0,0 +1,112 @@
import { createContext, type ReactNode, useContext } from "react";

type Language = "ko" | "en";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0878483 and cc762b2.

📒 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

@KwonDeaGeun KwonDeaGeun merged commit 0031260 into main Nov 12, 2025
4 checks passed
@KwonDeaGeun KwonDeaGeun deleted the feat/language-add-English branch November 12, 2025 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant