forked from baron/baron-sso
feat: i18n 개선 및 userfront 로그인/로케일 보완
This commit is contained in:
44
docs/SoT_Architecture_Policy.md
Normal file
44
docs/SoT_Architecture_Policy.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Baron SSO Data SoT (Source of Truth) Architecture Policy
|
||||
|
||||
## 1. Core Principle: "Ory Stack is the Single Source of Truth"
|
||||
Baron SSO 시스템에서 인증(Identity), 인가(Authorization), OAuth2 위임(Delegation)의 데이터 원천은 **Ory Stack (Kratos, Keto, Hydra)** 입니다.
|
||||
Backend의 로컬 데이터베이스(PostgreSQL)는 성능 최적화, 검색, 감사(Audit), 비즈니스 메타데이터 관리를 위한 **Read-Model** 및 **Cold Storage**의 역할만 수행합니다.
|
||||
|
||||
## 2. Component Policies
|
||||
|
||||
### 2.1 Identity & User Profile (Ory Kratos)
|
||||
* **SoT:** Ory Kratos Identity (`traits`, `metadata_public`)
|
||||
* **Local DB (`users` Table):** **Read-Model & Search Index**
|
||||
* **목적:** 대규모 사용자 목록의 고속 검색(`LIKE`), 필터링, 정렬, 테넌트 조인(Join) 지원.
|
||||
* **동기화 전략:** `Async Write-Behind`
|
||||
* 사용자 생성/수정 API는 Kratos 처리가 성공하면 즉시 성공 응답을 반환합니다.
|
||||
* 로컬 DB 동기화는 별도 고루틴(Goroutine)에서 비동기로 수행됩니다.
|
||||
* **장애 격리:** 로컬 DB 장애가 사용자의 로그인/가입 프로세스를 차단하지 않습니다.
|
||||
|
||||
### 2.2 Permissions & Relationships (Ory Keto)
|
||||
* **SoT:** Ory Keto (Relation Tuples)
|
||||
* **Local DB:**
|
||||
* 권한 판단 로직을 로컬 DB에 저장하지 않습니다.
|
||||
* `Tenant`, `TenantGroup` 등 비즈니스 객체의 **생성/삭제 이벤트**를 Keto의 관계(Relation)로 비동기 동기화합니다.
|
||||
* 모든 권한 검증(`CheckPermission`)은 반드시 Keto API를 통해 실시간으로 수행합니다.
|
||||
|
||||
### 2.3 OAuth2 Clients & Sessions (Ory Hydra)
|
||||
* **SoT:** Ory Hydra (OAuth2 Clients, Access/Refresh Tokens, Consent Sessions)
|
||||
* **Local DB (`client_secrets`, `client_consents`):** **Backup & Query-Model**
|
||||
* `client_secrets`: Hydra는 해시된 시크릿만 저장하므로, 시크릿 재발급 및 관리를 위한 **원본 보관소(Cold Storage)**로 사용합니다.
|
||||
* `client_consents`: Hydra API는 "특정 사용자의 동의 내역" 조회만 지원하므로, "특정 클라이언트의 전체 사용자 동의 목록"을 제공하기 위한 **조회용 모델(Query-Model)**로 사용합니다.
|
||||
|
||||
## 3. Data Flow & Synchronization Strategy
|
||||
|
||||
### 3.1 Write Path (Command)
|
||||
1. **Request:** 클라이언트가 Backend API 요청.
|
||||
2. **Ory Exec:** Backend가 Ory 서비스(Kratos/Hydra/Keto) API를 동기(Synchronous) 호출.
|
||||
3. **Response:** Ory 성공 시 클라이언트에게 즉시 성공 응답 반환 (SoT 확정).
|
||||
4. **Sync:** Backend가 비동기(Goroutine)로 로컬 DB 테이블을 갱신.
|
||||
|
||||
### 3.2 Read Path (Query)
|
||||
* **Self Context (내 정보, 내 권한):** Ory Session/Token을 통해 직접 검증하거나 Kratos/Keto를 실시간 조회 (Always Fresh).
|
||||
* **Admin Context (목록 조회, 검색):** 로컬 DB를 조회하여 빠른 응답 제공 (Eventually Consistent).
|
||||
|
||||
### 3.3 Conflict Resolution
|
||||
* 데이터 불일치가 발견될 경우, 항상 **Ory Stack의 데이터를 기준(Authority)**으로 로컬 DB를 보정(Self-healing)합니다.
|
||||
@@ -79,6 +79,7 @@ TOML에서는 `[Section]`을 사용하여 계층을 표현합니다.
|
||||
* `ko` 계열이면 `/ko/dashboard`로 리다이렉트합니다.
|
||||
* 그 외에는 `/en/dashboard`로 리다이렉트합니다.
|
||||
* *단, 이전에 언어를 선택한 쿠키나 로컬스토리지 값이 있다면 그 값을 우선합니다.*
|
||||
* 로컬스토리지 키는 **`locale`**을 사용합니다.
|
||||
2. **언어 변경 시**:
|
||||
* 모든 화면에는 **언어 선택기(Language Selector)**가 노출되어야 합니다.
|
||||
* 변경 시 해당 언어의 URL로 이동(`window.location` 변경 혹은 Router Push)하며, 선택된 언어를 로컬스토리지에 저장합니다.
|
||||
|
||||
86
docs/trouble-shooting/userfront-locale.md
Normal file
86
docs/trouble-shooting/userfront-locale.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# userfront locale 전환 문제 분석 및 대응
|
||||
|
||||
## 증상
|
||||
- URL은 `/ko` ↔ `/en`으로 변경되지만 실제 텍스트가 바뀌지 않음.
|
||||
- 브라우저에서 `window.localStorage.getItem('locale')`가 계속 `null`.
|
||||
- 빌드/배포 후에도 동일 증상 유지.
|
||||
|
||||
## 현재 구조 요약
|
||||
- Flutter Web + `easy_localization` 사용.
|
||||
- 경로 기반 로케일: `/:locale` 라우트 + `LocaleGate`로 로케일 적용.
|
||||
- 번역 리소스: `userfront/assets/translations/*.toml`.
|
||||
- 로케일 저장: `localStorage` key `locale`.
|
||||
|
||||
## 이미 적용한 변경
|
||||
- `easy_localization` + TOML loader 적용.
|
||||
- `LocaleGate`에서 로케일 적용 및 저장.
|
||||
- `LanguageSelector`에서 로케일 저장 + URL 변경.
|
||||
- `userfront/assets/translations`에 `en.toml`, `ko.toml`, `template.toml` 포함.
|
||||
- `pubspec.yaml` assets 등록.
|
||||
- GoRouter 호환성 수정(빌드 오류 대응).
|
||||
|
||||
## 원인 후보(우선순위)
|
||||
1) **로케일 저장이 실제로 실행되지 않음**
|
||||
- `LanguageSelector` 클릭 이벤트가 동작하지 않거나,
|
||||
- `LocaleGate`가 호출되지 않는 라우트 진입(예: 라우트 변경 없이 SPA 상태만 변경).
|
||||
|
||||
2) **서비스 워커/캐시로 인해 구 번들이 계속 로드됨**
|
||||
- Flutter Web 기본 `flutter_service_worker.js`가 캐시를 고정.
|
||||
- 기존 번들이 남아 `LocaleStorage.write()` 반영 전 코드가 계속 실행될 가능성.
|
||||
|
||||
3) **번역 리소스 미로딩**
|
||||
- `assets/translations/en.toml`, `ko.toml` 요청이 404 또는 미요청.
|
||||
- Nginx 경로/정적 파일 설정에서 `assets/`가 누락된 경우.
|
||||
|
||||
4) **en.toml 키 누락으로 fallback 문자열이 표시됨**
|
||||
- UI에서 `tr(..., fallback: '한국어')`를 쓰는 경우,
|
||||
en.toml에 키가 없으면 한국어가 그대로 노출됨.
|
||||
|
||||
## 확인 방법(권장 순서)
|
||||
1) **로케일 저장 확인**
|
||||
- 언어 변경 후 콘솔:
|
||||
- `window.localStorage.getItem('locale')`
|
||||
- `null`이면 저장 로직 실행 실패.
|
||||
|
||||
2) **번역 리소스 요청 확인**
|
||||
- DevTools Network에서:
|
||||
- `/assets/translations/ko.toml`
|
||||
- `/assets/translations/en.toml`
|
||||
- 404 또는 미요청이면 assets 로딩 문제.
|
||||
|
||||
3) **로케일 반영 확인**
|
||||
- UI 내 임시 텍스트로 `context.locale.languageCode` 출력
|
||||
- 로케일이 바뀌는데 텍스트가 그대로면 TOML 키 누락 가능성.
|
||||
|
||||
4) **캐시 무효화**
|
||||
- 하드 리로드(Shift+Reload)
|
||||
- service worker 제거 후 재접속
|
||||
|
||||
## 현재까지 실행한 대응
|
||||
- `LocaleGate`에서 로케일 동일 여부와 상관없이 `LocaleStorage.write()`가 실행되도록 수정.
|
||||
- 라우터 로케일 파싱/전환 로직 보강.
|
||||
- 번역 리소스 파일 배치 및 assets 등록.
|
||||
|
||||
## 앞으로의 대응 계획
|
||||
1) **서비스 워커 캐시 무효화 전략**
|
||||
- `flutter_service_worker.js` 버전 갱신 또는 Nginx 캐시 무력화 정책 적용.
|
||||
- 배포 시 `index.html`/`flutter_service_worker.js` 캐시 제어 헤더 추가.
|
||||
|
||||
2) **번역 파일 누락 방지**
|
||||
- `scripts/sync_userfront_locales.sh`를 CI에서 자동 실행.
|
||||
- en/ko 키 누락 검증 테스트 추가.
|
||||
|
||||
3) **로케일 저장 검증**
|
||||
- 언어 변경 후 `localStorage`에 값이 반드시 들어오는지 E2E 체크 추가.
|
||||
|
||||
4) **fallback 사용 최소화**
|
||||
- userfront에서 `fallback` 문자열(한국어) 남용 구간 정리.
|
||||
- en.toml에 키가 없을 때 한국어가 보이는 현상 방지.
|
||||
|
||||
## 참고 파일
|
||||
- `userfront/lib/core/i18n/locale_gate.dart`
|
||||
- `userfront/lib/core/widgets/language_selector.dart`
|
||||
- `userfront/lib/core/i18n/locale_storage_web.dart`
|
||||
- `userfront/lib/core/i18n/toml_asset_loader.dart`
|
||||
- `userfront/assets/translations/en.toml`
|
||||
- `userfront/assets/translations/ko.toml`
|
||||
Reference in New Issue
Block a user