Stabilize auth flow and profile images
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
# tdc114plus API 계약
|
||||
|
||||
작성일: 2026-07-02
|
||||
최종 개정일: 2026-07-10
|
||||
상태: v3.3
|
||||
|
||||
목적: `tdc114plus` Flutter 앱이 공식 인터페이스 기준으로 설계·개발될 수 있도록 1차 API 계약 원칙과 우선 사용 흐름을 정리한다.
|
||||
|
||||
상위 기준 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
|
||||
공식 인터페이스 기준:
|
||||
|
||||
- Swagger/API Docs: `https://sadmin.hmac.kr/api/docs#/`
|
||||
- 사용자 확인 추가 기준: `tdc114plus 앱 전용 API는 없고`, Swagger에 공개된 Baron API를 앱이 직접 소비한다.
|
||||
|
||||
## 1. 전제
|
||||
|
||||
- `tdc114plus` 신규 앱은 Baron SSO에 등록되는 별도 `RP(Relying Party)`다.
|
||||
- 앱 인증은 Baron SSO의 RP 로그인 절차 일부로 본다.
|
||||
- 앱은 Baron SSO 내부 구현이 아니라 공식 API 계약을 기준으로 설계한다.
|
||||
- 실제 backend 구현 상태와 무관하게 Flutter 앱은 이 계약을 바탕으로 mock/real 병행 개발이 가능해야 한다.
|
||||
- 현재 저장소 코드에 남아 있는 `/api/v1/tdc114plus/...` 가정은 확정 계약이 아니라 재검증 대상이다.
|
||||
- 재검증 대상 경로는 기능이 유지되는지 확인하면서 단계적으로 교체 또는 제거한다.
|
||||
|
||||
## 2. 핵심 원칙
|
||||
|
||||
- 신규 앱의 기본 로그인은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`로 진행한다.
|
||||
- 앱은 Baron SSO 인증 URL을 열고, Baron SSO 로그인 화면에서 휴대폰번호 입력 및 문자/메일 링크 인증을 처리한다.
|
||||
- 앱은 callback으로 받은 authorization code를 PKCE `code_verifier`로 token 교환한 뒤 앱 세션을 저장한다.
|
||||
- 로그인 성공 후 Baron SSO가 조직도 API 호출에 필요한 연동 키 묶음을 내려주는 구조를 최종 목표로 둔다.
|
||||
- 해당 Baron SSO 기능이 개발되기 전까지는 앱 개발/검증용으로 로컬 비추적 환경값에 설정한 staging `org-context` 키를 fallback으로 사용한다.
|
||||
- 기존 `선진행 후확인` 방식은 신규 앱 기본 인증 정책으로 사용하지 않는다.
|
||||
- 기존 `phone-login` 방식은 개발용 fallback 또는 제한적 호환 범위로만 둔다.
|
||||
- 레거시 계약 제거는 `대체 path 반영 -> mock/real 테스트 통과 -> 실제 화면 확인 -> 제거` 순서를 지킨다.
|
||||
- JSON field는 camelCase를 사용한다.
|
||||
- 목록 응답은 가능하면 `items`, `limit`, `offset`, `total`, `nextCursor` 형식을 따른다.
|
||||
- UI는 DTO와 repository interface만 의존하고, endpoint path나 header를 직접 다루지 않는다.
|
||||
|
||||
## 3. 1차 범위
|
||||
|
||||
- Baron SSO Hosted Login 시작
|
||||
- App Link callback 수신
|
||||
- PKCE authorization code token 교환
|
||||
- 로그인 세션 저장 후 앱 진입
|
||||
- 직원검색
|
||||
- 가족사/조직 탐색
|
||||
- 조직도
|
||||
- 직원 상세
|
||||
- 즐겨찾기 로컬 저장
|
||||
|
||||
보류:
|
||||
|
||||
- 공지사항
|
||||
- 전자결재
|
||||
- 수신전화식별
|
||||
- 수신팝업
|
||||
- 서버 기반 즐겨찾기 동기화
|
||||
|
||||
## 4. 인증 계약
|
||||
|
||||
주의:
|
||||
|
||||
- `tdc114plus 앱 전용 API는 없다`는 사용자 확인이 들어왔으므로, 아래 계약은 Baron Swagger 기준으로 재정렬한다.
|
||||
- Flutter 앱은 Baron headless API를 직접 호출하지 않는다.
|
||||
- 휴대폰번호 입력과 링크 발송/승인은 Baron SSO Hosted Login 화면과 서버 내부 구현으로 둔다.
|
||||
- legacy `/api/v1/tdc114plus/...` path는 예외 호환 또는 과거 흔적으로만 취급한다.
|
||||
|
||||
### 4.1 로그인 시작
|
||||
|
||||
```http
|
||||
GET https://sso.hmac.kr/oidc/oauth2/auth
|
||||
```
|
||||
|
||||
의미:
|
||||
|
||||
- 앱이 PKCE `code_verifier`, `code_challenge`, `state`, `nonce`를 생성한다.
|
||||
- 앱이 Baron SSO authorization endpoint를 브라우저/커스텀탭으로 연다.
|
||||
- 사용자는 Baron SSO Hosted Login 화면에서 휴대폰번호 입력과 문자/메일 링크 인증을 진행한다.
|
||||
|
||||
예시 query:
|
||||
|
||||
```http
|
||||
client_id=39d6190d-72f6-4a58-a84f-cdc5ece3e8af
|
||||
redirect_uri=https://114.hmac.kr/auth/callback
|
||||
response_type=code
|
||||
scope=openid profile email tenants
|
||||
state={random-state}
|
||||
nonce={random-nonce}
|
||||
code_challenge={S256-code-challenge}
|
||||
code_challenge_method=S256
|
||||
```
|
||||
|
||||
### 4.2 callback 수신
|
||||
|
||||
```http
|
||||
GET https://114.hmac.kr/auth/callback?code={authorization-code}&state={state}
|
||||
```
|
||||
|
||||
의미:
|
||||
|
||||
- `https://114.hmac.kr/auth/callback`은 Android App Link로 앱에 연결한다.
|
||||
- 앱은 callback의 `state`가 저장된 PKCE transaction의 `state`와 같은지 검증한다.
|
||||
- `state`가 다르면 token 교환을 중단한다.
|
||||
|
||||
### 4.3 token 교환
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/oidc/oauth2/token
|
||||
```
|
||||
|
||||
의미:
|
||||
|
||||
- 앱은 authorization code와 저장된 `code_verifier`를 사용해 token endpoint를 호출한다.
|
||||
- PKCE 공개 앱이므로 Client Secret을 보내지 않는다.
|
||||
|
||||
예시 요청:
|
||||
|
||||
```http
|
||||
grant_type=authorization_code
|
||||
client_id=39d6190d-72f6-4a58-a84f-cdc5ece3e8af
|
||||
code={authorization-code}
|
||||
code_verifier={stored-code-verifier}
|
||||
redirect_uri=https://114.hmac.kr/auth/callback
|
||||
```
|
||||
|
||||
완료 응답 예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "access-token",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 3600,
|
||||
"id_token": "id-token",
|
||||
"org_context": {
|
||||
"base_url": "https://sadmin.hmac.kr",
|
||||
"tenant_slug": "hanmac-family",
|
||||
"key_id": "org-context-key-id",
|
||||
"key_secret": "org-context-key-secret",
|
||||
"expires_at": "2026-07-10T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`org_context`는 향후 Baron SSO가 제공할 예정인 확장 필드 예시다. 현재 staging 서버 기능이 미개발이면 응답에 없을 수 있으며, 앱은 이 필드가 없을 때 로컬 비추적 환경값의 staging 고정 키를 사용한다.
|
||||
|
||||
### 4.4 headless API 직접 호출 제외
|
||||
|
||||
```http
|
||||
POST /api/v1/auth/headless/phone-login
|
||||
POST /api/v1/auth/headless/link/poll
|
||||
```
|
||||
|
||||
- 위 API는 Baron SSO 내부 구현 또는 confidential client용 참고 계약으로 본다.
|
||||
- 현재 Flutter 앱은 공개 PKCE 앱이므로 `client_assertion`, `private_key_jwt`, RP 개인키를 APK에 넣지 않는다.
|
||||
- 따라서 위 API는 신규 앱 기본 로그인 구현에서 직접 호출하지 않는다.
|
||||
|
||||
### 4.5 레거시/개발용 즉시 로그인
|
||||
|
||||
```http
|
||||
POST /api/v1/tdc114plus/auth/phone-login
|
||||
```
|
||||
|
||||
- 이 경로는 개발용 fallback 또는 제한적 호환 범위로만 본다.
|
||||
- 신규 앱 기본 로그인 UX로 간주하지 않는다.
|
||||
|
||||
## 5. 세션 및 사용자 정보
|
||||
|
||||
### 5.1 세션 저장 기준
|
||||
|
||||
- token 교환 성공 시 반환된 access token과 만료시간을 앱 저장소에 저장한다.
|
||||
- 사용자 정보는 `id_token` claim 또는 후속 `userinfo` 응답에서 가져온다.
|
||||
- 조직도 API 호출용 연동 키가 token 응답, userinfo, 또는 별도 session endpoint로 전달되면 앱 세션의 선택적 `orgContextCredential`로 저장한다.
|
||||
- `orgContextCredential`이 있으면 `integrations/org-context` 호출 시 이 값을 우선 사용하고, 없으면 개발/검증용 비추적 환경값 fallback을 사용한다.
|
||||
- 연동 키는 로그에 출력하지 않고, 운영 배포 전에는 안전 저장소 적용 여부를 별도 검토한다.
|
||||
- 앱 재실행 시 저장 세션이 유효하면 로그인 화면을 건너뛴다.
|
||||
- API 호출 중 `401/403`이 발생하면 세션 정리 후 재로그인 흐름으로 돌린다.
|
||||
|
||||
### 5.2 사용자 기본 정보
|
||||
|
||||
로그인 완료 후 앱이 기대하는 최소 사용자 정보:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"name": "홍길동",
|
||||
"phoneNumber": "+821012345678",
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantName": "한맥",
|
||||
"tenantSlug": "hanmac",
|
||||
"department": "기술연구소",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발"
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 조직/직원 데이터 계약 원칙
|
||||
|
||||
- 직원검색과 조직도는 공식 인터페이스가 제공하는 조직/직원 endpoint를 기준으로 설계한다.
|
||||
- 실제 배포 전까지 조직/직원 API 기준은 staging Swagger(`https://sadmin.hmac.kr/api/docs#/Integrations/get_api_v1_integrations_org_context`)와 staging `org-context` endpoint를 따른다.
|
||||
- 가족사/조직 탐색은 `tenant` 계층과 `tenantSlug`를 기준으로 진행한다.
|
||||
- 로그인 직후 기본 범위는 사용자의 회사급 `tenantSlug`를 우선 기준으로 한다.
|
||||
- 화면 정책상 필요한 drilldown 구조는 repository 계층에서 정리하고 UI는 결과 모델만 소비한다.
|
||||
- 현재 `/api/v1/tdc114plus/organization/*`, `/api/v1/tdc114plus/directory/*` 같은 path는 확정 계약이 아니라 placeholder 성격일 수 있으므로, Swagger의 실제 공개 path인 `integrations/org-context`, `public/orgchart` 기준으로 교체한다.
|
||||
- 교체 전까지는 mock과 실제 화면이 같은 결과를 내는지 확인해 기능 공백 없이 전환한다.
|
||||
|
||||
### 6.1 subtree 계약 보강 필요사항
|
||||
|
||||
- 회사 선택 후 `부서 -> 팀 -> 개인` drilldown을 구현하려면 조직 subtree 조회 계약이 필요하다.
|
||||
- 현재 API가 최상위 tenant 위주 응답만 제공하는 경우, 앱은 fallback으로 회사 단위 직원 목록과 본인팀 synthetic chip만 유지한다.
|
||||
- Swagger의 `public/orgchart`처럼 `tenants[]`, `users[]` 중심 응답을 사용할 경우에도, 최종 목표 계약은 해당 배열만으로 특정 tenant 기준 자식 조직 subtree와 leaf 판단 정보를 복원할 수 있는 형태다.
|
||||
- 해당 보강 요청은 `docs/00_guide_baron_sso_subtree_api_issue_request_2026-07-07.md` 초안 기준으로 Baron SSO 이슈로 병행 관리한다.
|
||||
|
||||
## 7. Flutter 구현 해석
|
||||
|
||||
- `auth` feature는 Hosted Login authorization URL 생성, PKCE transaction 저장, callback token 교환, 세션 저장 흐름을 우선 구현한다.
|
||||
- `directory`, `organization` feature는 `org-context` 중심 Swagger DTO와 repository interface를 먼저 고정한다.
|
||||
- mock repository는 실제 API 미구현 상태에서도 유지한다.
|
||||
- 실제 API 경로와 mock 경로는 동일한 UI 흐름을 만족해야 한다.
|
||||
|
||||
## 8. 문서 갱신 원칙
|
||||
|
||||
- Swagger 기준이 달라지면 이 문서를 먼저 갱신한다.
|
||||
- 새 endpoint를 사용하기 시작하면 request/response 예시를 추가한다.
|
||||
- 내부 추정이 아니라 공식 인터페이스에서 확인된 내용만 확정 표현으로 남긴다.
|
||||
- 사용자 확인으로 뒤집힌 가정은 즉시 `가정` 또는 `재검증 대상`으로 강등한다.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Baron SSO PKCE 모바일 RP Headless 계약 확인 요청
|
||||
|
||||
## 이슈 제목
|
||||
|
||||
`[API Contract Request] PKCE 모바일 RP의 Headless 전화번호 로그인 지원 방식 확인 요청`
|
||||
|
||||
## 배경
|
||||
|
||||
신규 Flutter 앱 `TDC114PLUS`를 Baron SSO의 PKCE 공개 클라이언트 RP로 등록했습니다.
|
||||
|
||||
- Client ID: `39d6190d-72f6-4a58-a84f-cdc5ece3e8af`
|
||||
- Redirect URI: `https://114.hmac.kr/auth/callback`
|
||||
- Client Secret: 없음
|
||||
- OIDC issuer: `https://sso.hmac.kr/oidc`
|
||||
|
||||
앱의 로그인 UX는 아래 순서를 사용합니다.
|
||||
|
||||
1. 사용자가 앱에서 전화번호로 로그인을 요청
|
||||
2. Baron SSO가 문자 또는 메일로 승인 링크 발송
|
||||
3. 사용자가 링크 클릭
|
||||
4. 앱이 승인 상태를 확인
|
||||
5. OIDC authorization code + PKCE로 앱 세션 생성
|
||||
|
||||
## 확인된 계약
|
||||
|
||||
Swagger의 아래 API는 `client_assertion`을 필수로 요구합니다.
|
||||
|
||||
- `POST /api/v1/auth/headless/phone-login`
|
||||
- `POST /api/v1/auth/headless/link/poll`
|
||||
|
||||
`client_assertion`은 `private_key_jwt`로 설명되어 있습니다. 그러나 TDC114PLUS는 Client Secret이나 개인키를 안전하게 보관할 수 없는 PKCE 공개 모바일 앱입니다.
|
||||
|
||||
## 문제점
|
||||
|
||||
모바일 APK에 `private_key_jwt` 서명용 개인키를 포함하면 추출될 수 있으므로 공개 클라이언트 보안 모델에 맞지 않습니다.
|
||||
|
||||
OIDC Discovery에서는 token endpoint 인증 방식 `none`과 PKCE S256을 지원하므로 authorization code 교환은 가능하지만, 그 앞의 headless API 호출 방법이 현재 계약만으로는 확정되지 않습니다.
|
||||
|
||||
## 요청 사항
|
||||
|
||||
PKCE 공개 모바일 RP에서 아래 값을 획득하고 headless 로그인을 진행하는 공식 절차를 명세해 주시기 바랍니다.
|
||||
|
||||
1. `login_challenge` 획득 절차
|
||||
2. `client_assertion` 생략 가능 여부
|
||||
3. 생략이 불가능한 경우 단기·1회성 assertion 발급 endpoint
|
||||
4. assertion의 issuer, subject, audience, 만료시간, 서명 알고리즘
|
||||
5. `phone-login -> link/poll -> redirectTo -> callback -> token` 전체 순서
|
||||
6. 각 단계의 Request/Response 예시와 오류 코드
|
||||
|
||||
## 제안 가능한 방식
|
||||
|
||||
- 모바일 PKCE RP에 한해 headless API에서 assertion 대신 등록된 Client ID, PKCE transaction, 짧은 TTL의 서버 challenge를 검증
|
||||
- Baron SSO가 모바일 RP용 단기·1회성 assertion을 발급
|
||||
- confidential 중계 서버를 별도로 두고 해당 서버만 `private_key_jwt`를 생성
|
||||
|
||||
## 완료 기준
|
||||
|
||||
- 개인키를 APK에 저장하지 않고 headless API를 호출할 수 있음
|
||||
- 승인 완료 후 `https://114.hmac.kr/auth/callback`으로 authorization code가 전달됨
|
||||
- 앱이 PKCE verifier로 token endpoint에서 토큰을 교환할 수 있음
|
||||
@@ -0,0 +1,96 @@
|
||||
# Baron SSO 하위조직 Subtree API 보강 요청 초안
|
||||
|
||||
작성일: 2026-07-07
|
||||
상태: draft
|
||||
|
||||
목적: Baron SSO 개발자에게 `tdc114plus` 신규 앱 기준 하위조직 subtree API 보강 필요사항을 Gitea 이슈 형식으로 전달하기 위한 등록용 초안이다. 현재 Swagger의 `GET /api/v1/public/orgchart?token=...` 형태를 참고해, 실제 수신 가능한 응답 구조 기준으로 요청 내용을 맞춘다.
|
||||
|
||||
## 1. 이슈 제목 초안
|
||||
|
||||
`[Feature Request] tdc114plus 직원검색/조직도용 public orgchart subtree 응답 보강 필요`
|
||||
|
||||
## 2. 이슈 본문 초안
|
||||
|
||||
```md
|
||||
## 배경
|
||||
신규 앱 `tdc114plus`는 Baron SSO에 추가되는 별도 RP(Relying Party)로 개발 중이며,
|
||||
직원검색/조직도 화면은 정의된 API 인터페이스를 통해 데이터를 조회하는 구조로 진행하고 있습니다.
|
||||
|
||||
현재 Swagger상 공개 조직 조회 API는 아래 형태로 확인됩니다.
|
||||
|
||||
- `GET /api/v1/public/orgchart?token=...`
|
||||
- 응답 구조: `tenants[]`, `users[]`, `sharedWith`
|
||||
|
||||
신규 앱에서는 이 응답을 기반으로 `전체 -> 회사 -> 부서 -> 팀 -> 개인` 단계 탐색이 가능해야 합니다.
|
||||
|
||||
## 문제점
|
||||
현재 제공 중인 조직 관련 API 응답은 최상위 회사/법인 수준 정보 위주로 내려오고 있어,
|
||||
특정 회사 하위의 부서/팀 subtree 구조를 충분히 구성할 수 없습니다.
|
||||
|
||||
실제 확인 결과:
|
||||
- `GET /api/v1/tdc114plus/organization/tenants` 응답은 최상위 tenant 위주
|
||||
- `GET /api/v1/tdc114plus/organization/orgchart`도 동일하게 하위 부서/팀 subtree 확인이 어려움
|
||||
- `tenantId`를 지정해도 회사 하위 조직 subtree가 아니라 동일한 최상위 목록 중심 응답으로 확인됨
|
||||
- 직원 상세의 joined tenant 정보도 회사급까지만 확인되어 세부 부서/팀 탐색 기준으로 사용하기 어렵습니다.
|
||||
- `public/orgchart` 예시도 현재는 `tenants[]`, `users[]` 기본 구조만 보여서, 하위조직 경로 복원용 정보가 부족해 보입니다.
|
||||
|
||||
## 재현 절차
|
||||
1. 신규 앱에서 직원검색/조직도 화면 진입
|
||||
2. 상단 회사 뱃지 선택
|
||||
3. 선택한 회사의 하위조직 탐색 시도
|
||||
4. 하위 부서/팀 단위 트리 확장에 필요한 subtree 데이터가 부족하여 화면 구성이 제한됨
|
||||
|
||||
## 현재 동작
|
||||
- 최상위 조직(회사/법인) 중심 데이터만 확인 가능
|
||||
- 회사 하위 부서/팀 subtree를 안정적으로 구성하기 어려움
|
||||
- leaf 조직 선택 후 해당 조직 기준 후속 조회 구현이 제한됨
|
||||
|
||||
## 기대 동작
|
||||
- `public/orgchart` 계열 응답만으로도 특정 회사 또는 조직 기준 하위 subtree 전체를 복원할 수 있어야 합니다.
|
||||
- 각 tenant 항목에서 상위 조직 관계와 leaf 여부를 확인할 수 있어야 합니다.
|
||||
- 각 user 항목은 어떤 tenant/조직에 속하는지 연결 가능해야 합니다.
|
||||
- 프론트는 이 응답만으로 `전체 -> 회사 -> 부서 -> 팀 -> 개인` 탐색과 해당 조직 사용자 표시를 구현할 수 있어야 합니다.
|
||||
|
||||
## 요청 사항
|
||||
현재 Swagger에 노출된 `GET /api/v1/public/orgchart?token=...`를 기준으로,
|
||||
조직 subtree 복원이 가능하도록 응답 보강이 필요합니다.
|
||||
|
||||
가능한 방향 예시:
|
||||
- 기존 `public/orgchart` 응답에 조직 계층 복원용 필드 추가
|
||||
- 또는
|
||||
- `public/orgchart`와 유사한 응답 구조를 유지하면서 subtree 전용 API 추가
|
||||
|
||||
예를 들어 `tenants[]`에 아래 정보가 필요합니다.
|
||||
- `id`
|
||||
- `parentId`
|
||||
- `slug`
|
||||
- `name`
|
||||
- `type` (`COMPANY`, `DEPARTMENT`, `TEAM` 등)
|
||||
- `hasChildren` 또는 `isLeaf`
|
||||
- `depth` 또는 경로 복원 가능 정보
|
||||
|
||||
예를 들어 `users[]`에는 아래 정보가 필요합니다.
|
||||
- `id`
|
||||
- `name`
|
||||
- `position`
|
||||
- `jobTitle`
|
||||
- `companyCode`
|
||||
- `tenantId` 또는 `tenantSlug`
|
||||
- 필요 시 `department`
|
||||
|
||||
즉, 프론트가 `tenants[]`와 `users[]`만으로 조직 계층 구성, leaf 조직 판별, 해당 조직 사용자 표시를 수행할 수 있어야 합니다.
|
||||
|
||||
## 검토 포인트
|
||||
- `public/orgchart` 응답 확장으로 처리할지, subtree 전용 API를 분리할지
|
||||
- `tenants[]`, `users[]` 기준으로 조직-사용자 연결 식별자 통일 가능 여부
|
||||
- leaf 조직 판단 기준 제공 여부
|
||||
- 공유 token 기반 조회에서 subtree 범위 제한을 어떻게 둘지
|
||||
- 신규 앱 포함 타 RP에서 공통 활용 가능 여부
|
||||
```
|
||||
|
||||
## 3. 작성 메모
|
||||
|
||||
- 현재 Flutter 앱은 subtree API 부재 구간에서 `본인팀 synthetic chip + 회사 단위 직원 목록` fallback으로 동작하도록 정리했다.
|
||||
- 즉, 앱 개발은 병행 가능하지만, 완전한 조직 drilldown UX는 해당 응답 보강이 필요하다.
|
||||
- 현재 초안은 `신규 endpoint 생성 요구`보다 `기존 public orgchart 스타일 응답 보강 요청`에 더 가깝다.
|
||||
- 등록 시에는 이 문서의 `## 2. 이슈 본문 초안` 블록만 그대로 사용하면 된다.
|
||||
@@ -0,0 +1,83 @@
|
||||
# TDC114PLUS Android App Link 설정 가이드
|
||||
|
||||
작성일: 2026-07-09
|
||||
상태: debug 공기계 callback 수신 검증 완료
|
||||
|
||||
## 1. 목적
|
||||
|
||||
Baron SSO가 인증 완료 후 아래 HTTPS 주소로 이동했을 때 Android의 TDC114PLUS 앱이 열리도록 설정한다.
|
||||
|
||||
```text
|
||||
https://114.hmac.kr/auth/callback
|
||||
```
|
||||
|
||||
## 2. 앱 설정
|
||||
|
||||
| 항목 | 값 |
|
||||
| --- | --- |
|
||||
| Android package | `kr.co.baron.tdc114plus` |
|
||||
| scheme | `https` |
|
||||
| host | `114.hmac.kr` |
|
||||
| path | `/auth/callback` |
|
||||
| App Link 자동 검증 | 사용 |
|
||||
|
||||
## 3. 서버 담당자 요청 사항
|
||||
|
||||
`docs/references/assetlinks.debug.json` 파일을 아래 공개 주소에 JSON 원문으로 배포한다.
|
||||
|
||||
```text
|
||||
https://114.hmac.kr/.well-known/assetlinks.json
|
||||
```
|
||||
|
||||
배포 조건:
|
||||
|
||||
- HTTP 상태코드 `200`
|
||||
- 리다이렉트 없이 직접 응답
|
||||
- `Content-Type: application/json`
|
||||
- 로그인이나 쿠키 요구 없음
|
||||
- 외부 네트워크와 테스트 공기계에서 접근 가능
|
||||
|
||||
## 4. 현재 테스트 APK 지문
|
||||
|
||||
```text
|
||||
3A:2D:60:48:6F:E5:3A:84:0C:41:14:DC:3A:17:A4:3B:64:E7:DE:A5:10:4A:09:26:0E:DC:5F:49:88:44:71:76
|
||||
```
|
||||
|
||||
이 지문은 2026-07-09에 빌드한 debug APK용이다. 운영 APK는 운영 서명 인증서의 SHA-256 지문을 같은 배열에 추가해야 한다.
|
||||
|
||||
## 5. 검증 순서
|
||||
|
||||
1. 서버에서 `assetlinks.json`을 배포한다.
|
||||
2. 최신 APK를 공기계에 재설치한다.
|
||||
3. Android가 도메인 소유권 검증을 완료하도록 잠시 기다린다.
|
||||
4. 아래 주소를 공기계에서 연다.
|
||||
|
||||
```text
|
||||
https://114.hmac.kr/auth/callback?code=test-code&state=test-state
|
||||
```
|
||||
|
||||
5. 브라우저나 앱 선택창이 아니라 TDC114PLUS의 `로그인 결과 확인` 화면이 열리는지 확인한다.
|
||||
6. 실제 RP Client ID를 앱에 주입한 후 headless 승인부터 OIDC callback까지 E2E를 수행한다.
|
||||
|
||||
## 6. 현재 확인 결과
|
||||
|
||||
- `http://172.16.8.198:8080/auth/callback`: 정상
|
||||
- `https://114.hmac.kr/auth/callback`: 브라우저 응답 정상
|
||||
- 최신 debug APK 공기계 설치: 정상
|
||||
- App Link 테스트: 앱 선택창 표시
|
||||
- `assetlinks.json` 임시 테스트 서버 배포: 정상
|
||||
- 외부 HTTPS JSON 응답: HTTP 200, `application/json` 확인
|
||||
- 구형 공기계 자동 연결 상태: `undefined`
|
||||
- 공기계 테스트 기본 앱 지정 후 callback 실행: TDC114PLUS `.MainActivity` 직접 실행 성공
|
||||
- callback 화면에서 `code=test-code` 수신 확인
|
||||
- 판정: callback 수신 경로는 검증 완료. 실제 Client ID와 PKCE code 교환 구현이 남아 있음
|
||||
|
||||
## 7. RP Client ID
|
||||
|
||||
```text
|
||||
39d6190d-72f6-4a58-a84f-cdc5ece3e8af
|
||||
```
|
||||
|
||||
- Client ID는 공개 식별자이므로 debug APK 기본 설정에 포함한다.
|
||||
- Client Secret은 APK에 포함하지 않는다.
|
||||
- 환경별 Client ID 변경은 `TDC114_OIDC_CLIENT_ID` Dart define을 사용한다.
|
||||
@@ -0,0 +1,374 @@
|
||||
# TDC114PLUS / tdc114plus-auth / Baron SSO Redirect Flow
|
||||
|
||||
작성일: 2026-07-15
|
||||
|
||||
## 결론
|
||||
|
||||
현재 우리가 진행 중인 방식에서는 TDC114PLUS 앱 RP의 아래 callback은 로그인 완료에 필수 아님이다.
|
||||
|
||||
```text
|
||||
https://114.hmac.kr/auth/callback
|
||||
```
|
||||
|
||||
현재 필요한 것은 `tdc114plus-auth` 중계서버 RP에 등록한 redirect URI다.
|
||||
|
||||
```text
|
||||
https://114-auth.hmac.kr/api/v1/auth/oidc/callback
|
||||
```
|
||||
|
||||
개발 로컬에서는 아래 URI를 사용한다.
|
||||
|
||||
```text
|
||||
http://172.16.8.198:5001/api/v1/auth/oidc/callback
|
||||
http://127.0.0.1:5001/api/v1/auth/oidc/callback
|
||||
```
|
||||
|
||||
다만 앱 소스에는 아직 예전/보조 구조인 아래 callback이 남아 있다.
|
||||
|
||||
```text
|
||||
https://114.hmac.kr/auth/callback
|
||||
```
|
||||
|
||||
이 값은 Hosted Login + PKCE 방식으로 앱이 Baron SSO에 직접 붙던 구조의 흔적이다.
|
||||
|
||||
## 역할 구분
|
||||
|
||||
### TDC114PLUS 앱
|
||||
|
||||
- 전화번호 입력 화면 제공
|
||||
- `tdc114plus-auth`에 링크 발송 요청
|
||||
- `pendingRef`를 받아 저장
|
||||
- 계속 poll
|
||||
- poll 성공 시 받은 앱 세션 token 저장
|
||||
- 직원검색 화면 진입
|
||||
|
||||
### tdc114plus-auth
|
||||
|
||||
- 앱 대신 Baron SSO headless API 호출
|
||||
- `client_assertion` 생성
|
||||
- `login_challenge` 확보
|
||||
- Baron SSO `link/init`, `link/poll` 호출
|
||||
- poll 성공 후 `redirectTo` 추적
|
||||
- consent 필요 시 자동 consent 처리
|
||||
- authorization code 수신
|
||||
- token exchange
|
||||
- 앱용 session token 발급
|
||||
- 직원/조직 API 중계
|
||||
|
||||
### Baron SSO
|
||||
|
||||
- 사용자/전화번호 검증
|
||||
- SMS 링크 발송
|
||||
- 사용자가 링크 클릭하면 승인 처리
|
||||
- OIDC authorization code 발급
|
||||
- token endpoint 제공
|
||||
|
||||
## 현재 실제 로그인 흐름
|
||||
|
||||
### 1. 앱 실행
|
||||
|
||||
```text
|
||||
TDC114PLUS 앱
|
||||
```
|
||||
|
||||
### 2. 사용자가 전화번호 입력 후 로그인 링크 보내기
|
||||
|
||||
로컬 개발 기준:
|
||||
|
||||
```http
|
||||
POST http://127.0.0.1:5001/api/v1/auth/link/init
|
||||
```
|
||||
|
||||
실서버/도메인 기준:
|
||||
|
||||
```http
|
||||
POST https://114-auth.hmac.kr/api/v1/auth/link/init
|
||||
```
|
||||
|
||||
요청 예:
|
||||
|
||||
```json
|
||||
{
|
||||
"loginId": "01091365338"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. tdc114plus-auth가 Baron SSO OIDC authorization 시작
|
||||
|
||||
```http
|
||||
GET https://sso.hmac.kr/oidc/oauth2/auth
|
||||
```
|
||||
|
||||
주요 값:
|
||||
|
||||
```text
|
||||
client_id=tdc114plus-auth RP client_id
|
||||
redirect_uri=https://114-auth.hmac.kr/api/v1/auth/oidc/callback
|
||||
response_type=code
|
||||
scope=openid profile email tenants
|
||||
state=...
|
||||
```
|
||||
|
||||
### 4. Baron SSO가 login_challenge 발급
|
||||
|
||||
```http
|
||||
302 Location: https://sso.hmac.kr/login?login_challenge=...
|
||||
```
|
||||
|
||||
### 5. tdc114plus-auth가 Baron SSO headless link init 호출
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/api/v1/auth/headless/link/init
|
||||
```
|
||||
|
||||
요청 주요 값:
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "tdc114plus-auth RP client_id",
|
||||
"client_assertion": "tdc114plus-auth가 개인키로 서명한 JWT",
|
||||
"loginId": "01091365338",
|
||||
"login_challenge": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Baron SSO 응답
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "pending",
|
||||
"pendingRef": "...",
|
||||
"interval": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 7. tdc114plus-auth가 앱에 pendingRef 반환
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "pending",
|
||||
"pendingRef": "...",
|
||||
"pollInterval": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 8. 앱이 poll 시작
|
||||
|
||||
```http
|
||||
POST http://127.0.0.1:5001/api/v1/auth/link/poll
|
||||
```
|
||||
|
||||
요청:
|
||||
|
||||
```json
|
||||
{
|
||||
"pendingRef": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### 9. tdc114plus-auth가 Baron SSO poll 호출
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/api/v1/auth/headless/link/poll
|
||||
```
|
||||
|
||||
요청 주요 값:
|
||||
|
||||
```json
|
||||
{
|
||||
"client_id": "tdc114plus-auth RP client_id",
|
||||
"client_assertion": "tdc114plus-auth가 개인키로 서명한 JWT",
|
||||
"pendingRef": "..."
|
||||
}
|
||||
```
|
||||
|
||||
## 운영 점검 기준 추가
|
||||
|
||||
2026-07-20 기준 실제 점검에서 아래 사실을 확인했다.
|
||||
|
||||
- 앱에서 `link/init` 요청이 로컬 `tdc114plus-auth:5001`에 정상 도달할 수 있다.
|
||||
- `pendingRef` 생성과 `link/poll` 반복도 서버 로그에서 확인할 수 있다.
|
||||
- 실기기 `adb reverse tcp:5001 tcp:5001`까지 정상이어도, 실제 사용자 휴대폰에 문자 링크가 도착하지 않을 수 있다.
|
||||
|
||||
이 경우의 판단 기준은 아래와 같다.
|
||||
|
||||
1. `link/init` 로그가 찍히고 `pendingRef`가 생성되면 앱 -> auth broker 구간은 우선 정상이다.
|
||||
2. 이후 `link/poll`이 계속 pending인데 사용자 휴대폰에 문자가 오지 않으면, 우선 Baron SSO 문자 발송 또는 SMS 연계 구간을 의심해야 한다.
|
||||
3. 즉 `pendingRef 생성 성공`은 `문자 실제 발송 성공`과 같은 뜻이 아니다.
|
||||
|
||||
### 10. 사용자가 SMS 링크 클릭
|
||||
|
||||
```http
|
||||
GET https://sso.hmac.kr/ko/verify-cc/...
|
||||
```
|
||||
|
||||
또는 내부적으로:
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/api/v1/auth/magic-link/verify
|
||||
```
|
||||
|
||||
### 11. Baron SSO는 브라우저에 승인 완료 화면 표시
|
||||
|
||||
```text
|
||||
https://sso.hmac.kr/ko/verify-complete
|
||||
```
|
||||
|
||||
여기서 앱으로 자동 이동하지 않는다. 현재 Baron SSO 정책상 정상이다.
|
||||
|
||||
### 12. 앱의 poll이 성공 감지
|
||||
|
||||
Baron SSO에서 `tdc114plus-auth`로 내려오는 값:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"redirectTo": "https://sso.hmac.kr/oidc/oauth2/auth?..."
|
||||
}
|
||||
```
|
||||
|
||||
### 13. tdc114plus-auth가 redirectTo 추적
|
||||
|
||||
```http
|
||||
GET https://sso.hmac.kr/oidc/oauth2/auth?...
|
||||
```
|
||||
|
||||
### 14. consent가 필요하면 consent 처리
|
||||
|
||||
```http
|
||||
GET https://sso.hmac.kr/api/v1/auth/consent?consent_challenge=...
|
||||
```
|
||||
|
||||
이후:
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/api/v1/auth/consent/accept
|
||||
```
|
||||
|
||||
### 15. Baron SSO가 최종 callback으로 code 전달
|
||||
|
||||
```http
|
||||
GET https://114-auth.hmac.kr/api/v1/auth/oidc/callback?code=...&state=...
|
||||
```
|
||||
|
||||
여기가 현재 필요한 redirect URI다.
|
||||
|
||||
### 16. tdc114plus-auth가 token exchange
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/oidc/oauth2/token
|
||||
```
|
||||
|
||||
주요 값:
|
||||
|
||||
```text
|
||||
grant_type=authorization_code
|
||||
code=...
|
||||
redirect_uri=https://114-auth.hmac.kr/api/v1/auth/oidc/callback
|
||||
client_id=tdc114plus-auth RP client_id
|
||||
client_assertion=...
|
||||
```
|
||||
|
||||
### 17. Baron SSO token 응답
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "...",
|
||||
"id_token": "...",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 3600
|
||||
}
|
||||
```
|
||||
|
||||
### 18. tdc114plus-auth가 앱용 세션 발급
|
||||
|
||||
앱 poll 응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"accessToken": "tdc114plus-auth 앱용 세션 JWT",
|
||||
"user": {
|
||||
"id": "...",
|
||||
"name": "...",
|
||||
"email": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 19. 앱이 직원검색/조직정보 호출
|
||||
|
||||
로컬 개발 기준:
|
||||
|
||||
```http
|
||||
GET http://127.0.0.1:5001/api/v1/integrations/org-context
|
||||
Authorization: Bearer 앱용 세션 JWT
|
||||
```
|
||||
|
||||
실서버 기준:
|
||||
|
||||
```http
|
||||
GET https://114-auth.hmac.kr/api/v1/integrations/org-context
|
||||
Authorization: Bearer 앱용 세션 JWT
|
||||
```
|
||||
|
||||
## 그럼 https://114.hmac.kr/auth/callback은 무엇인가
|
||||
|
||||
아래 구조에서 필요했던 URI다.
|
||||
|
||||
```text
|
||||
앱이 Baron SSO에 직접 OIDC 로그인 요청
|
||||
-> Baron SSO 로그인
|
||||
-> Baron SSO가 앱 App Link로 code 전달
|
||||
-> 앱이 직접 token exchange
|
||||
```
|
||||
|
||||
그때 필요한 redirect URI가 아래 값이었다.
|
||||
|
||||
```text
|
||||
https://114.hmac.kr/auth/callback
|
||||
```
|
||||
|
||||
하지만 지금 구조는 바뀌었다.
|
||||
|
||||
```text
|
||||
앱이 직접 Baron SSO OIDC callback을 받지 않음
|
||||
앱은 tdc114plus-auth에만 요청함
|
||||
OIDC callback은 tdc114plus-auth가 받음
|
||||
```
|
||||
|
||||
그래서 현재 필수 callback은 아래 값이다.
|
||||
|
||||
```text
|
||||
https://114-auth.hmac.kr/api/v1/auth/oidc/callback
|
||||
```
|
||||
|
||||
## 정리 표
|
||||
|
||||
| 항목 | 현재 필요 여부 | 용도 |
|
||||
| --- | --- | --- |
|
||||
| `https://114.hmac.kr/auth/callback` | 필수 아님 | 예전 앱 직접 OIDC/PKCE App Link callback |
|
||||
| `https://114-auth.hmac.kr/api/v1/auth/oidc/callback` | 필요 | `tdc114plus-auth`가 Baron SSO authorization code 받는 callback |
|
||||
| `https://114-auth.hmac.kr/.well-known/jwks.json` | 필요 | Baron SSO가 `tdc114plus-auth` client_assertion 서명 검증 |
|
||||
| `https://114-auth.hmac.kr/api/v1/auth/link/init` | 필요 | 앱이 중계서버에 링크 발송 요청 |
|
||||
| `https://114-auth.hmac.kr/api/v1/auth/link/poll` | 필요 | 앱이 승인 상태 확인 |
|
||||
|
||||
## 현재 판단
|
||||
|
||||
Baron SSO 쪽에 TDC114PLUS 앱 RP를 계속 유지할 필요는 현재 흐름 기준으로 낮다.
|
||||
|
||||
정식 구조를 단순화하려면 `tdc114plus-auth` RP 하나만 남기는 방향이 맞다.
|
||||
|
||||
2026-07-15 작업으로 앱 코드 안의 `/auth/callback` 직접 수신 흔적은 제거했다.
|
||||
|
||||
제거한 항목:
|
||||
|
||||
- AndroidManifest의 `https://114.hmac.kr/auth/callback` App Link intent-filter
|
||||
- Flutter GoRouter의 `/auth/callback` route
|
||||
- 앱 직접 OIDC/PKCE callback 화면
|
||||
- 앱 직접 OIDC/PKCE token exchange 코드
|
||||
- startup의 Windows App Link 테스트 서버 강제 확인
|
||||
|
||||
남겨둘 수 있는 항목:
|
||||
|
||||
- 이 문서 안의 `https://114.hmac.kr/auth/callback` 언급은 과거 구조 설명과 혼선 방지를 위한 기록이다.
|
||||
@@ -0,0 +1,204 @@
|
||||
# tdc114plus 배포 구조 마이그레이션 표
|
||||
|
||||
작성일: 2026-07-19
|
||||
상태: v1.2
|
||||
|
||||
목적: `baron-sso-tdc114plus-api` 의존을 줄이고, 최종적으로 `tdc114plus` + `tdc114plus-auth` + Baron SSO 원본 `staging/prod` 구조로 전환하기 위해 현재 남아 있는 기능을 `배포 필수`, `개발 중 임시`, `제거 가능`으로 분류한다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- `docs/00_guide_tdc114plus_auth_broker_redirect_flow_2026-07-15.md`
|
||||
- `docs/00_policy_tdc114plus_auth_repo_2026-07-15.md`
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
|
||||
## 1. 목표 구조
|
||||
|
||||
최종 배포 목표 구조는 아래와 같다.
|
||||
|
||||
- 모바일 앱: `tdc114plus`
|
||||
- 인증/중계 서버: `tdc114plus-auth`
|
||||
- 인증/조직 원본: Baron SSO 원본 `staging` -> 안정화 후 `production`
|
||||
|
||||
제거 목표:
|
||||
|
||||
- 로컬 개발 전용 Baron worktree `baron-sso-tdc114plus-api`가 배포 시점의 필수 구성으로 남지 않도록 한다.
|
||||
|
||||
## 2. 현재 확인 기준
|
||||
|
||||
2026-07-19 당시 auth 서버에 실제 등록된 route는 아래와 같았다.
|
||||
|
||||
- `GET /health`
|
||||
- `GET /.well-known/jwks.json`
|
||||
- `GET /api/v1/auth/jwks.json`
|
||||
- `POST /api/v1/auth/link/init`
|
||||
- `POST /api/v1/auth/link/poll`
|
||||
- `GET /api/v1/integrations/org-context`
|
||||
|
||||
같은 날짜 기준 추가 확인:
|
||||
|
||||
- 당시 실행 중이던 5001 서버는 `/api/v1/profile-image`에 `404`를 반환했다.
|
||||
- 당시 체크아웃된 `tdc114plus-auth` 코드에도 `/api/v1/profile-image` route 등록이 없었다.
|
||||
- 따라서 프로필 사진 1순위/2순위/3순위 실기기 검증은 `profile-image` endpoint 복구 또는 대체 경로 확정 전에는 완료 처리할 수 없다.
|
||||
|
||||
2026-07-20 추가 확인:
|
||||
|
||||
- 실기기와 로컬 `tdc114plus-auth:5001` 연결 자체는 정상이다.
|
||||
- `adb reverse tcp:5001 tcp:5001` 정상 확인했다.
|
||||
- 앱에서 `link/init` 호출 후 `pendingRef` 생성과 `link/poll` 반복도 서버 로그로 확인했다.
|
||||
- 따라서 같은 날짜 기준 로그인 end-to-end 막힘의 주 blocker는 `앱/로컬 auth broker 연결`이 아니라 `Baron SSO 문자 링크 실제 발송 또는 SMS 연계 구간`이다.
|
||||
- `tdc114plus-auth`에 `GET /api/v1/profile-image` route를 복구했고, 미인증 호출 기준 `401 unauthorized`가 반환되는 것을 확인했다. 즉 route 부재 `404` 상태는 해소됐다.
|
||||
- 로그인 정상화 후 `NAVER_WORKS`와 `BARON_UUID_R2` source가 서버 로그와 실기기 화면에서 확인됐다.
|
||||
- 네이버웍스 원본 `302 Location` URL은 앱에서 직접 열 수 없는 경우가 있어, `tdc114plus-auth`에 `GET /api/v1/profile-image/naver-photo` 프록시 route를 추가했다.
|
||||
- 프록시 route는 네이버웍스 Access Token으로 실제 이미지 바이너리를 받아 앱에 `image/jpeg`로 내려준다.
|
||||
|
||||
## 2-A. 현재 사용 API 목록
|
||||
|
||||
2026-07-20 기준 신규앱과 `tdc114plus-auth`가 실제 작업 기준으로 삼는 API는 아래와 같이 분류한다.
|
||||
|
||||
| 구분 | Method | Path | 호출 주체 | 현재 판단 | 용도 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 앱 중계 로그인 시작 | `POST` | `/api/v1/auth/link/init` | `tdc114plus` -> `tdc114plus-auth` | 현재 사용 | 앱에서 전화번호 기준 로그인 링크 요청 |
|
||||
| 앱 중계 로그인 확인 | `POST` | `/api/v1/auth/link/poll` | `tdc114plus` -> `tdc114plus-auth` | 현재 사용 | 문자 링크 승인 후 앱 세션 발급 확인 |
|
||||
| 앱 세션 JWKS | `GET` | `/api/v1/auth/jwks.json` | Baron/RP 검증 또는 내부 검증 | 현재 사용 | 앱 세션/JWT 검증 키 제공 |
|
||||
| 조직/직원 중계 | `GET` | `/api/v1/integrations/org-context` | `tdc114plus` -> `tdc114plus-auth` | 현재 핵심 사용 | 직원검색, 조직도, `members[].id` UUID 확보 |
|
||||
| 프로필 사진 lookup | `GET` | `/api/v1/profile-image` | `tdc114plus` -> `tdc114plus-auth` | 현재 사용 | NAVER WORKS -> Baron UUID R2 -> DEFAULT 판단 |
|
||||
| 네이버웍스 사진 프록시 | `GET` | `/api/v1/profile-image/naver-photo` | `tdc114plus` -> `tdc114plus-auth` | 현재 사용 | NAVER WORKS 원본 URL 직접 노출 없이 `image/jpeg` 제공 |
|
||||
| 원본 조직/직원 API | `GET` | `https://sadmin.hmac.kr/api/v1/integrations/org-context` | `tdc114plus-auth` -> Baron SSO 원본 | 현재 핵심 원본 | 조직/직원 원본 데이터 조회, 앱에 key/secret 비노출 |
|
||||
| Baron 링크 로그인 시작 원본 | `POST` | `https://sso.hmac.kr/api/v1/auth/headless/link/init` | `tdc114plus-auth` -> Baron SSO 원본 | 현재 사용 | 실제 문자 링크 생성/발송 요청 |
|
||||
| Baron 링크 로그인 확인 원본 | `POST` | `https://sso.hmac.kr/api/v1/auth/headless/link/poll` | `tdc114plus-auth` -> Baron SSO 원본 | 현재 사용 | pendingRef 승인 상태 확인 |
|
||||
| Baron 매직 링크 검증 | `POST` | `https://sso.hmac.kr/api/v1/auth/magic-link/verify` | 문자 링크/Baron SSO 원본 흐름 | 연동 참고 | 사용자가 문자 링크를 눌렀을 때 승인 처리 후보/참고 경로 |
|
||||
| NAVER WORKS 사진 조회 | `GET` | `https://www.worksapis.com/v1.0/users/{userId}/photo` | `tdc114plus-auth` -> NAVER WORKS | 현재 사용 | 프로필 사진 1순위 조회, `302 Location` 및 프록시 바이너리 응답 기반 |
|
||||
|
||||
현재 기준에서 직접 사용하지 않는 API는 아래처럼 둔다.
|
||||
|
||||
| 구분 | Method | Path | 현재 판단 | 이유 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 공개 조직도 | `GET` | `/api/v1/public/orgchart` | 참고 API | 공유 링크/공개 조회 성격이므로 신규앱 내부 기준 데이터는 `integrations/org-context`로 유지 |
|
||||
| 레거시 직원목록 | `GET` | `/api/v1/tdc114plus/directory/employees` | 제거 대상 | `org-context` 기반 재구성으로 대체 |
|
||||
| 레거시 직원상세 | `GET` | `/api/v1/tdc114plus/directory/employees/{employeeId}` | 제거 대상 | `org-context members[]` 또는 auth proxy 보강으로 대체 |
|
||||
| 레거시 테넌트 목록 | `GET` | `/api/v1/tdc114plus/organization/tenants` | 제거 대상 | `org-context tenants/tree` 기준으로 대체 |
|
||||
| 레거시 조직도 | `GET` | `/api/v1/tdc114plus/organization/orgchart` | 제거 대상 | `org-context tree` 기준으로 대체 |
|
||||
| 레거시 전화번호 로그인 | `POST` | `/api/v1/tdc114plus/auth/phone-login` | 제거 대상 | 현재 기본 로그인은 `tdc114plus-auth link/init/link/poll` 중계 흐름 |
|
||||
|
||||
## 3. 기능 분류표
|
||||
|
||||
| 기능/자산 | 현재 위치 | 현재 용도 | 분류 | 목표 방향 | 비고 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 앱 UI/상태관리 | `tdc114plus` | 모바일 앱 본체 | 배포 필수 | 유지 | 최종 배포 직접 대상 |
|
||||
| 링크 로그인 진입 `link/init` | `tdc114plus-auth` | 앱 로그인 시작 | 배포 필수 | 유지 | Baron SSO headless/link upstream 호출 |
|
||||
| 링크 로그인 완료 `link/poll` | `tdc114plus-auth` | 앱 세션 발급 | 배포 필수 | 유지 | 2026-07-19 기준 user 메타데이터 확장 반영 완료 |
|
||||
| 앱 세션 JWT 발급/검증 | `tdc114plus-auth` | 앱 인증 유지 | 배포 필수 | 유지 | 앱 전용 세션 계층 |
|
||||
| JWKS 제공 | `tdc114plus-auth` | Baron RP/JWKS 연계 | 배포 필수 | 유지 | 도메인 기준 배포 필요 |
|
||||
| org-context proxy | `tdc114plus-auth` | 앱이 Baron key 없이 조직도 조회 | 배포 필수 | 유지 | staging/prod 원본 의존 |
|
||||
| Baron OIDC authorization / token / consent 흐름 | Baron SSO 원본 | 인증 원본 | 배포 필수 | Baron 원본 의존 | 로컬 worktree 필수 아님 |
|
||||
| Baron headless `link/init`, `link/poll` | Baron SSO 원본 | 문자 링크 승인 원본 | 배포 필수 | Baron 원본 의존 | auth 서버가 소비 |
|
||||
| `GET /api/v1/integrations/org-context` 원본 | Baron SSO 원본 | 조직/직원 원본 데이터 | 배포 필수 | Baron 원본 의존 | 앱은 auth proxy 또는 직접 staging 기준 확인 |
|
||||
| `/api/v1/tdc114plus/directory/employees` | `baron-sso-tdc114plus-api` | 과거 직원검색 경로 | 제거 가능 | `org-context` 중심으로 교체 | 레거시 흔적 |
|
||||
| `/api/v1/tdc114plus/organization/tenants` | `baron-sso-tdc114plus-api` | 과거 테넌트 목록 경로 | 제거 가능 | `org-context` 중심으로 교체 | 레거시 흔적 |
|
||||
| `/api/v1/tdc114plus/organization/orgchart` | `baron-sso-tdc114plus-api` | 과거 조직도 경로 | 제거 가능 | `org-context` 중심으로 교체 | 레거시 흔적 |
|
||||
| `/api/v1/tdc114plus/auth/phone-login` | `baron-sso-tdc114plus-api` | 과거 예외 로그인 seed | 제거 가능 | 기본 로그인 경로에서 제외 | 테스트용 예외 경로만 검토 |
|
||||
| 로컬 Baron compose runtime | `baron-sso-tdc114plus-api` | 로컬 재현/비교 | 개발 중 임시 | staging/prod 기준 검증으로 축소 | 배포 필수 구성 아님 |
|
||||
| 프로필 사진 `/api/v1/profile-image` | `tdc114plus-auth` | NAVER WORKS -> UUID -> DEFAULT | 배포 필수 | auth 서버에 유지 | 2026-07-20 route 복구 및 실기기 확인 |
|
||||
| 네이버웍스 사진 프록시 `/api/v1/profile-image/naver-photo` | `tdc114plus-auth` | NAVER WORKS 이미지 바이너리 프록시 | 배포 필수 | auth 서버에 유지 | 원본 Location 직접 노출 방지 |
|
||||
| PostgreSQL 기반 프로필 매핑안 | `tdc114plus-auth` 과거 검토 | 사진 fallback 대안 | 제거 가능 | 운영 기본안에서 제외 | 보류 대안 |
|
||||
|
||||
## 3-A. `baron-sso-tdc114plus-api` -> `tdc114plus-auth` 흡수 가능 기능 표
|
||||
|
||||
| 기능 | 현재 기준 | `tdc114plus-auth` 흡수 가능 여부 | 이유 | 현재 상태 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 앱 로그인 시작/완료 | 이미 `tdc114plus-auth` 담당 | 완료 | 앱 전용 broker 책임과 일치 | 유지 |
|
||||
| 앱 세션 JWT 발급/검증 | 이미 `tdc114plus-auth` 담당 | 완료 | 모바일 세션 경계는 auth 서버 책임 | 유지 |
|
||||
| 로그인 user 메타데이터 반환 | `tdc114plus-auth` 담당 | 완료 | 앱이 초기 컨텍스트에 바로 사용 가능 | 2026-07-19 확장 반영 |
|
||||
| Baron org-context key 은닉 proxy | 이미 `tdc114plus-auth` 담당 | 완료 | 앱에 key/secret 비노출 | 유지 |
|
||||
| 직원/조직 초기 컨텍스트 계산 보조 | 일부 앱 fallback 혼재 | 가능 | auth 응답 메타데이터가 충분하면 앱 fallback 감소 | 후속 검증 필요 |
|
||||
| 프로필 사진 lookup endpoint | `tdc114plus-auth` | 완료 | 사진 우선순위 정책은 auth 서버가 가장 자연스러움 | 2026-07-20 route 복구 및 실기기 확인 |
|
||||
| 네이버웍스 사진 프록시 endpoint | `tdc114plus-auth` | 완료 | 네이버웍스 원본 URL을 앱이 직접 열 수 없는 케이스를 서버가 흡수 | 배포 필수 기능으로 유지 |
|
||||
| `/api/v1/tdc114plus/directory/*` 레거시 API | `baron-sso-tdc114plus-api` | 불필요 | org-context 중심 구조와 중복 | 제거 대상 |
|
||||
| `/api/v1/tdc114plus/organization/*` 레거시 API | `baron-sso-tdc114plus-api` | 불필요 | org-context 중심 구조와 중복 | 제거 대상 |
|
||||
| 로컬 Baron compose runtime | `baron-sso-tdc114plus-api` | 흡수 대상 아님 | 개발용 재현 자산이지 auth 기능이 아님 | 축소 대상 |
|
||||
| Baron 원본 로그인/consent/token 발급 | Baron SSO 원본 | 흡수 불가 | 공식 인증 원본이므로 대체 대상 아님 | staging/prod 의존 유지 |
|
||||
|
||||
## 3-B. 제거 마이그레이션 실행 표
|
||||
|
||||
아래 표는 `baron-sso-tdc114plus-api`에 남아 있는 흔적을 실제 작업 단위로 쪼갠 것이다.
|
||||
|
||||
| 구분 | 현재 남은 흔적 | 실제 사용 주체 | 목표 처리 | 선행 조건 | 최종 판단 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 로그인 진입 | `/api/v1/tdc114plus/auth/phone-login` | 앱 구버전/초기 테스트 흔적 | 신규앱 경로에서 제거 | 현재 앱이 `link/init`, `link/poll`만 쓰는지 재확인 | 제거 가능 |
|
||||
| 직원검색 목록 | `/api/v1/tdc114plus/directory/employees` | 앱 일부 코드/테스트 흔적 | `org-context` 재구성 결과로 완전 대체 | 목록/검색/상세가 `org-context` 기준으로 동일 동작 | 제거 가능 |
|
||||
| 직원 상세 | `/api/v1/tdc114plus/directory/employees/:id` | 앱 일부 코드 흔적 | `org-context members[]` 기반 또는 auth proxy 보강으로 대체 | 현재 상세 화면 필요 필드 표 확정 | 제거 가능 |
|
||||
| 회사/테넌트 목록 | `/api/v1/tdc114plus/organization/tenants` | 앱 일부 코드/테스트 흔적 | `org-context tenants[]`로 대체 | 현재 tenant chip/초기 선택 로직 안정화 | 제거 가능 |
|
||||
| 조직도 트리 | `/api/v1/tdc114plus/organization/orgchart` | 앱 일부 코드/테스트 흔적 | `org-context tree + tenants[]`로 대체 | 조직도 화면 회귀 검증 | 제거 가능 |
|
||||
| 조직도 credential 은닉 | Baron 전용 key/secret 직접 처리 필요성 | 신규앱 | `tdc114plus-auth /api/v1/integrations/org-context` 유지 | app session + proxy 정상 유지 | auth에 유지 |
|
||||
| 앱 세션 발급 | Baron 원본에 없는 앱 전용 세션 계층 | 신규앱 | `tdc114plus-auth` 유지 | 현재 JWT 검증 안정화 | auth에 유지 |
|
||||
| 프로필 이미지 lookup | `/api/v1/profile-image` auth 구현 | 신규앱 | auth에 유지 | 1순위/2순위 실기기 확인 완료, DEFAULT 확대 검증 | auth에 유지 |
|
||||
| 로컬 Baron runtime | worktree 기동/비교 환경 | 개발자 로컬 | 배포 필수 구성에서 제외 | staging/prod 기준 검증 루틴 확보 | 개발 전용 유지 |
|
||||
|
||||
## 3-C. 워크스페이스별 최종 역할 표
|
||||
|
||||
| 워크스페이스 | 오늘 기준 역할 | 배포 직접 관여 | 비고 |
|
||||
| --- | --- | --- | --- |
|
||||
| `tdc114plus` | 모바일 앱 UI, 상태관리, 사진 fallback, 직원검색/조직도 화면 | 예 | 최종 APK/앱 배포 대상 |
|
||||
| `tdc114plus-auth` | 앱 전용 인증 broker, 앱 세션 JWT, org-context proxy, profile-image lookup/proxy | 예 | 신규앱 전용 중계서버 |
|
||||
| `baron-sso-tdc114plus-api` | 과거 레거시 API 검증, 로컬 비교, 흔적 확인용 worktree | 아니오 | 제거/축소 대상 |
|
||||
| Baron SSO staging/prod 원본 | 실제 OIDC, 문자 링크, org-context 원본 | 예 | 신규앱의 최종 외부 의존 원본 |
|
||||
|
||||
## 4. 바로 이어서 손봐야 하는 항목
|
||||
|
||||
### 4.1 `tdc114plus-auth`에서 유지하되 보강이 필요한 것
|
||||
|
||||
1. `link/poll` 응답의 사용자 메타데이터 확장
|
||||
- 2026-07-19 기준 아래 항목을 응답과 앱 세션 JWT `user` 클레임에 함께 담도록 반영했다.
|
||||
- `tenantSlug`
|
||||
- `tenantId`
|
||||
- `tenantName`
|
||||
- `department`
|
||||
- `grade`
|
||||
- `position`
|
||||
- `jobTitle`
|
||||
- 남은 확인:
|
||||
- 실기기 로그인 후 앱에서 이 값들이 실제로 저장/사용되는지 확인
|
||||
- 실제 Baron upstream 응답마다 중첩 구조 차이가 없는지 샘플 확대 확인
|
||||
|
||||
2. `/api/v1/profile-image` route 상태 재정렬
|
||||
- 2026-07-20 기준 `tdc114plus-auth`에 route를 복구했다.
|
||||
- 미인증 호출 기준 `401 unauthorized`가 반환되어 route 등록은 확인했다.
|
||||
- 네이버웍스 `302 Location` 원본 URL 직접 사용 시 `400 Authentication failed`가 발생할 수 있어 `/api/v1/profile-image/naver-photo` 프록시를 추가했다.
|
||||
- 2026-07-20 기준 NAVER WORKS 1순위와 Baron UUID R2 2순위는 실기기 화면 및 서버 로그로 확인했다.
|
||||
- 남은 확인은 DEFAULT 3순위와 직원 상세/조직도/즐겨찾기 화면 확대 검증이다.
|
||||
|
||||
3. OIDC callback 실서버 기준 정합성 유지
|
||||
- 현재 문서 기준 redirect URI는 `https://114-auth.hmac.kr/api/v1/auth/oidc/callback`
|
||||
- 실제 배포 기준 도메인/프록시와 일치하게 유지해야 한다.
|
||||
|
||||
### 4.2 `baron-sso-tdc114plus-api`에서 빼야 하는 것
|
||||
|
||||
1. `/api/v1/tdc114plus/...` 전용 경로에 대한 앱 직접 의존
|
||||
2. 로컬 Baron compose가 항상 떠 있어야만 앱이 개발되는 구조
|
||||
3. 사진 fallback용 PostgreSQL 기본안
|
||||
|
||||
## 5. 마이그레이션 순서 제안
|
||||
|
||||
1. `tdc114plus-auth link/poll` 사용자 메타데이터 확장을 먼저 반영한다. 완료.
|
||||
2. 실기기 로그인 후 저장된 user/session에서 `tenantSlug` 등 메타데이터가 실제로 유지되는지 확인한다. 진행 예정.
|
||||
3. Baron SSO 문자 링크 실제 발송/SMS 연계 이슈 답변을 먼저 받는다. 진행 중.
|
||||
4. `/api/v1/profile-image`를 현재 auth 코드 기준으로 복구한다. 완료.
|
||||
5. 앱 코드에서 남아 있는 `/api/v1/tdc114plus/...` 직접 의존을 다시 표로 수집한다. 진행 예정.
|
||||
6. 조직/직원 데이터는 `org-context` 기준으로만 유지되도록 경계를 정리한다. 진행 예정.
|
||||
7. 로컬 Baron worktree 없이도 `staging` 기준 로그인 + 직원검색 + 조직도 + 사진 fallback이 되는지 검증한다. 진행 예정.
|
||||
8. 그 다음에 `production` 승격 체크리스트를 만든다. 진행 예정.
|
||||
|
||||
## 6. 현재 판단
|
||||
|
||||
2026-07-20 기준 현재 가장 중요한 사실은 아래 두 가지다.
|
||||
|
||||
1. `baron-sso-tdc114plus-api`는 이미 최종 배포 직접 대상이라기보다 개발 중 임시 worktree로 보는 것이 맞다.
|
||||
2. `profile-image`는 `tdc114plus-auth`에 유지할 배포 필수 기능으로 정리한다. 네이버웍스 원본 URL 직접 노출 문제는 auth 프록시로 처리한다.
|
||||
|
||||
따라서 다음 실제 작업은 아래 순서가 가장 안전하다.
|
||||
|
||||
1. DEFAULT 기본 아바타와 직원 상세/조직도/즐겨찾기 이미지 규칙 확대 검증
|
||||
2. auth 응답 메타데이터 실기기 반영 유지 확인
|
||||
3. 실기기 기능 재검증
|
||||
4. 레거시 경로 제거
|
||||
@@ -0,0 +1,194 @@
|
||||
# tdc114plus 외부 API 사용 및 앱 내 활용 정리
|
||||
|
||||
작성일: 2026-07-03
|
||||
최종 개정일: 2026-07-20
|
||||
상태: v3.4
|
||||
|
||||
목적: `tdc114plus` 앱이 Baron SSO가 이미 제공하는 API를 어떤 원칙으로 직접 소비해야 하는지, 그리고 어떤 인증값이 앱에 들어가면 안 되는지 정리한다.
|
||||
|
||||
상위 기준 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
|
||||
## 1. 한 줄 결론
|
||||
|
||||
- 신규 앱은 Baron SSO에 추가되는 별도 `RP`다.
|
||||
- Baron SSO 원본에 신규앱 전용 `/api/v1/tdc114plus/...` API를 추가하지 않는다는 현재 기준을 따른다.
|
||||
- 단, 앱 비밀값 보호와 모바일 세션 유지를 위해 `tdc114plus-auth` 중계서버는 별도 운영한다.
|
||||
- 앱은 Baron SSO/조직도 사이트가 이미 제공하는 공식 API를 직접 소비하는 클라이언트다.
|
||||
- 다만 앱에 넣으면 안 되는 운영 Key나 비밀값은 계속 서버/운영자 전용으로 본다.
|
||||
- 현재 코드에 남아 있는 `tdc114plus` 전용 API 가정은 레거시 흔적으로 보고, 기능 보존 테스트를 동반해 점진 제거한다.
|
||||
|
||||
## 2. 현재 API 계층 해석
|
||||
|
||||
2026-07-08 기준 현재 해석은 아래와 같다.
|
||||
|
||||
| 계층 | 호출 주체 | 용도 | 비고 |
|
||||
| --- | --- | --- | --- |
|
||||
| Baron 공개/기존 API | Flutter 앱 | 조직도, 조직/사용자 데이터 조회 | Swagger에 노출된 endpoint 기준으로 재확인 필요 |
|
||||
| Baron 로그인/웹 절차 | Flutter 앱 + 사용자 브라우저/링크 | RP 로그인, 승인 링크 처리 | Hosted Login + PKCE 원칙 |
|
||||
| 운영 Key 기반 외부 연동 API | 운영 서버 또는 운영자 | 원본 데이터 조회 또는 관리자성 연동 | 모바일 앱 직접 탑재 금지 |
|
||||
|
||||
정리하면, Flutter 앱은 Baron SSO 원본에 신규앱 전용 API를 새로 요구하지 않는다. 대신 앱에 노출되면 안 되는 key/secret, Baron SSO 링크 로그인 중계, 앱 세션 JWT, 프로필 이미지 lookup은 `tdc114plus-auth`가 맡는다.
|
||||
|
||||
## 3. 신규 앱의 인증 해석
|
||||
|
||||
- `tdc114plus`는 Baron SSO에 추가되는 별도 `RP(Relying Party)`다.
|
||||
- 앱 로그인은 Baron SSO의 RP 로그인 절차 일부다.
|
||||
- 기본 인증 방식은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`다.
|
||||
- 흐름은 `앱 -> Baron SSO 인증 URL 열기 -> Hosted Login 화면에서 휴대폰번호 입력 -> 문자/메일 링크 인증 -> App Link callback -> token 교환 -> 앱 로그인 완료`다.
|
||||
- 앱은 승인 링크를 직접 만들지 않고, 휴대폰번호/인증정보도 직접 처리하지 않는다.
|
||||
- Swagger의 `phone-login`, `headless`, `enchanted-link`, `sms`, `qr` 계열 Auth API는 Baron SSO Hosted Login 화면과 서버 내부 구현의 참고 대상이다.
|
||||
- Flutter 앱 기본 구현은 위 Auth API를 직접 조합하지 않고, OIDC authorization endpoint와 token endpoint를 사용한다.
|
||||
- 로그인 성공 후 Baron SSO가 조직도 API 호출에 필요한 연동 키 묶음을 전달하면 앱은 이를 선택적 세션 값으로 받아 사용할 준비를 한다.
|
||||
- 해당 기능이 Baron SSO에 구현되기 전까지는 staging `org-context` 검증을 위해 로컬 비추적 env/Dart define의 고정 키 fallback을 사용한다.
|
||||
|
||||
2026-07-20 현재 로컬 실기기 검증 흐름에서는 모바일 앱이 Baron SSO 원본을 직접 호출하지 않고 `tdc114plus-auth`의 아래 중계 API를 호출한다.
|
||||
|
||||
```http
|
||||
POST /api/v1/auth/link/init
|
||||
POST /api/v1/auth/link/poll
|
||||
GET /api/v1/integrations/org-context
|
||||
GET /api/v1/profile-image
|
||||
```
|
||||
|
||||
위 API는 Baron SSO 원본에 새로 추가한 신규앱 API가 아니라, 신규앱 전용 중계서버 `tdc114plus-auth`의 API다.
|
||||
|
||||
## 4. 앱이 실제로 호출할 인증 API
|
||||
|
||||
현재 저장소 코드에는 아래 레거시 경로 가정이 남아 있거나 제거 대상이다.
|
||||
|
||||
```http
|
||||
POST /api/v1/auth/headless/phone-login
|
||||
POST /api/v1/auth/headless/link/poll
|
||||
POST /api/v1/tdc114plus/auth/phone-login
|
||||
```
|
||||
|
||||
하지만 2026-07-08 사용자 확인 기준으로 `tdc114plus 앱 전용 API는 없다`.
|
||||
|
||||
따라서 위 경로들 중 legacy `POST /api/v1/tdc114plus/auth/phone-login`을 포함한 레거시 표기는 `확정 계약`이 아니라 `기존 로컬/가정 기반 경로`로 격하한다.
|
||||
|
||||
처리 원칙:
|
||||
|
||||
1. 먼저 Swagger에서 대응 endpoint를 찾는다.
|
||||
2. 그 다음 앱 DTO/repository를 대체 계약으로 맞춘다.
|
||||
3. mock/real 테스트와 실제 화면 검증이 끝난 뒤에만 옛 경로를 제거한다.
|
||||
|
||||
현재 확정 사실:
|
||||
|
||||
- 신규 앱의 기본 로그인 정책은 Hosted Login + PKCE다.
|
||||
- 사용자가 링크를 클릭해야 앱 로그인이 완료된다는 정책은 유지한다.
|
||||
- 다만 링크 발송/승인 처리는 앱이 직접 headless API로 수행하지 않고 Baron SSO Hosted Login 화면과 서버 내부 구현에 맡긴다.
|
||||
- Swagger에 `POST /api/v1/auth/phone-login` 또는 `POST /api/v1/auth/headless/phone-login`이 보이더라도, 앱의 기본 로그인 버튼은 이 API를 직접 호출하지 않는다.
|
||||
|
||||
## 5. 팀장 전달 외부 API 정보의 위치
|
||||
|
||||
현재 저장소 기준으로 팀장 전달 정보와 직접 연결되는 외부 연동 대상은 아래 API다.
|
||||
|
||||
```http
|
||||
GET https://sadmin.hmac.kr/api/v1/integrations/org-context
|
||||
X-Baron-Key-ID: {KEY_ID}
|
||||
X-Baron-Key-Secret: {KEY_SECRET}
|
||||
```
|
||||
|
||||
참고:
|
||||
|
||||
- Swagger UI: `https://sadmin.hmac.kr/api/docs#/Integrations/get_api_v1_integrations_org_context`
|
||||
- OpenAPI: `https://sadmin.hmac.kr/api/openapi.yaml`
|
||||
- 로컬 참고 문서: `docs/guide_baron_org_context_api_reference_2026-07-03.md`
|
||||
|
||||
중요 해석:
|
||||
|
||||
- 이 API는 앱 화면을 구성할 때 참고해야 하는 원본/공식 문서 계층이다.
|
||||
- 장기적으로는 로그인 성공 후 Baron SSO가 내려주는 조직도 API 연동 키를 사용한다.
|
||||
- 단기적으로는 Baron SSO의 키 전달 기능이 아직 미개발이므로, 개발/검증용 staging 고정 키를 로컬 비추적 env/Dart define에만 둔다.
|
||||
- tracked 문서, tracked 소스, 운영 APK 기본값에는 `X-Baron-Key-ID`, `X-Baron-Key-Secret` 실제 값을 넣지 않는다.
|
||||
|
||||
## 6. 앱이 실제로 호출하는 데이터 API
|
||||
|
||||
현재 저장소 코드에는 아래 레거시 데이터 경로 가정이 남아 있다.
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/directory/employees
|
||||
GET /api/v1/tdc114plus/directory/employees/{employeeId}
|
||||
GET /api/v1/tdc114plus/organization/tenants
|
||||
GET /api/v1/tdc114plus/organization/orgchart
|
||||
```
|
||||
|
||||
하지만 이 역시 `확정 계약`으로 보지 않는다.
|
||||
|
||||
현재 확인된 근거:
|
||||
|
||||
- `sadmin.hmac.kr`는 org-context 참고 host이지 `tdc114plus` 앱 route host는 아니다.
|
||||
- `sorg.hmac.kr/login?returnTo=%2Fchart`는 웹 로그인 진입 주소이며 JSON API가 아니라 HTML 응답을 돌려준다.
|
||||
- Swagger 화면에는 `Public /api/v1/public/orgchart` 같은 조직도 관련 공개 API 흔적이 보인다.
|
||||
|
||||
따라서 앞으로의 기준은 아래와 같다.
|
||||
|
||||
1. 조직도/가족사/사용자 조회는 Swagger에 실제로 존재하는 `integrations/org-context`, `public/orgchart` 기준으로 다시 잡는다.
|
||||
2. 현재 코드의 `/api/v1/tdc114plus/...` 경로는 전면 재확정 대상이다.
|
||||
3. 정확한 path, query, 응답 스키마가 확인되기 전에는 코드 경로를 확정 표현으로 문서화하지 않는다.
|
||||
4. 레거시 경로 정리는 `유지`, `교체`, `제거` 분류표를 먼저 만든 뒤 순차적으로 수행한다.
|
||||
|
||||
## 7. 원본 외부 API와 앱 기능의 연결
|
||||
|
||||
| 원본 정보 | 앱 또는 중간 가공 결과 | 앱 기능 |
|
||||
| --- | --- | --- |
|
||||
| 조직 트리 | `org-context` 또는 공개 `orgchart` 응답을 앱 내부 모델로 매핑 | 회사/조직 구조 표시 |
|
||||
| 조직 목록 | 상단 칩용 tenant/company 모델 | 상단 필터 칩 |
|
||||
| 조직 구성원 | 직원 목록/상세용 앱 모델 | 직원검색, 상세 |
|
||||
| 사용자 전화번호 | `phoneNumber`, `phoneDisplay` | 전화/문자 실행 |
|
||||
| 사용자 이메일/직급/직위/직무 | 동일 또는 유사 필드 | 상세 정보 표시 |
|
||||
|
||||
즉, 앱은 Swagger에 드러나는 원본/공개 응답을 앱 화면용 모델로 직접 매핑하는 구조로 전환될 수 있다.
|
||||
|
||||
## 8. 환경변수 및 보안 원칙
|
||||
|
||||
앱 측 런타임 값:
|
||||
|
||||
- `SSO_BASE_URL`
|
||||
- `TDC114_API_BASE`
|
||||
- `APP_VERSION`
|
||||
|
||||
서버 측 외부 API 연동 값 예시:
|
||||
|
||||
```env
|
||||
TDC114PLUS_ORG_CONTEXT_BASE_URL=https://sadmin.hmac.kr
|
||||
TDC114PLUS_ORG_CONTEXT_KEY_ID=
|
||||
TDC114PLUS_ORG_CONTEXT_KEY_SECRET=
|
||||
TDC114PLUS_ORG_CONTEXT_TENANT_SLUG=hanmac-family
|
||||
TDC114PLUS_ORG_CONTEXT_INCLUDE_USERS=true
|
||||
TDC114PLUS_ORG_CONTEXT_INCLUDE_USER_IDS=true
|
||||
```
|
||||
|
||||
추가 메모:
|
||||
|
||||
- 2026-07-10 기준 팀장 지시에 따라 원본 Baron API 기준 host는 `https://sadmin.hmac.kr/`를 사용한다.
|
||||
- 팀장 전달 운영 키(`CLIENT ID`, `X-Baron-Key-Secret`)는 로컬 비추적 env에만 반영하고 tracked 문서에는 직접 기록하지 않는다.
|
||||
- 실제 배포 전까지 신규앱에서 사용하는 Baron SSO API 참고 기준은 staging Swagger `https://sadmin.hmac.kr/api/docs#/`다.
|
||||
|
||||
보안 원칙:
|
||||
|
||||
- `X-Baron-Key-ID`, `X-Baron-Key-Secret` 실제 값은 tracked 앱 소스와 tracked 문서에 넣지 않는다.
|
||||
- 개발/검증 중 Baron SSO가 키 전달 기능을 제공하기 전까지는 비추적 env/Dart define fallback으로만 제한 사용한다.
|
||||
- 운영 APK에서는 로그인 성공 후 받은 세션 기반 연동 키 또는 별도 안전한 서버 중계 방식으로 전환한다.
|
||||
- 앱에는 공개 가능한 RP Client ID, issuer, redirect URI 같은 공개 설정만 기본값으로 둔다.
|
||||
- RP 비밀값, 승인 링크 생성용 내부 인증정보, 외부 API Key는 모두 서버 전용이다.
|
||||
- 앱이 저장하는 세션 정보는 운영 전 안전한 저장소 적용 여부를 재검토한다.
|
||||
|
||||
## 9. 팀 공유용 핵심 메시지
|
||||
|
||||
1. `tdc114plus`는 Baron SSO의 별도 RP다.
|
||||
2. 로그인은 Baron SSO Hosted Login + PKCE 방식이며, Baron SSO 화면에서 휴대폰번호 입력 후 사용자가 문자/메일 링크를 클릭해야 앱 로그인이 완료된다.
|
||||
3. 앱 전용 `tdc114plus` backend API는 없다는 현재 기준으로 재정렬한다.
|
||||
4. 앱은 Baron이 이미 제공하는 Swagger 공개 API를 직접 소비하는 클라이언트 앱이다.
|
||||
5. 운영 Key나 RP 비밀값은 모바일 앱과 저장소 tracked 파일에 두면 안 된다.
|
||||
|
||||
## 10. 현재 기준 주의사항
|
||||
|
||||
- `phone-login`은 개발용 fallback 경로일 뿐 기본 UX가 아니다.
|
||||
- 현재 코드에 남아 있는 `/api/v1/tdc114plus/...` path는 검증 전 가정일 수 있다.
|
||||
- 해당 가정 path 제거는 기능이 유지되는지 테스트한 뒤 단계적으로만 진행한다.
|
||||
- 실제 앱 구조는 `auth`, `directory`, `organization` feature별 repository 분리 기준으로 유지하되, endpoint는 Swagger 기준으로 다시 매핑해야 한다.
|
||||
- 실제 응답 정합성 검증 중이라, 세부 필드명과 사용 범위는 Swagger 기준으로 계속 재확인해야 한다.
|
||||
@@ -0,0 +1,57 @@
|
||||
# TDC114PLUS Headless/PKCE 계약 차이 검토
|
||||
|
||||
작성일: 2026-07-09
|
||||
상태: 정책 재정렬 완료, headless 직접 호출은 기본 흐름에서 제외
|
||||
|
||||
2026-07-09 결론:
|
||||
|
||||
- TDC114PLUS 앱의 기본 로그인은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`다.
|
||||
- 앱은 `/api/v1/auth/headless/...` API를 직접 호출하지 않는다.
|
||||
- 이 문서는 headless 직접 호출을 검토하던 시점의 계약 차이를 보존하되, 현재 실행 기준으로는 `참고/레거시 검토 문서`로 본다.
|
||||
|
||||
## 1. 확인된 RP 설정
|
||||
|
||||
- RP 유형: PKCE 공개 클라이언트
|
||||
- Client ID: `39d6190d-72f6-4a58-a84f-cdc5ece3e8af`
|
||||
- Redirect URI: `https://114.hmac.kr/auth/callback`
|
||||
- Client Secret: 없음
|
||||
- OIDC issuer: `https://sso.hmac.kr/oidc`
|
||||
|
||||
## 2. 확인된 표준 OIDC 기능
|
||||
|
||||
Discovery 문서에서 아래 기능을 확인했다.
|
||||
|
||||
- authorization code grant
|
||||
- token endpoint 인증 방식 `none`
|
||||
- PKCE `S256`
|
||||
- authorization, token, userinfo endpoint
|
||||
|
||||
따라서 공개 모바일 앱이 Client Secret 없이 PKCE verifier로 authorization code를 교환하는 표준 흐름은 지원된다.
|
||||
|
||||
## 3. Headless API 계약 차이
|
||||
|
||||
공식 Swagger의 아래 API는 `client_assertion`을 필수로 요구한다.
|
||||
|
||||
- `POST /api/v1/auth/headless/phone-login`
|
||||
- `POST /api/v1/auth/headless/link/poll`
|
||||
|
||||
Swagger는 `client_assertion`을 `private_key_jwt`라고 정의한다. 이를 모바일 앱이 직접 생성하려면 RP 개인키가 APK에 포함되어야 하므로 공개 PKCE 앱 보안 모델과 맞지 않는다.
|
||||
|
||||
## 4. 적용 정책
|
||||
|
||||
- Client ID는 공개 식별자이므로 APK에 포함한다.
|
||||
- Client Secret 또는 `private_key_jwt` 서명용 개인키는 APK에 포함하지 않는다.
|
||||
- 표준 PKCE 생성, state 검증, authorization code 교환은 앱에 구현한다.
|
||||
- 앱은 Baron SSO authorization endpoint를 열고, Baron SSO Hosted Login 화면이 휴대폰번호 입력과 문자/메일 링크 인증을 처리하게 한다.
|
||||
- headless API 직접 호출은 현재 앱 기본 구현에서 제외한다.
|
||||
- 추후 별도 신뢰 백엔드가 생기거나 Baron SSO가 모바일 공개 RP용 headless 계약을 제공하는 경우에만 별도 feature로 재검토한다.
|
||||
|
||||
## 5. Baron SSO 확인 요청
|
||||
|
||||
아래 질문은 앱이 headless API를 직접 호출해야 한다는 전제가 다시 살아날 때만 유효하다.
|
||||
|
||||
1. PKCE 공개 RP에서 `client_assertion` 생략이 가능한지
|
||||
2. 불가능하다면 단기 assertion 발급 endpoint가 있는지
|
||||
3. assertion의 issuer, subject, audience, 만료시간, 서명 알고리즘
|
||||
4. `login_challenge`를 모바일 앱이 얻는 공식 절차
|
||||
5. headless 승인 완료 후 `redirectTo`와 PKCE callback 연결 절차
|
||||
@@ -0,0 +1,234 @@
|
||||
# tdc114plus org-context 응답 매핑 판단서
|
||||
|
||||
작성일: 2026-07-08
|
||||
상태: v1.0
|
||||
|
||||
목적: Baron Swagger의 `GET /api/v1/integrations/org-context` 설명과 예시 응답을 기준으로, 현재 `tdc114plus` 앱 화면 요소에 어떤 필드를 직접 매핑할 수 있는지와 어떤 부분은 추가 가공이 필요한지 판단한다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
- `docs/00_guide_tdc114plus_external_api_usage_2026-07-03.md`
|
||||
- `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`
|
||||
|
||||
## 1. 결론
|
||||
|
||||
- `org-context`는 현재 기준으로 `조직도/직원 데이터 원형 API`로 매우 유력하다.
|
||||
- 특히 `tenantSlug` 기준 subtree, `tree`, `tenants`, `members` 구조는 `전체 > 회사 > 하위조직 > 개인` 탐색 정책과 잘 맞는다.
|
||||
- 다만 이 API는 `Integrations` 영역이며 `API Key`가 필요하므로, 모바일 앱이 운영 Key를 직접 넣고 호출하는 구조는 기본안으로 채택하면 안 된다.
|
||||
- 따라서 `데이터 구조 기준 API`로는 채택 가능하지만, `실기기 앱 직접 호출 방식`은 보안 검토가 끝나기 전까지 확정하지 않는다.
|
||||
|
||||
## 2. Swagger에서 확인된 사실
|
||||
|
||||
대상 API:
|
||||
|
||||
```http
|
||||
GET /api/v1/integrations/org-context
|
||||
```
|
||||
|
||||
특징:
|
||||
|
||||
- 계정 세션 없이 `API Key`로 조회
|
||||
- `tenantSlug`가 없으면 기본 `hanmac-family` subtree 반환
|
||||
- `includeUsers=false`이면 tenant members는 빈 배열
|
||||
- `includeUserIds=true`이면 `members[].id`, `members[].phone` 추가
|
||||
|
||||
주요 응답 구조:
|
||||
|
||||
- `scope.tenantId`
|
||||
- `scope.tenantSlug`
|
||||
- `tree`
|
||||
- `tenants[]`
|
||||
- `tenant.members[]`
|
||||
|
||||
즉, 조직 트리와 조직별 직접 소속 구성원 목록을 함께 주는 구조다.
|
||||
여기서 `tenant.members[]`와 `tenant.memberCount`는 해당 조직에 직접 붙어 있는 구성원 기준으로 해석한다.
|
||||
화면의 하위조직 카드에 표시하는 인원 수는 직접 소속 수가 아니라, 해당 조직과 모든 descendant 조직의 직접 소속 인원을 합산한 `subtree 인원 수`로 앱에서 계산한다.
|
||||
|
||||
## 3. 현재 앱 기능과의 적합도 판단
|
||||
|
||||
### 3.1 매우 잘 맞는 부분
|
||||
|
||||
1. 회사/가족사 칩
|
||||
- `tree.name`, `tree.slug`, `tenants[].name`, `tenants[].slug`, `parentId`
|
||||
- 현재 상단 칩 구조와 직접 연결 가능
|
||||
|
||||
2. 하위조직 drilldown
|
||||
- `tree.children[]`
|
||||
- `tenant.parentId`
|
||||
- 현재 정책의 `전체 > 회사 > 하위조직 > 개인` 탐색 구조와 잘 맞음
|
||||
|
||||
3. 조직별 소속 인원 표시
|
||||
- `tenant.members[]`
|
||||
- leaf 조직에서 직원 목록으로 진입하는 정책과 맞음
|
||||
- 비-leaf 조직의 `members[]`는 직접 소속 인원이므로, 하위조직 목록과 한 화면에 섞어 표시하지 않는다
|
||||
|
||||
4. 직원 상세 기본 텍스트
|
||||
- `members[].name`
|
||||
- `members[].email`
|
||||
- `members[].department`
|
||||
- `members[].grade`
|
||||
- `members[].position`
|
||||
- `members[].jobTitle`
|
||||
|
||||
5. 조직도 정렬 힌트
|
||||
- `members[].isOwner`
|
||||
- `members[].isLeader`
|
||||
- `members[].isPrimary`
|
||||
- 현재 `팀장 우선` 정렬 정책에 보조 신호로 활용 가능
|
||||
|
||||
### 3.2 조건부로 맞는 부분
|
||||
|
||||
1. 전화/문자 기능
|
||||
- `members[].phone`
|
||||
- 하지만 Swagger 설명상 `includeUserIds=true`일 때만 포함
|
||||
- 즉, 전화/문자 기능까지 쓰려면 `includeUserIds=true`가 사실상 필요
|
||||
|
||||
2. 직원 식별자 기반 상세/즐겨찾기
|
||||
- `members[].id`
|
||||
- 이것도 `includeUserIds=true`일 때만 포함
|
||||
- 즐겨찾기/상세/프로필 이미지 매핑 안정성을 높이려면 필요
|
||||
- 2026-07-15 실조회 기준 이 값은 실제 UUID 형식으로 내려오는 것을 확인했다
|
||||
|
||||
3. 초기 내 팀 뱃지 계산
|
||||
- `members[].department`와 `tenant.name` 매칭으로 어느 정도 가능
|
||||
- 다만 `department` 문자열과 tenant 이름이 항상 1:1 대응하는지 추가 확인 필요
|
||||
|
||||
### 3.3 그대로는 부족한 부분
|
||||
|
||||
1. 앱 현재 `Employee` 모델의 `tenantId`, `tenantName`, `tenantSlug`
|
||||
- `OrgContextMember` 안에는 tenant 정보가 직접 들어있지 않음
|
||||
- 따라서 `tenant.members[]`를 순회하며 `상위 tenant 정보`를 멤버에 주입하는 앱 내부 flatten 가공이 필요
|
||||
|
||||
2. 현재 `EmployeeListResponse.items` 형태
|
||||
- `org-context`는 `items[]` 응답이 아니라 `tree + tenants[] + tenant.members[]` 구조
|
||||
- 즉, 직원검색용 평탄 목록은 앱 내부에서 별도 생성해야 함
|
||||
|
||||
3. 현재 `TenantListResponse.items`
|
||||
- `org-context`는 `items[]` 래퍼가 아님
|
||||
- `tenants[]` 또는 `tree.children[]`를 `TenantSummary` 형태로 바꾸는 adapter 필요
|
||||
|
||||
4. `totalMemberCount`
|
||||
- Swagger 예시에는 `memberCount`는 보이지만 `totalMemberCount`는 보장되지 않음
|
||||
- 현재 앱 모델의 `totalMemberCount`는 앱 내부에서 descendant 포함 합산 계산이 필요
|
||||
- 예: `CM본부` 자체 직접 소속이 0명이라도 하위 `CM사업부`에 511명이 있으면 `CM본부` 카드에는 511명으로 표시한다
|
||||
- 반대로 leaf 조직의 직접 소속이 0명이면 leaf 진입 시 `검색 결과 없음` 표시가 정상일 수 있다
|
||||
|
||||
5. 프로필 사진 URL
|
||||
- `profileImageUrl` 필드는 없음
|
||||
- 사번/이미지 URL 직접 연결은 불가
|
||||
|
||||
## 4. 현재 Flutter 모델 기준 매핑 판단
|
||||
|
||||
### 4.1 `TenantSummary`
|
||||
|
||||
현재 필드:
|
||||
|
||||
- `id`
|
||||
- `name`
|
||||
- `slug`
|
||||
- `type`
|
||||
- `parentId`
|
||||
- `memberCount`
|
||||
- `totalMemberCount`
|
||||
|
||||
매핑 판단:
|
||||
|
||||
| 앱 필드 | org-context 소스 | 판단 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `tenant.id` | 직접 가능 |
|
||||
| `name` | `tenant.name` | 직접 가능 |
|
||||
| `slug` | `tenant.slug` | 직접 가능 |
|
||||
| `type` | `tenant.type` | 직접 가능 |
|
||||
| `parentId` | `tenant.parentId` | 직접 가능 |
|
||||
| `memberCount` | `tenant.memberCount` 또는 `tenant.members.length` | 직접 소속 수로 사용 |
|
||||
| `totalMemberCount` | 없음 | 앱 내부에서 subtree 합산 계산 필요 |
|
||||
|
||||
### 4.2 `Employee`
|
||||
|
||||
현재 필드:
|
||||
|
||||
- `id`
|
||||
- `name`
|
||||
- `phoneNumber`
|
||||
- `email`
|
||||
- `tenantId`
|
||||
- `tenantName`
|
||||
- `tenantSlug`
|
||||
- `department`
|
||||
- `grade`
|
||||
- `position`
|
||||
- `jobTitle`
|
||||
- `status`
|
||||
- `profileImageUrl`
|
||||
|
||||
매핑 판단:
|
||||
|
||||
| 앱 필드 | org-context 소스 | 판단 |
|
||||
| --- | --- | --- |
|
||||
| `id` | `member.id` | `includeUserIds=true` 필요 |
|
||||
| `name` | `member.name` | 직접 가능 |
|
||||
| `phoneNumber` | `member.phone` | `includeUserIds=true` 필요 |
|
||||
| `email` | `member.email` | 직접 가능 |
|
||||
| `tenantId` | 상위 `tenant.id` | 가공 필요 |
|
||||
| `tenantName` | 상위 `tenant.name` | 가공 필요 |
|
||||
| `tenantSlug` | 상위 `tenant.slug` | 가공 필요 |
|
||||
| `department` | `member.department` | 직접 가능 |
|
||||
| `grade` | `member.grade` | 직접 가능 |
|
||||
| `position` | `member.position` | 직접 가능 |
|
||||
| `jobTitle` | `member.jobTitle` | 직접 가능 |
|
||||
| `status` | 없음 또는 tenant status와 혼동 가능 | 재정의 필요 |
|
||||
| `profileImageUrl` | 없음 | 별도 정책 필요 |
|
||||
|
||||
## 5. 화면 정책 기준 판단
|
||||
|
||||
### 5.1 바로 충족 가능한 정책
|
||||
|
||||
- 회사급 초기 범위
|
||||
- 전체 > 회사 > 하위조직 > 개인 drilldown
|
||||
- breadcrumb 유지
|
||||
- leaf 조직 진입 후 직원 목록 표시
|
||||
- 하위조직 카드의 subtree 인원 수 표시
|
||||
- 조직도 그룹 내 리더 우선 정렬 보조
|
||||
|
||||
### 5.2 추가 가공 후 충족 가능한 정책
|
||||
|
||||
- 본인 팀 뱃지 고정 노출
|
||||
- 선택 scope 기준 직원검색
|
||||
- 즐겨찾기 로컬 저장
|
||||
- 상세 화면 tenant/부서/직급/직위 표시
|
||||
- 프로필 이미지 2순위 UUID 파일명 연결
|
||||
|
||||
### 5.3 현재 구조만으로는 바로 어려운 정책
|
||||
|
||||
- 프로필 사진 URL 표시
|
||||
- 안정적인 직원 상세 단건 조회
|
||||
- 서버 기반 즐겨찾기 동기화
|
||||
|
||||
## 6. 최종 판단
|
||||
|
||||
`org-context`는 다음 의미에서 채택 가치가 높다.
|
||||
|
||||
1. 조직도와 직원검색의 데이터 원형으로 충분히 쓸 수 있다.
|
||||
2. 현재 앱이 원하는 조직 탐색 UX와 구조적으로 잘 맞는다.
|
||||
3. 현재 코드의 `tdc114plus 전용 DTO`는 상당 부분 이 응답을 flatten/adapter 한 결과로 재해석할 수 있다.
|
||||
|
||||
하지만 아래 2가지는 분리해서 봐야 한다.
|
||||
|
||||
1. `데이터 구조 기준으로 채택할 것인가`
|
||||
- 예
|
||||
2. `모바일 앱이 운영 Key를 넣고 직접 호출할 것인가`
|
||||
- 현재 기준으로는 보안 검토 전까지 아니오
|
||||
|
||||
### 6.1 2026-07-15 추가 확인
|
||||
|
||||
- 가족사 전체 `org-context` 응답과 기존 프로필 파일 CSV를 대조한 결과, 기존 `2457`건이 `members[].id`와 전건 매핑됐다.
|
||||
- 따라서 현재 기준으로 `members[].id`는 프로필 이미지 2순위 식별자로 실사용 가능한 후보가 아니라, 사실상 채택 가능한 기준값으로 본다.
|
||||
|
||||
## 7. 다음 작업 권장 순서
|
||||
|
||||
1. `org-context`를 기준 데이터 구조로 채택한다고 문서에 명시
|
||||
2. 현재 `Employee`, `TenantSummary`, `OrgChartSnapshot`를 `org-context adapter` 기준으로 재설계
|
||||
3. `includeUserIds=true`를 전제로 해야 하는 기능과 아닌 기능을 분리
|
||||
4. 운영 Key 보호 방식을 확정
|
||||
5. 그 다음 실제 코드 변경
|
||||
@@ -0,0 +1,330 @@
|
||||
# tdc114plus 프로필 이미지 관리 정책 및 단계별 진행안
|
||||
|
||||
작성일: 2026-07-14
|
||||
최종 개정일: 2026-07-20
|
||||
상태: v2.2
|
||||
관련 Phase: `Phase 7-C`
|
||||
|
||||
## 1. 목적
|
||||
|
||||
신규앱의 직원 프로필 이미지를 어떤 우선순위와 어떤 식별 기준으로 운영할지 고정한다.
|
||||
|
||||
본 문서는 아래 사항을 최신 기준으로 정리한다.
|
||||
|
||||
- 프로필 이미지 노출 우선순위
|
||||
- 네이버웍스와 Baron SSO 조직도 응답의 역할
|
||||
- R2 버킷 파일명 정책
|
||||
- 앱과 중계서버가 직접 하지 않아야 할 일
|
||||
- 현재까지 확인된 검증 결과
|
||||
- 다음 작업 순서
|
||||
|
||||
## 2. 현재 확정 정책
|
||||
|
||||
### 2-1. 이미지 노출 우선순위
|
||||
|
||||
신규앱의 프로필 이미지 우선순위는 아래처럼 고정한다.
|
||||
|
||||
1. 네이버웍스 프로필 사진
|
||||
2. Baron SSO 조직도 `members[].id` 기준 UUID 파일명 이미지
|
||||
3. 신규앱 기본 아바타
|
||||
|
||||
즉, R2 버킷 이미지는 유지하되, 더 이상 이메일 또는 해시 매핑 DB를 기본 경로로 사용하지 않는다.
|
||||
|
||||
### 2-2. 기본 식별자 정책
|
||||
|
||||
- 직원 프로필 이미지의 2순위 식별자는 Baron SSO 조직도 응답의 `members[].id`를 사용한다.
|
||||
- 이 값은 `includeUsers=true`, `includeUserIds=true` 조건의 `org-context` 응답에서 확인되는 사용자 고정 식별자다.
|
||||
- 신규앱은 `이메일 @앞부분.jpg`를 직접 만들지 않는다.
|
||||
- 신규앱은 해시 파일명도 직접 계산하지 않는다.
|
||||
- 신규앱은 직원별 Baron UUID를 확보한 뒤 `https://baroncs.co.kr/employee_img/{uuid}.jpg` 규칙으로만 2순위 이미지를 시도한다.
|
||||
|
||||
### 2-3. DB 사용 정책
|
||||
|
||||
- 현재 운영 기본안에서는 프로필 이미지 전용 매핑 DB를 두지 않는다.
|
||||
- `tdc114plus-auth` 내부 PostgreSQL 기반 fallback 구현은 검토/검증 결과물로만 남기고, 현재 채택안의 기본 경로로 사용하지 않는다.
|
||||
- 추후 Baron SSO UUID를 안정적으로 받을 수 없는 별도 화면이나 별도 운영 요구가 생기면 그때 보조안으로만 재검토한다.
|
||||
|
||||
## 3. 현재까지 확인된 사실
|
||||
|
||||
### 3-1. 네이버웍스 문서 및 실연동 검토 결과
|
||||
|
||||
2026-07-15 기준 네이버웍스 개발자 문서와 실제 서비스 계정 호출 기준으로 아래를 확인했다.
|
||||
|
||||
- 구성원 프로필 조회 endpoint: `GET /users/{userId}`
|
||||
- 구성원 사진 조회 endpoint: `GET /users/{userId}/photo`
|
||||
- `userId`에는 구성원 ID, 메일, 리소스 ID, `externalKey:{externalKey}` 형식 사용 가능
|
||||
- 사진 조회 응답은 `HTTP 302`, `HTTP 400`, `HTTP 404` 규칙을 가진다
|
||||
|
||||
실제 1차 호출 결과:
|
||||
|
||||
- 서비스 계정 토큰 발급: `HTTP 200`
|
||||
- `GET /users/{userId}` 샘플 1
|
||||
- 입력: `khkang@samaneng.com`
|
||||
- 결과: `HTTP 200`
|
||||
- `GET /users/{userId}/photo` 샘플 1
|
||||
- 입력: `khkang@samaneng.com`
|
||||
- 결과: `HTTP 404`
|
||||
- `GET /users/{userId}` 샘플 2
|
||||
- 입력: `thlee3@samaneng.com`
|
||||
- 결과: `HTTP 200`
|
||||
- `GET /users/{userId}/photo` 샘플 2
|
||||
- 입력: `thlee3@samaneng.com`
|
||||
- 결과: `HTTP 302`
|
||||
- `Location` 헤더에 실제 이미지 접근 URL 반환 확인
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 네이버웍스 사진 연동은 1순위 경로로 실제 성립한다.
|
||||
- 현재까지의 1차 검증 기준으로는 `사진 있음 -> 302`, `사진 없음 -> 404` 흐름이 확인됐다.
|
||||
|
||||
### 3-2. R2 버킷과 공개 경로
|
||||
|
||||
현재 프로필 이미지 파일은 Cloudflare R2 Object Storage에 적재되어 있다.
|
||||
|
||||
- 공개 도메인 prefix: `https://baroncs.co.kr/employee_img/`
|
||||
- 현재부터는 UUID 파일명 기준으로 관리한다.
|
||||
- 목표 URL 규칙: `https://baroncs.co.kr/employee_img/{uuid}.jpg`
|
||||
|
||||
2026-07-15 기준 UUID 파일명 샘플 공개 URL 검증 결과:
|
||||
|
||||
- `https://baroncs.co.kr/employee_img/bebb832c-052e-493d-b5a9-732518d67685.jpg`
|
||||
- `HTTP 200`
|
||||
- `content-type: image/jpeg`
|
||||
- `https://baroncs.co.kr/employee_img/cc2db80c-5a18-4439-8026-22dd06d6452f.jpg`
|
||||
- `HTTP 200`
|
||||
- `content-type: image/jpeg`
|
||||
|
||||
현재 판단:
|
||||
|
||||
- UUID 파일명으로 변경된 2순위 이미지가 실제 공개 경로에서 응답하는 것을 확인했다.
|
||||
- 따라서 2순위 경로는 문서상 계획이 아니라 실배치/실응답까지 확인된 상태로 본다.
|
||||
|
||||
### 3-3. Baron SSO 조직도 UUID 실검증 결과
|
||||
|
||||
2026-07-15 기준 `org-context` 실조회로 아래 사실을 확인했다.
|
||||
|
||||
- 조회 대상: `tenantSlug=hanmac-family`
|
||||
- 옵션: `includeUsers=true`, `includeUserIds=true`
|
||||
- `members[].id`가 실제 응답에 포함된다
|
||||
- 해당 값은 예시 문자열이 아니라 UUID 형식이다
|
||||
- 예:
|
||||
- `c6ac492a-d4f3-4fff-8409-b50e317ca793`
|
||||
- `73f80ef0-62ec-49b2-a8eb-1f4de52966b7`
|
||||
- `bebb832c-052e-493d-b5a9-732518d67685`
|
||||
|
||||
현재 판단:
|
||||
|
||||
- `members[].id`는 2순위 프로필 이미지 파일명 기준으로 사용할 수 있다.
|
||||
- 이메일 local-part보다 보안성과 변경 내성이 높다.
|
||||
|
||||
### 3-4. 가족사 전인원 UUID 매핑 확인 결과
|
||||
|
||||
2026-07-15 기준 가족사 전체 `org-context` 응답과 기존 파일 매핑 CSV를 대조해 아래를 확인했다.
|
||||
|
||||
- 기준 원본: `docs/references/file_rename_hash_results.csv`
|
||||
- 기존 원본 행 수: `2457`
|
||||
- `org-context` 고유 이메일 수: `2610`
|
||||
- UUID 매핑 성공 행 수: `2457`
|
||||
- 미매핑 행 수: `0`
|
||||
|
||||
생성한 참고 산출물:
|
||||
|
||||
- `docs/references/profile_image_uuid_rename_candidates.csv`
|
||||
|
||||
이 CSV에는 아래 컬럼을 포함했다.
|
||||
|
||||
- `comp`
|
||||
- `employee_name`
|
||||
- `employee_email`
|
||||
- `employee_email_local_part`
|
||||
- `legacy_photo_file_name`
|
||||
- `hashed_photo_file_name`
|
||||
- `baron_user_uuid`
|
||||
- `target_uuid_file_name`
|
||||
- `rename_ready`
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 기존 사진 파일을 UUID 파일명으로 재정리하는 작업은 충분히 진행 가능하다.
|
||||
- 현재 확보된 CSV만으로 `기존 파일명 -> UUID 파일명` 변경 작업 계획을 잡을 수 있다.
|
||||
|
||||
## 4. 채택안 기준 연동 구조
|
||||
|
||||
### 4-1. 신규앱 기본 흐름
|
||||
|
||||
```text
|
||||
직원 DTO 수신
|
||||
-> 앱이 직접 네이버웍스와 외부 이미지 서버를 각각 판단하지 않음
|
||||
-> 중계서버 /api/v1/profile-image 호출
|
||||
-> 중계서버가 네이버웍스 사진 조회 시도
|
||||
-> 실패 시 Baron UUID 기준 https://baroncs.co.kr/employee_img/{uuid}.jpg 판단
|
||||
-> 둘 다 없으면 found=false 반환
|
||||
-> 앱은 기본 아바타 표시
|
||||
```
|
||||
|
||||
현재 시점의 가장 효율적인 구현안은, 앱이 직접 1순위/2순위를 분기하지 않고 기존 `tdc114plus-auth`의 `GET /api/v1/profile-image` endpoint를 유지한 채 내부 우선순위만 `네이버웍스 -> UUID 이미지 -> 기본 미발견`으로 바꾸는 방식이다.
|
||||
|
||||
2026-07-20 기준 네이버웍스 1순위 이미지는 외부 `Location` URL을 앱에 그대로 전달하지 않는다.
|
||||
|
||||
이유:
|
||||
|
||||
- 네이버웍스 `GET /users/{userId}/photo`는 사진이 있으면 `302 Location`을 반환한다.
|
||||
- 일부 `Location` URL은 앱이나 일반 HTTP 클라이언트가 인증 없이 직접 열면 `400 Authentication failed`가 발생한다.
|
||||
- 따라서 앱이 네이버웍스 원본 URL을 직접 표시하는 방식은 안정적이지 않다.
|
||||
|
||||
현재 확정 처리:
|
||||
|
||||
- `tdc114plus-auth`가 네이버웍스 사진 존재 여부를 확인한다.
|
||||
- 네이버웍스 사진이 있으면 앱에는 `tdc114plus-auth`의 프록시 URL을 반환한다.
|
||||
- 앱은 이 프록시 URL을 일반 이미지 URL처럼 표시한다.
|
||||
- 프록시는 내부에서 네이버웍스 Access Token을 사용해 실제 이미지 바이너리를 받아 앱에 `image/jpeg`로 내려준다.
|
||||
- 네이버웍스 사진이 없거나 프록시 확인이 실패하면 UUID 이미지 2순위로 내려간다.
|
||||
|
||||
이 방식의 장점은 아래와 같다.
|
||||
|
||||
- 앱 계약을 크게 흔들지 않는다.
|
||||
- 네이버웍스 서비스 계정/토큰 처리 로직을 앱에 넣지 않아도 된다.
|
||||
- 추후 우선순위가 바뀌어도 서버만 수정하면 된다.
|
||||
- UUID 이미지 경로 변경, 캐시 정책, timeout 정책을 서버에서 통제할 수 있다.
|
||||
|
||||
### 4-2. 신규앱이 직접 하지 않아야 하는 일
|
||||
|
||||
- `이메일 @앞부분.jpg` 직접 조합
|
||||
- 해시 파일명 직접 계산
|
||||
- 별도 프로필 이미지 매핑 DB 직접 조회
|
||||
- 버킷 내부 경로 추론
|
||||
|
||||
### 4-3. 중계서버 역할
|
||||
|
||||
현재 채택안 기준 중계서버의 역할은 아래처럼 정리한다.
|
||||
|
||||
- Baron SSO 로그인/세션 유지
|
||||
- 필요 시 조직도 `org-context` proxy 제공
|
||||
- `GET /api/v1/profile-image` 단일 endpoint 제공
|
||||
- 네이버웍스 1순위 경로 처리
|
||||
- 네이버웍스 사진 원본 URL을 앱에 직접 노출하지 않고 `GET /api/v1/profile-image/naver-photo` 프록시로 이미지 바이너리 제공
|
||||
- Baron UUID 기준 2순위 이미지 경로 판단
|
||||
- 앱에는 최종 `found/source/imageUrl` 결과만 반환
|
||||
|
||||
현재 채택안 기준으로는 중계서버가 프로필 이미지 전용 매핑 DB를 운영 기본 구조로 갖지 않는다. 다만 기존 `tdc114plus-auth`의 `/api/v1/profile-image` endpoint는 유지하고, 내부 로직만 새 우선순위로 재정리하는 것이 가장 효율적이다.
|
||||
|
||||
## 5. PostgreSQL 검토 결과 정리
|
||||
|
||||
2026-07-15 기준 `tdc114plus-auth`에 PostgreSQL 기반 fallback 검토를 이미 진행했다.
|
||||
|
||||
확인된 내용:
|
||||
|
||||
- 로컬 PostgreSQL 컨테이너 구성
|
||||
- `profile_image_mapping` 스키마 초안 작성
|
||||
- CSV `2457`건 적재 검증
|
||||
- `GET /api/v1/profile-image?comp=...&email=...` 샘플 검증
|
||||
|
||||
현재 정책 판단:
|
||||
|
||||
- 위 결과는 기술 검증 자료로는 유효하다.
|
||||
- 하지만 운영 기본안은 아니다.
|
||||
- 현재 기준 주 경로는 `네이버웍스 -> UUID 파일명 이미지 -> 기본 아바타`다.
|
||||
- 따라서 PostgreSQL 경로는 `보류된 대안`으로만 기록한다.
|
||||
- 실제 구현은 기존 `tdc114plus-auth` endpoint를 재사용하되, PostgreSQL 분기는 기본 비활성 또는 최후 예비안으로만 남기는 편이 적절하다.
|
||||
|
||||
## 6. 단계별 진행작업 타임테이블
|
||||
|
||||
| 단계 | 상태 | 작업 구분 | 작업 내용 | 완료 기준 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Step 1 | 완료 | 문서/정책 | 프로필 이미지 우선순위와 기본 검토 구조를 정리했다 | 초기 문서 기준선 확보 |
|
||||
| Step 2 | 완료 | 네이버웍스 문서 검토 | `GET /users/{userId}`, `GET /users/{userId}/photo`, scope, 302/404 구조를 확인했다 | 1순위 경로 성립 가능 조건 확인 |
|
||||
| Step 3 | 완료 | R2 자산 점검 | 공개 prefix `https://baroncs.co.kr/employee_img/` 와 공개 응답을 확인했다 | 2순위 파일 배치 경로 확인 |
|
||||
| Step 4 | 완료 | Baron UUID 실검증 | `org-context` 실응답에서 `members[].id`가 UUID 형식으로 내려오는 것을 확인했다 | 2순위 식별자 확정 |
|
||||
| Step 5 | 완료 | 가족사 전인원 매핑 검증 | 기존 CSV `2457`건을 Baron UUID와 대조해 전건 매핑 성공을 확인했다 | `profile_image_uuid_rename_candidates.csv` 생성 |
|
||||
| Step 6 | 완료 | 외부 파일 재배치 | 기존 사진 파일명을 `[uuid].jpg`로 변경하고 `employee_img/` 하위에 재배치했다 | 샘플 URL 2건 `HTTP 200 image/jpeg` 검증 완료 |
|
||||
| Step 7 | 완료 | 앱 공통 resolver 정리 | 앱은 `GET /api/v1/profile-image`를 우선 호출하고, 응답 실패 또는 미발견 시에는 `profileImageUrl -> UUID 파일명 -> 기본 아바타` 순서의 보조 fallback을 사용하도록 정리했다 | 앱 공통 resolver와 보조 fallback 반영 완료 |
|
||||
| Step 8 | 완료 | 네이버웍스 실연동 검증 | 개발자 계정 기준으로 사진 조회를 실제 호출해 `302`와 `404` 규칙을 확인했다 | 1순위 경로 실응답 규칙 1차 확정 |
|
||||
| Step 9 | 완료 이력 | 서버 구현 및 실검증 | 2026-07-15 시점에는 `tdc114plus-auth GET /api/v1/profile-image`가 `NAVER WORKS -> Baron UUID 이미지 -> DEFAULT` 순서로 동작하는 구현과 샘플 응답을 확인했다 | 2026-07-15 기준 실검증 이력 |
|
||||
| Step 10 | 완료 | 현재 기동 정합성 검증 | 2026-07-20 기준 `tdc114plus-auth`에 `/api/v1/profile-image`와 `/api/v1/profile-image/naver-photo` 프록시 route를 복구/보강했다 | `go test ./cmd/server` 통과, 5001 health 정상 |
|
||||
| Step 11 | 완료 | 네이버웍스 프록시 검증 | 네이버웍스 302 Location을 앱에 직접 주지 않고 중계서버 프록시가 `image/jpeg` 바이너리로 내려주는 것을 확인했다 | `한치영`, `이태훈` 프록시 `200 OK image/jpeg` 확인 |
|
||||
| Step 12 | 진행 중 | 실기기 화면 확대 검증 | 직원검색 목록에서 NAVER_WORKS와 BARON_UUID_R2가 동시에 정상 표시되는 것을 확인했다. DEFAULT 기본 아바타 케이스는 추가 샘플로 계속 확인한다 | 1순위/2순위 화면 확인 완료, 3순위 확대 검증 필요 |
|
||||
|
||||
## 7. 다음 작업 순서
|
||||
|
||||
1. DEFAULT 기본 아바타 케이스를 명시 샘플로 추가 확인한다.
|
||||
2. 직원 상세/조직도/즐겨찾기 화면에서도 동일 이미지 규칙이 유지되는지 확인한다.
|
||||
3. 화면 전환 후 이미지 캐시가 잘못된 null 상태를 유지하지 않는지 확인한다.
|
||||
4. `adb reverse 5001/5000`이 끊겼을 때 로그인 실패처럼 보일 수 있으므로, 실기기 검증 전 reverse 상태를 먼저 확인한다.
|
||||
5. 검증 결과를 본 문서와 타임테이블 문서에 즉시 반영한다.
|
||||
|
||||
## 8. 현재 시점 결론
|
||||
|
||||
- 프로필 이미지 1순위는 네이버웍스다.
|
||||
- 2순위는 Baron SSO 조직도 `members[].id`를 파일명으로 사용하는 UUID 이미지다.
|
||||
- 현재 운영 기본안에서는 프로필 이미지 전용 DB를 두지 않는다.
|
||||
- 기존 PostgreSQL fallback 검토는 예비안으로만 남긴다.
|
||||
- 2026-07-20 기준 `tdc114plus-auth`의 `/api/v1/profile-image` route와 네이버웍스 프록시 route는 복구/보강됐다.
|
||||
- 네이버웍스 사진 원본 URL은 앱에 직접 주지 않고 `tdc114plus-auth` 프록시 URL로 제공한다.
|
||||
- 현재 가장 중요한 다음 단계는 실기기 기준으로 `DEFAULT` 3순위와 직원 상세/조직도/즐겨찾기 화면의 동일 규칙 유지 여부를 확대 검증하는 것이다.
|
||||
|
||||
## 9. 2026-07-20 검증 및 보강 메모
|
||||
|
||||
2026-07-20 기준 아래를 확인했다.
|
||||
|
||||
- `tdc114plus-auth GET /api/v1/profile-image` route 복구 및 유지
|
||||
- `tdc114plus-auth GET /api/v1/profile-image/naver-photo` 프록시 route 추가
|
||||
- `cyhan@samaneng.com`, `thlee3@samaneng.com` 네이버웍스 사진 존재 확인
|
||||
- 네이버웍스 `Location` 원본 URL 직접 접근 시 `400 Authentication failed`가 발생할 수 있음 확인
|
||||
- 프록시 route에서 두 사용자 모두 `200 OK`, `Content-Type: image/jpeg` 확인
|
||||
- 실기기 직원검색 화면에서 기존에 기본 이니셜로 떨어지던 인원의 네이버웍스 사진 표시 정상화 확인
|
||||
- `BARON_UUID_R2` source 로그도 동시에 확인되어 2순위 경로가 유지됨을 확인
|
||||
|
||||
검증한 자동 테스트:
|
||||
|
||||
- `tdc114plus-auth`: `GOCACHE=/tmp/go-build-cache go test ./cmd/server`
|
||||
- `tdc114plus`: `./scripts/flutter-docker.sh test test/directory/profile_image_api_client_test.dart`
|
||||
|
||||
주의:
|
||||
|
||||
- 로컬 실기기 검증 중 `adb reverse tcp:5001 tcp:5001`, `adb reverse tcp:5000 tcp:5000`이 끊기면 앱 화면에는 `인증 서버에 연결하지 못했습니다`처럼 보일 수 있다.
|
||||
- 이 경우 프로필 사진 코드 문제가 아니라 실기기와 로컬 중계서버 연결 문제일 수 있으므로, 먼저 `adb reverse --list`를 확인한다.
|
||||
|
||||
## 10. 2026-07-15 실기기 확인 메모
|
||||
|
||||
2026-07-15 기준 Android 실기기 직원검색 화면에서 실제 프로필 사진 노출을 확인했다.
|
||||
|
||||
확인 내용:
|
||||
|
||||
- 로그인 후 직원검색 목록 진입 확인
|
||||
- 원형 기본 이니셜 아바타 대신 실제 사진 노출 확인
|
||||
- 확인 화면에는 여러 직원의 사진이 동시에 표시됐다
|
||||
- 현재 앱은 `tdc114plus-auth /api/v1/profile-image`를 우선 호출하고, 응답 실패 또는 미발견 시 UUID 공개 경로 fallback을 사용한다
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 정책 문서상 구조가 아니라, 실기기 화면 기준으로도 프로필 사진 표시가 동작하는 상태다
|
||||
- 다만 어떤 직원이 `NAVER_WORKS`로 해석됐는지, 어떤 직원이 `BARON_UUID_R2`로 해석됐는지는 추가 로그/샘플 검증으로 더 구분해 둘 필요가 있다
|
||||
|
||||
## 9. 2026-07-15 자격값 재검증 메모
|
||||
|
||||
2026-07-15 오후 기준, 갱신된 네이버웍스 서비스 계정 자격값을 다시 반영한 뒤 실제 호출을 재검증했다.
|
||||
|
||||
확인 결과:
|
||||
|
||||
- 서비스 계정 토큰 발급: `HTTP 200`
|
||||
- 샘플 사용자 `thlee3@samaneng.com` 프로필 조회: `HTTP 200`
|
||||
- 샘플 사용자 `thlee3@samaneng.com` 사진 조회: `HTTP 302`
|
||||
- `Location` 헤더로 실제 이미지 접근 URL 반환 확인
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 최신 자격 세트는 유효하다.
|
||||
- `tdc114plus-auth` 서버가 이 자격 세트를 사용해 1순위 경로를 실제 구현할 수 있는 준비가 됐다.
|
||||
- 이후 로컬 auth 서버 실기동 검증에서도 아래를 확인했다.
|
||||
- `GET /api/v1/profile-image?email=thlee3@samaneng.com`
|
||||
- `found=true`
|
||||
- `source=NAVER_WORKS`
|
||||
- `GET /api/v1/profile-image?email=khkang@samaneng.com`
|
||||
- `found=true`
|
||||
- `source=BARON_UUID_R2`
|
||||
|
||||
## 10. 관련 문서
|
||||
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- `docs/00_guide_tdc114plus_org_context_mapping_2026-07-08.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
@@ -0,0 +1,163 @@
|
||||
# tdc114plus Swagger API 목록 및 Feature 매핑
|
||||
|
||||
작성일: 2026-07-07
|
||||
상태: v1.2
|
||||
|
||||
목적: 타임테이블의 다음 작업인 `Swagger 기준 1차 사용 API 목록 고정`, `현재 Flutter feature 매핑`, `구조 차이점 정리`를 한 문서에 정리한다.
|
||||
|
||||
상위 기준 문서:
|
||||
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
|
||||
주의:
|
||||
|
||||
- 현재 기준은 Baron Swagger 문서와 앱 소스의 대조 결과를 합친 중간 정리본이다.
|
||||
- 신규앱 전용 `/api/v1/tdc114plus/...` API는 공식 계약으로 간주하지 않는다.
|
||||
- 옛 `/api/v1/tdc114plus/...` 경로는 과거 구현 흔적 또는 호환 경로이며, 기능이 무너지지 않게 테스트하면서 점진 제거한다.
|
||||
|
||||
## 1. 1차 사용 API 목록
|
||||
|
||||
현재 Baron Swagger 기준 1차 사용 또는 즉시 검토 대상 API는 아래다.
|
||||
|
||||
| 구분 | Method | Path | 현재 상태 | 앱 사용 목적 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| auth | `GET` | `https://sso.hmac.kr/oidc/oauth2/auth` | RP 설정 기준 | Baron SSO Hosted Login 시작 |
|
||||
| auth | `POST` | `https://sso.hmac.kr/oidc/oauth2/token` | RP 설정 기준 | PKCE authorization code token 교환 |
|
||||
| auth | `GET` | `https://sso.hmac.kr/oidc/userinfo` | RP 설정 기준 | 로그인 사용자 정보 조회 |
|
||||
| auth reference | `POST` | `/api/v1/auth/phone-login` | 앱 직접 호출 제외 | Baron SSO Hosted Login 내부 전화번호 로그인 구현 참고 |
|
||||
| auth reference | `POST` | `/api/v1/auth/headless/phone-login` | 앱 직접 호출 제외 | Baron SSO Hosted Login 내부 구현 참고 |
|
||||
| auth reference | `POST` | `/api/v1/auth/headless/link/poll` | 앱 직접 호출 제외 | Baron SSO Hosted Login 내부 구현 참고 |
|
||||
| auth reference | `POST` | `/api/v1/auth/enchanted-link/init` | 앱 직접 호출 제외 | Baron SSO 링크 로그인 내부 구현 참고 |
|
||||
| auth reference | `POST` | `/api/v1/auth/enchanted-link/poll` | 앱 직접 호출 제외 | Baron SSO 링크 로그인 내부 구현 참고 |
|
||||
| auth reference | `POST` | `/api/v1/auth/sms`, `/api/v1/auth/verify-sms` | 앱 직접 호출 제외 | Baron SSO SMS 인증 내부 구현 참고 |
|
||||
| auth reference | `POST` | `/api/v1/auth/qr/*` | 앱 직접 호출 제외 | Baron SSO QR 인증 내부 구현 참고 |
|
||||
| organization | `GET` | `/api/v1/integrations/org-context` | 공식 계약 | 조직 subtree/구성원 조회 |
|
||||
| organization | `GET` | `/api/v1/public/orgchart` | 공식 계약 | 공유용 조직도 조회 |
|
||||
| legacy auth | `POST` | `/api/v1/tdc114plus/auth/phone-login` | 호환 흔적 | 테스트용 세션 seed 예외 경로 |
|
||||
| legacy directory | `GET` | `/api/v1/tdc114plus/directory/employees` | 제거 대상 | 과거 직원검색 목록 가정 |
|
||||
| legacy organization | `GET` | `/api/v1/tdc114plus/organization/tenants` | 제거 대상 | 과거 회사 필터 가정 |
|
||||
| legacy organization | `GET` | `/api/v1/tdc114plus/organization/orgchart` | 제거 대상 | 과거 조직도 가정 |
|
||||
|
||||
## 2. Feature별 현재 매핑
|
||||
|
||||
### 2.1 auth
|
||||
|
||||
관련 코드:
|
||||
|
||||
- `app/lib/src/features/auth/data/auth_api_client.dart`
|
||||
- `app/lib/src/features/auth/data/auth_repository.dart`
|
||||
|
||||
현재 매핑:
|
||||
|
||||
| 기능 | 기준 API | 비고 |
|
||||
| --- | --- | --- |
|
||||
| 로그인 시작 | `GET https://sso.hmac.kr/oidc/oauth2/auth` | 기본 로그인 경로. 외부 Baron SSO Hosted Login 화면을 연다 |
|
||||
| callback 처리 | `https://114.hmac.kr/auth/callback` | App Link로 앱 복귀 |
|
||||
| token 교환 | `POST https://sso.hmac.kr/oidc/oauth2/token` | PKCE `code_verifier`로 authorization code 교환 |
|
||||
| 사용자 정보 | `GET https://sso.hmac.kr/oidc/userinfo` | 후속 연결 대상 |
|
||||
| fallback 로그인 | legacy `POST /api/v1/tdc114plus/auth/phone-login` | 예외 호환 경로만 유지 |
|
||||
| 세션 저장 | API 아님 | `AuthSessionStore`에서 로컬 저장 |
|
||||
|
||||
구조 메모:
|
||||
|
||||
- `AuthRepository` 추상화는 이미 존재한다.
|
||||
- 구현체 이름은 `RemoteAuthRepository`로 일반화했다.
|
||||
- `OidcLoginRepository`는 Hosted Login authorization URL 생성, PKCE transaction 저장, callback token 교환을 담당한다.
|
||||
- Swagger Auth 섹션에 표시되는 `phone-login`, `headless`, `enchanted-link`, `sms`, `qr` 계열 API는 Baron SSO Hosted Login 화면/서버 내부 구현 참고 대상으로 분류한다.
|
||||
- 기존 headless/legacy phone login 계층은 테스트 호환 및 제거 대상 분류용으로만 유지한다.
|
||||
- 로그인 성공 후 Baron SSO가 `org-context` 호출용 연동 키를 내려주면 앱 세션의 선택적 credential로 받아 사용한다.
|
||||
- 해당 기능이 미개발인 동안은 staging `org-context` 고정 키를 비추적 env/Dart define fallback으로 사용한다.
|
||||
|
||||
### 2.2 directory
|
||||
|
||||
관련 코드:
|
||||
|
||||
- `app/lib/src/features/directory/data/directory_api_client.dart`
|
||||
- `app/lib/src/features/directory/data/directory_repository.dart`
|
||||
|
||||
현재 매핑:
|
||||
|
||||
| 기능 | 기준 API | 비고 |
|
||||
| --- | --- | --- |
|
||||
| 직원 목록/검색 | `GET /api/v1/integrations/org-context` 기반 재구성 | 메인 직원검색 진입점 |
|
||||
| 직원 상세 | `org-context` member 필드 또는 후속 공식 API 확인 필요 | API 계약 재정렬 중 |
|
||||
|
||||
구조 메모:
|
||||
|
||||
- `DirectoryRepository` 추상화는 존재한다.
|
||||
- 구현체 이름은 `RemoteDirectoryRepository`로 일반화했다.
|
||||
- 현재는 directory repository를 `org-context` 기반 구조로 재정렬하는 단계다.
|
||||
|
||||
### 2.3 organization
|
||||
|
||||
관련 코드:
|
||||
|
||||
- `app/lib/src/features/organization/data/organization_api_client.dart`
|
||||
|
||||
현재 매핑:
|
||||
|
||||
| 기능 | 기준 API | 비고 |
|
||||
| --- | --- | --- |
|
||||
| 테넌트/상위 조직 | `GET /api/v1/integrations/org-context` | 실제 화면 사용 높음 |
|
||||
| 조직도/공유형 | `GET /api/v1/public/orgchart` | 공유/외부 링크 전용 |
|
||||
|
||||
구조 메모:
|
||||
|
||||
- organization 쪽은 repository 추상화가 추가됐다.
|
||||
- `orgContextProvider`를 통해 subtree 조회를 별도 책임으로 분리한다.
|
||||
- 1차 화면 재사용 범위는 `orgContextProvider`까지로 고정한다.
|
||||
- `org-context` 전용 provider를 준비하되, 현재 직원검색 화면 연결은 점진 전환한다.
|
||||
|
||||
## 3. 구조 차이점 및 정리 우선순위
|
||||
|
||||
### 3.1 우선순위 1
|
||||
|
||||
- Hosted Login + PKCE를 기본 로그인 계약으로 고정
|
||||
- 앱 내부 phone 입력/headless 직접 호출 UI와 API 의존 제거
|
||||
- callback `state` 검증, token 교환, userinfo 조회 연결
|
||||
|
||||
### 3.2 우선순위 2
|
||||
|
||||
- organization 상태 재사용 범위를 `org-context` 중심으로 먼저 고정
|
||||
- `org-context` 전용 provider를 준비하고, 실제 UI 연결은 후속 단계로 분리
|
||||
- directory 화면에서 subtree/member 비동기 조합 방식을 더 다듬을지 검토
|
||||
|
||||
### 3.3 우선순위 3
|
||||
|
||||
- 직원 상세 API를 화면에서 실제로 쓰는 범위를 확대할지 판단
|
||||
- orgchart client를 drilldown 화면에 실제 연결할지 판단
|
||||
|
||||
## 4. 현재 확인된 구조상 이슈
|
||||
|
||||
1. 일부 코드와 문서에 legacy `/api/v1/tdc114plus/...` 흔적이 남아 있다.
|
||||
2. 실제 `org-context` 응답 필드 대조가 끝나기 전까지는 DTO 필드 확정 표현을 최소화해야 한다.
|
||||
3. Baron SSO의 로그인 성공 응답 또는 후속 userinfo/session 응답에 조직도 API 연동 키가 아직 포함되지 않을 수 있다.
|
||||
4. 따라서 앱은 `세션 credential 우선 -> 비추적 env fallback` 순서로 구현되어야 한다.
|
||||
|
||||
## 5. 다음 코드 작업 제안
|
||||
|
||||
다음 코드 작업은 아래 순서를 권장한다.
|
||||
|
||||
1. organization 상태 재사용은 `orgContextProvider` 우선으로 유지
|
||||
2. legacy `/api/v1/tdc114plus/...` 의존은 테스트를 곁들여 단계적으로 제거
|
||||
3. 실제 UI 연결 전 `org-context` 매핑과 member 검색 규칙을 먼저 고정
|
||||
4. auth session 모델에 선택적 `orgContextCredential` 수신/저장 구조를 추가
|
||||
5. `org-context` client는 session credential을 우선 사용하고 없으면 staging env fallback을 사용
|
||||
|
||||
## 6. 이 문서로 완료된 타임테이블 항목
|
||||
|
||||
이 문서로 아래 작업을 1차 수행했다.
|
||||
|
||||
- Swagger 기준 1차 사용 API 목록 문서화
|
||||
- 현재 Flutter 코드의 auth/directory/organization feature 매핑
|
||||
- feature별 DTO/repository/mock 구조 차이점의 초안 정리
|
||||
- auth feature의 기본 로그인 경로와 fallback 경로 역할 분리
|
||||
- directory repository와 organization repository의 1차 책임 경계 분리
|
||||
- organization 상태 재사용 범위와 orgchart 연결 범위 1차 확정
|
||||
- orgchart 전용 provider 준비 완료, 실제 UI 연결은 후속 단계로 유지
|
||||
- auth/directory 구현체 명칭을 `Remote...Repository`로 일반화
|
||||
- auth/directory 구현체 명칭 일반화 후 관련 테스트 통과
|
||||
|
||||
다만 실제 Swagger UI 대조 확인은 후속 작업으로 남아 있다.
|
||||
@@ -0,0 +1,367 @@
|
||||
# tdc114plus 작업진행 절차 및 타임테이블
|
||||
|
||||
작성일: 2026-07-02
|
||||
최종 개정일: 2026-07-20
|
||||
상태: v3.0
|
||||
|
||||
목적: `tdc114plus` 개발 작업을 새 분리형 API 전환 정책 기준으로 어떤 순서로 진행할지 고정하고, 현재 진행 상태를 최신 기준으로 유지한다.
|
||||
|
||||
상위 기준 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
|
||||
## 1. 현재 기준
|
||||
|
||||
`tdc114plus`는 Baron SSO에 추가되는 별도 `RP(Relying Party)` 성격의 신규 앱이다.
|
||||
|
||||
현재 구조는 `개발 중 임시 운영 구조`와 `최종 배포 목표 구조`를 구분해서 본다.
|
||||
|
||||
- 개발 중 임시 운영 구조:
|
||||
- 앱 저장소 `tdc114plus`
|
||||
- 중계서버 저장소 `tdc114plus-auth`
|
||||
- Baron SSO API 검증용 로컬 worktree `baron-sso-tdc114plus-api`
|
||||
- 최종 배포 목표 구조:
|
||||
- 신규앱은 `tdc114plus` + `tdc114plus-auth` 기준으로 배포 준비를 진행한다.
|
||||
- 인증/조직 원본은 로컬 Baron worktree가 아니라 Baron SSO 원본 `staging`을 먼저 바라본다.
|
||||
- 안정화 확인 후 Baron SSO 원본 `production`을 바라보는 구조로 전환한다.
|
||||
- 따라서 `baron-sso-tdc114plus-api`는 현재 개발/검증용 임시 worktree로 보고, 최종 운영 필수 구성으로 간주하지 않는다.
|
||||
|
||||
현재 1차 범위:
|
||||
|
||||
- Baron SSO Hosted Login + PKCE 로그인
|
||||
- 직원검색
|
||||
- 가족사/조직 탐색
|
||||
- 조직도
|
||||
- 직원 상세
|
||||
- 전화걸기/문자보내기
|
||||
- 즐겨찾기 로컬 저장
|
||||
|
||||
1차 보류:
|
||||
|
||||
- 공지사항
|
||||
- 전자결재
|
||||
- 수신전화식별
|
||||
- 수신팝업
|
||||
- 서버 기반 즐겨찾기 동기화
|
||||
|
||||
## 2. 작업진행 절차
|
||||
|
||||
| 순서 | 단계 | 상태 | 작업 내용 | 산출물 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | 저장소 및 앱 골격 준비 | 완료 | Flutter 프로젝트, 기본 문서, 기본 스크립트, 테스트 기반 구성 | `app/`, `docs/`, `scripts/` |
|
||||
| 2 | Mock 기반 화면 구축 | 완료 | 직원검색/조직도/상세/즐겨찾기 화면을 mock 데이터로 우선 구현 | 동작 가능한 UI 및 widget test |
|
||||
| 3 | API 연동 1차 구현 | 진행 중 | auth, directory, organization API client/repository 및 세션 저장 흐름 구현 | Flutter API 계층, 단위 테스트 |
|
||||
| 4 | Hosted Login + PKCE 전환 | 진행 중 | Baron SSO 인증 URL 생성, App Link callback, state 검증, PKCE token 교환, 세션 저장 흐름을 기본 로그인으로 반영 | auth client/repository/UI |
|
||||
| 5 | 분리형 API 정책 정리 | 완료 | RP, Swagger 중심 계약, mock/real 병행 개발 원칙 문서화 | 정책 문서 개정본 |
|
||||
| 6 | Swagger 기준 계약 재정렬 | 진행 중 | 실제 사용 endpoint와 DTO를 Swagger 기준으로 재확정하고 1차 사용 API/feature 매핑 문서를 추가했다 | 계약 문서 및 feature별 매핑 |
|
||||
| 7 | Repository/Mock 구조 정리 | 진행 중 | feature별 remote/mock 구현을 더 명확히 분리하기 위해 organization repository 추상화를 추가하고 directory의 직접 API client 의존을 한 단계 분리했다 | repository interface 및 mock 구현 |
|
||||
| 8 | 실제 API 정합성 검증 | 완료 | 로그인, 직원검색, 조직/테넌트 응답의 실제 정합성 점검 | smoke/integration 결과 |
|
||||
| 8-A | Android integration runtime 기준 정렬 | 완료 | 실제 API smoke 완료 후 Android target bridge 포트와 integration 실행 기준을 최신 정책값으로 정렬하고 재검증했다 | target/ADB 점검 결과 및 재실행 로그 |
|
||||
| 9 | staging 반영 검토 준비 | 진행 중 | 승인 완료 E2E, 예외 케이스, 환경값/롤백 경로 정리와 함께 실제 API 공백은 Baron SSO 이슈 명세로 분리 정리 | 수동 점검 체크리스트, API 보강 요청 초안 |
|
||||
| 9-A | 직원검색/조직도 UI 정렬 보정 | 진행 중 | 선택 칩 강조, 칩 overflow 스크롤 탐색, 조직도 인원 정렬 규칙을 정책과 코드에 반영 | 개정 정책 문서, widget test, emulator 확인 |
|
||||
| 9-B | 직원검색 규칙/프로필 표현 보강 | 진행 중 | 검색 범위 정책, 한글/전화번호 최소 입력 규칙, 프로필 사진 노출 가능 조건을 정책과 코드에 반영 | 개정 정책 문서, widget test, emulator 확인 |
|
||||
| 9-C | 프로필 사진 식별자 매핑 검토 | 진행 중 | 네이버웍스 우선, Baron SSO `members[].id` 기반 UUID 파일명 2순위, 앱 기본 아바타 3순위 구조로 정책을 재정렬하고 파일 재배치/앱 연동 기준을 정리 | 매핑 정책 문서, UUID 매핑 CSV, 샘플 URL 검증 |
|
||||
| 9-D | 입력기/구분 표식 보정 | 진행 중 | 직원검색 입력기의 한글 입력 친화 설정과 상하 영역 구분 표식을 정책과 코드에 반영 | 개정 정책 문서, widget test, emulator 확인 |
|
||||
| 9-E | 초기 선택 scope 재정렬 | 진행 중 | 앱 첫 진입 시 회사급이 아니라 본인 팀 뱃지가 실제 선택 상태가 되도록 정책과 코드에 반영하고, 중앙 구분 아이콘은 제거 | 개정 정책 문서, widget test, emulator 확인 |
|
||||
| 9-F | 공기계 USB 테스트 전환 | 진행 중 | emulator 기반 수동 검증의 반복 장애를 줄이기 위해 공기계 USB 연결, `adb reverse`, 실기기 env/preflight를 추가하고 수동 점검부터 안정화 | 공기계 정책 문서, device env 예시, preflight 스크립트, 수동 실행 결과 |
|
||||
| 9-G | 독립형 실기기 서버 연동 전환 | 진행 중 | USB reverse 기반 로컬 실행과 별도로, 공기계/실사용 폰이 USB 없이도 staging 또는 production Baron API에 직접 붙어 동작할 수 있도록 공개 base URL, 인증 흐름, APK 실행 조건을 정리 | 독립 실행 체크리스트, 환경값 표, 실서버 APK 검증 절차 |
|
||||
| 9-H | 레거시 전용 API 흔적 단계적 제거 | 진행 중 | `/api/v1/tdc114plus/...` 가정 path와 Baron 전용 DTO 흔적을 실제 Swagger path 매핑 기준으로 `유지/교체/제거` 분류하고, 기능 보존 테스트를 동반해 순차 제거 | 레거시 분류표, 대체 path 매핑, 기능 보존 테스트 결과 |
|
||||
| 9-I | Baron SSO RP/PKCE 연결 | 진행 중 | 등록된 PKCE RP의 issuer, callback, client ID를 앱 환경에 반영하고 Hosted Login 완료 후 OIDC 세션 연결을 검증 | RP 설정표, 앱 링크 설정, callback 수신 및 토큰 교환 테스트 |
|
||||
| 9-J | Headless 직접 호출 계약 정리 | 진행 중 | headless API 직접 호출은 앱 기본 흐름에서 제외하고, Baron SSO Hosted Login 내부 구현 참고사항으로 격하 | 정책 개정, 레거시 코드 제거 계획 |
|
||||
| 9-K | 로그인 후 org-context credential 수신 준비 | 진행 중 | Baron SSO가 로그인 성공 후 조직도 API 연동 키를 내려줄 예정이므로 세션 모델/저장소/API client에 선택적 credential 구조를 준비하고, 미개발 기간에는 staging env fallback을 유지 | AuthSession 확장, credential 우선순위, fallback 테스트 |
|
||||
| 10 | 빌드/배포 준비 | 대기 | Android debug APK, README, 잔여 이슈 정리 | APK 및 배포 준비 문서 |
|
||||
|
||||
## 3. 단계별 타임테이블
|
||||
|
||||
| 단계 | 상태 | 목표 | 주요 작업 | 완료 기준 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Phase 0 | 완료 | 저장소와 개발환경 출발점 확보 | clone, 문서 이관, Flutter 실행 기반 구성 | 기본 프로젝트 동작 |
|
||||
| Phase 1 | 완료 | Mock 기반 UI/상태 흐름 확보 | 로그인 화면, 직원검색, 조직도, 상세, 즐겨찾기 구성 | analyze/test 통과 |
|
||||
| Phase 2 | 완료 | 초기 API 연동 골격 확보 | auth/directory/organization client, repository, session 저장 | 단위 테스트 통과 |
|
||||
| Phase 3 | 진행 중 | 기본 로그인 흐름을 Hosted Login + PKCE 방식으로 전환 | authorization URL 생성, 외부 SSO 로그인, App Link callback, token 교환, 세션 저장 | PKCE 로그인 기본 흐름 코드 반영 |
|
||||
| Phase 4 | 진행 중 | Swagger 기준 계약 재정렬 | 실제 사용 endpoint/DTO/에러 구조 재확정, 1차 사용 API/feature 매핑 문서화 | 계약 문서와 코드 구조 정렬 |
|
||||
| Phase 5 | 진행 중 | feature별 분리형 구조 고정 | remote data source, repository interface, mock implementation 정리 | mock/real 전환 가능한 구조 확보 |
|
||||
| Phase 6 | 완료 | 실제 API 응답 정합성 점검 | 로그인, directory, organization smoke 및 integration 확인 | 핵심 응답 필드 일치 확인 |
|
||||
| Phase 7 | 진행 중 | staging 반영 검토 준비 | 승인 완료 E2E, 예외 케이스, 수동 체크리스트 정리, API 공백 이슈 분리 | staging 검토 가능 상태 및 API 보강 요청 초안 |
|
||||
| Phase 7-A | 진행 중 | 직원검색/조직도 시인성 보정 | 선택 상태가 눈에 띄는 칩 표현, 스크롤 가능한 칩 탐색, 조직도 인원 정렬 규칙 반영 | 캡쳐 요청사항 반영 및 widget test |
|
||||
| Phase 7-B | 진행 중 | 직원검색 규칙/프로필 표현 보강 | 검색 입력 최소 조건, 선택 범위 내 검색 원칙, 프로필 사진 노출 가능 구조 반영 | 정책 반영 및 emulator 확인 |
|
||||
| Phase 7-C | 진행 중 | 프로필 사진 식별자 매핑 검토 | 네이버웍스 우선, Baron SSO `members[].id` 기반 UUID 파일명 이미지 2순위, 앱 기본 아바타 3순위 구조를 기준으로 실제 매핑 가능 조건과 파일 재배치/앱 연동 기준을 정리 | UUID 매핑 CSV, 샘플 URL 검증, 앱 공통 resolver 정리 |
|
||||
| Phase 7-D | 진행 중 | 입력기/구분 표식 보정 | 직원검색 입력기의 한글 입력 친화 설정과 상하 영역 구분 표식 반영 | emulator 확인 및 사용성 점검 |
|
||||
| Phase 7-E | 진행 중 | 초기 선택 scope 재정렬 | 첫 진입 시 본인 팀을 실제 선택 상태로 맞추고 불필요한 중앙 아이콘 제거 | emulator 확인 및 정책 일치 |
|
||||
| Phase 7-F | 진행 중 | 공기계 USB 테스트 전환 | 실기기 연결 preflight, `adb reverse`, 실기기 env, 수동 실행 경로를 추가하고 emulator 경로는 fallback으로 보존 | 공기계에서 수동 post-login 점검 가능 |
|
||||
| Phase 7-G | 진행 중 | USB 없는 독립형 실기기 테스트 전환 | 공기계/실폰이 로컬 PC 연결 없이도 staging 또는 production Baron API에 직접 붙도록 공개 API base URL, HTTPS, headless 승인 로그인, APK 실행값을 정리 | USB 분리 후에도 앱이 실서버 기준으로 로그인/직원검색 가능 |
|
||||
| Phase 7-H | 진행 중 | 레거시 전용 API 흔적 단계적 제거 | 전용 API 가정 path와 Baron 종속 DTO를 `유지/교체/제거`로 분류하고, 각 단계마다 로그인/직원검색/조직도 기능 보존 테스트를 수행 | Swagger 기준 재매핑 후 기능 유지 상태 확보 |
|
||||
| Phase 7-I | 진행 중 | 등록된 Baron SSO RP와 앱 연결 | PKCE 공개 클라이언트 설정, HTTPS callback 수신, state 검증, authorization code 교환을 Hosted Login callback에 연결 | 실기기에서 SSO 로그인 완료 후 앱 세션 생성 |
|
||||
| Phase 7-J | 진행 중 | 로그인 후 조직도 API 키 수신 준비 | Baron SSO 로그인 성공 응답/후속 session 응답에서 org-context credential을 받을 수 있게 앱 모델을 확장하고, 미개발 동안 staging 고정 키 fallback을 유지 | session credential 우선, env fallback 보장 |
|
||||
| Phase 8 | 대기 | 빌드/배포 준비 | APK, 실행 문서, 잔여 이슈 정리 | 배포 준비 산출물 확보 |
|
||||
|
||||
## 4. 현재 진행 상태
|
||||
|
||||
완료된 핵심 항목:
|
||||
|
||||
- Flutter 앱 기본 프로젝트 및 테스트 기반 구성
|
||||
- 직원검색/조직도/상세/즐겨찾기 mock 화면 구축
|
||||
- auth, directory, organization API client 및 repository 초안 구성
|
||||
- 세션 저장/복원 흐름 구현
|
||||
- Baron SSO Hosted Login + PKCE callback 수신 경로 반영
|
||||
- 분리형 API 전환 정책 문서 수립
|
||||
- 개발 정책, API 계약, 테스트 정책 개정
|
||||
- 1차 사용 API 및 auth/directory/organization feature 매핑 문서화
|
||||
|
||||
진행 중 핵심 항목:
|
||||
|
||||
- Swagger 기준 실제 사용 API 목록 재정리
|
||||
- Hosted Login + PKCE 기준 실제 응답 정합성 점검
|
||||
- directory/organization 응답의 실제 데이터 정합성 검토
|
||||
- feature별 remote/mock 구조 정리
|
||||
- organization repository 추상화 추가 및 directory 직접 의존 완화
|
||||
- auth repository의 기본 경로와 fallback 경로 역할 분리
|
||||
- directory repository는 employees만, organization repository는 tenants만 담당하도록 1차 경계 분리
|
||||
- organization 상태 재사용은 `org-context` 중심으로 유지하고 공유 orgchart UI 연결은 후속 단계로 분리
|
||||
- `org-context` 전용 provider를 추가하고 실제 UI 연결은 후속 단계로 유지
|
||||
- auth/directory 구현체 명칭을 `Remote...Repository`로 일반화
|
||||
- 실제 API smoke와 Android emulator fallback integration smoke를 모두 통과했고, 당일 override 포트(`5561`) 기준 실행도 확인했다
|
||||
- Android integration 실행기는 현재 Flutter 버전 기준 `flutter drive` + `integration_test` driver 조합으로 정렬 완료했다
|
||||
- 조직 하위 subtree 응답 부재를 실제 API에서 확인했고, 앱 fallback 정책과 별도로 Baron SSO 보강 이슈를 문서화해 병행 진행한다
|
||||
- 직원검색/조직도 화면에 대해 선택 칩 시인성, overflow 스크롤, 조직도 인원 정렬 우선순위 보정 요청을 추가 반영 중이다
|
||||
- 직원검색 범위는 선택된 상단 뱃지 기준으로 유지하고, 최소 입력 규칙과 프로필 사진 표현 보강을 추가 반영 중이다
|
||||
- 프로필 사진은 현재 `profileImageUrl` 필드가 있으면 표현 가능하지만, 사번 기반 로컬/원격 이미지 매핑은 직원 DTO에 사번 식별자가 없어 추가 검토가 필요하다
|
||||
- 프로필 이미지 정책은 현재 `네이버웍스 우선 -> Baron SSO org-context UUID 파일명 이미지 -> 앱 기본 아바타` 기준으로 재정렬했다
|
||||
- 2026-07-20 기준 `tdc114plus-auth /api/v1/profile-image` route를 복구/보강하고, 네이버웍스 사진 원본 URL을 앱에 직접 주지 않도록 `/api/v1/profile-image/naver-photo` 프록시를 추가했다
|
||||
- 네이버웍스 `Location` 원본 URL은 앱이 직접 열 때 `400 Authentication failed`가 발생할 수 있으므로, 1순위 NAVER_WORKS 이미지는 중계서버 프록시를 통해 `image/jpeg` 바이너리로 제공한다
|
||||
- 2026-07-20 기준 실기기에서 기존에 기본 이니셜로 떨어지던 네이버웍스 사진 보유 인원의 이미지 표시가 정상화된 것을 확인했다
|
||||
- 같은 시점 서버 로그에서 `NAVER_WORKS`와 `BARON_UUID_R2` source가 모두 확인되어 1순위/2순위 분기 동작을 확인했다
|
||||
- 2026-07-15 기준 `org-context` 실응답에서 `members[].id`가 실제 UUID 형식으로 내려오는 것을 확인했다
|
||||
- 2026-07-15 기준 가족사 전체 `org-context`와 기존 CSV를 대조해 `2457/2457` 전건 UUID 매핑 성공을 확인했다
|
||||
- 관련 산출물로 `docs/references/profile_image_uuid_rename_candidates.csv`를 생성했다
|
||||
- 2026-07-15 기준 네이버웍스 서비스 계정 토큰 발급과 실제 User/Profile API 호출을 확인했다
|
||||
- 샘플 `khkang@samaneng.com`는 `GET /users/{userId}/photo` 결과 `HTTP 404`로 무사진 케이스를 확인했다
|
||||
- 샘플 `thlee3@samaneng.com`는 `GET /users/{userId}/photo` 결과 `HTTP 302`와 `Location` 헤더를 확인했다
|
||||
- 2026-07-15 기준 UUID 파일명 공개 URL 샘플 2건이 `HTTP 200 image/jpeg`로 응답하는 것을 확인했다
|
||||
- 기존 `tdc114plus-auth + PostgreSQL` profile-image fallback 경로는 기술 검증 자료로만 남기고, 현재 운영 기본안으로는 채택하지 않는다
|
||||
- 현재 Phase 7-C의 중심 작업은 `앱 공통 resolver를 새 우선순위로 정리`하고 `302 -> UUID -> 기본 아바타` fallback 분기를 연결하는 일이다
|
||||
- 2026-07-15 기준 Android 실기기 직원검색 화면에서 실제 프로필 사진 노출을 확인했다
|
||||
- 현재 앱은 `tdc114plus-auth /api/v1/profile-image`를 우선 호출하고, 응답 실패 또는 미발견 시 UUID 공개 경로 fallback을 사용하는 보조 안전장치를 함께 둔다
|
||||
- 2026-07-16 기준 실기기 로그인 후 직원검색이 다시 무너지는 핵심 원인은 `tdc114plus-auth` 5001 서버의 `org-context upstream self-recursion`이었다
|
||||
- 원인은 `scripts/start-auth-server.sh`가 `TDC114_AUTH_UPSTREAM_ORG_CONTEXT_API_BASE`를 env 파일 `source` 전에 읽던 순서 문제였고, 이 때문에 실행 중 `BARON_ORG_CONTEXT_BASE_URL`이 `http://127.0.0.1:5001`로 잘못 설정되었다
|
||||
- 2026-07-16 기준 해당 스크립트 순서를 수정하고 5001 재기동 후 실행 중 프로세스 환경값이 `BARON_ORG_CONTEXT_BASE_URL=https://sadmin.hmac.kr`로 반영된 것을 확인했다
|
||||
- 위 복구 이후 실기기에서 `로그인 성공 -> 직원검색 목록 표시 성공`까지 다시 확인했다
|
||||
- 직원검색 한글 입력은 코드상 차단 요소를 제거한 상태로 정렬하고, 상하 영역 구분 표식을 추가 반영 중이다
|
||||
- 초기 진입 선택 상태는 본인 팀 뱃지가 실제 선택되도록 재정렬 중이며, 중앙 구분 아이콘은 제거 방향으로 반영 중이다
|
||||
- Android emulator의 물리 키보드/ADB/portproxy 반복 장애가 확인되어, 공기계 USB 연결을 기본 수동 테스트 경로로 전환하는 작업을 시작한다
|
||||
- 공기계 USB 연결 기준으로는 실데이터 화면까지 확인했지만, 현재 실행 모드는 `adb reverse + http://127.0.0.1:5000` 기반 로컬 Baron API 연결이므로 USB 분리 후 독립 동작은 아직 보장하지 않는다
|
||||
- USB 없이 동작하는 실서버 APK 테스트로 가려면 `TDC114_API_BASE`를 staging 또는 production 공개 URL로 전환하고, headless 승인 로그인과 HTTPS 경로를 그 환경에서 다시 검증해야 한다
|
||||
- 2026-07-08 기준 앱/스크립트는 `TDC114_AUTH_API_BASE`, `TDC114_DIRECTORY_API_BASE`, `TDC114_ORGANIZATION_API_BASE` 분리 주입을 지원하므로 `로그인은 staging`, `직원/조직 데이터는 production` 조합까지 실행 준비가 되어 있다
|
||||
- 2026-07-10 기준 조직/직원 원본 참고 host는 staging `https://sadmin.hmac.kr`로 되돌린다. `admin.brsw.kr` production host는 현재 앱 개발 기준에서 우선 사용하지 않는다
|
||||
- 2026-07-10 기준 Baron SSO 로그인 성공 시 조직도 API 호출용 ID/Secret을 함께 내려주는 기능은 아직 미개발로 보고, 앱은 해당 값을 받을 준비만 먼저 한다
|
||||
- 해당 기능이 완성되기 전까지 조직/직원 데이터는 staging `org-context` endpoint와 로컬 비추적 env/Dart define의 고정 키 fallback으로 검증한다
|
||||
- 따라서 USB 없는 독립형 실기기 최종 검증의 현재 외부 blocker는 `신규앱 public TDC114_API_BASE` 확정이다
|
||||
- 2026-07-08 사용자 확인 기준으로는 `신규앱 public TDC114_API_BASE` 자체를 별도 `tdc114plus 전용 API host`로 찾는 방향이 아니라, Swagger에 공개된 Baron 기존 API path를 앱 데이터 소스로 직접 쓰는 방향으로 재정렬해야 한다
|
||||
- 따라서 현재 진짜 blocker는 `별도 host 탐색`이 아니라 `Swagger 공개 path 중 무엇이 직원검색/조직도/로그인에 대응하는지 endpoint 단위로 재매핑`하는 일이다
|
||||
- 그에 따라 현재 코드와 문서에 남아 있는 `/api/v1/tdc114plus/...` 전용 API 흔적은 레거시로 분류하고, 기능이 무너지지 않도록 테스트를 동반해 단계적으로 제거하는 것을 기본 작업원칙으로 추가한다
|
||||
- 2026-07-19 기준 배포 관점의 기준 구조를 다시 정리한다
|
||||
- `tdc114plus-auth`는 최종 배포 단위로 유지한다
|
||||
- `baron-sso-tdc114plus-api`는 현재 로컬 개발/검증용 worktree로만 취급하고, 배포 시점의 직접 필수 구성으로 보지 않는다
|
||||
- 최종적으로 신규앱은 Baron SSO 원본 `staging` 연동을 먼저 안정화하고, 이후 Baron SSO 원본 `production` 연동으로 승격하는 순서를 기본 정책으로 삼는다
|
||||
- 따라서 지금부터의 정리 작업은 `무엇을 tdc114plus-auth에 남길지`, `무엇을 Baron SSO 원본에 의존할지`, `무엇을 로컬 전용 임시 자산으로 볼지`를 분리하는 방향으로 진행한다
|
||||
|
||||
대기 중 핵심 항목:
|
||||
|
||||
- staging 승인 완료 E2E 검증
|
||||
- Android debug APK 빌드 및 실행 점검
|
||||
- 운영 전 저장소/보안 저장 방식 재검토
|
||||
|
||||
## 5. 다음 작업
|
||||
|
||||
다음 작업은 아래 순서로 진행한다.
|
||||
|
||||
1. 앱 직원검색/조직도/상세 화면의 공통 resolver를 `네이버웍스 -> UUID 파일명 -> 기본 아바타` 순서로 정리한다.
|
||||
2. 네이버웍스 `302`, `404` 실응답 규칙을 `tdc114plus-auth` 프록시와 UUID fallback 분기에 연결한 상태를 유지 검증한다.
|
||||
3. 샘플 사용자 외에 `UUID 이미지 성공`, `UUID 이미지 없음`, `이메일 누락`, `DEFAULT 기본 아바타` 케이스를 추가 검증한다.
|
||||
4. 먼저 5001 auth broker의 실행 중 upstream 값이 `https://sadmin.hmac.kr`로 유지되는지 재확인한다.
|
||||
5. 실기기 검증 전 `adb reverse tcp:5001 tcp:5001`, `adb reverse tcp:5000 tcp:5000`이 유지되는지 확인한다.
|
||||
6. 로그인 후 30초 이상 세션이 유지되는지 다시 확인한다.
|
||||
7. 조직 하위 subtree API 보강 요청 이슈 초안을 정리하고 Baron SSO 개발자 검토용 명세를 확정한다.
|
||||
8. Swagger 공개 path 중 직원검색/조직도/로그인에 대응하는 실제 endpoint를 표로 다시 정리한다.
|
||||
9. 현재 코드의 `/api/v1/tdc114plus/...` 가정 path를 `유지`, `교체`, `폐기`로 분류한다.
|
||||
10. `교체` 대상으로 분류된 path부터 대체 Swagger path/DTO를 코드와 mock에 반영한다.
|
||||
11. 각 교체 단계마다 `로그인`, `직원검색`, `조직도`, `초기 선택 scope` 기능 보존 테스트를 수행한다.
|
||||
12. `org-context` 응답을 기준으로 현재 앱 화면 요소와 모델 필드를 1:1 매핑한 판단서를 만든다.
|
||||
13. staging 승인 완료 E2E와 예외 케이스 범위를 체크리스트로 구체화한다.
|
||||
14. Hosted Login + PKCE 기준 수동 검증 절차를 Baron SSO RP 설정 기준으로 재정렬한다.
|
||||
15. 검토 결과를 test log와 체크리스트에 반영한다.
|
||||
16. USB reverse 기반 로컬 실행과 별도로, 실제 공개 path를 사용한 독립형 실기기 APK 검증 단계를 실행한다.
|
||||
17. Baron SSO RP의 전체 Client ID를 `TDC114_OIDC_CLIENT_ID`로 주입하고 discovery 문서의 실제 endpoint와 일치하는지 확인한다.
|
||||
18. `https://114.hmac.kr/auth/callback`이 앱으로 연결되는 HTTPS App Link 설정과 `assetlinks.json`을 검증한다.
|
||||
19. callback의 `state`, authorization code, PKCE `code_verifier` 검증 및 token 교환을 구현한다.
|
||||
20. AuthSession에 선택적 `orgContextCredential` 구조를 추가한다.
|
||||
21. `org-context` API client가 `session credential -> staging env fallback` 순서로 인증값을 선택하도록 정리한다.
|
||||
22. Baron SSO Hosted Login 시작부터 callback 수신, 세션 저장, 직원검색 진입까지 실기기 E2E를 수행한다.
|
||||
23. 현재 `baron-sso-tdc114plus-api`에 남아 있는 기능을 `배포 필수`, `개발 중 임시`, `제거 가능`으로 분류한다.
|
||||
24. `배포 필수` 기능 중 `tdc114plus-auth`로 흡수 가능한 항목과 Baron SSO 원본 `staging/prod` 의존으로 남겨야 할 항목을 구분한다.
|
||||
25. 로컬 Baron worktree 없이도 신규앱이 배포 구조에서 동작할 수 있도록 최종 연동도와 점검표를 만든다.
|
||||
|
||||
## 5-B. 2026-07-15 Phase 7-C 연속성 메모
|
||||
|
||||
다음 작업 재개 시 우선 확인할 기준점은 아래와 같다.
|
||||
|
||||
- 2순위 프로필 이미지 식별자는 Baron SSO `org-context`의 `members[].id`다.
|
||||
- 2026-07-15 기준 `members[].id`가 실제 UUID 형식으로 내려오는 것을 실조회로 확인했다.
|
||||
- 공개 이미지 prefix는 `https://baroncs.co.kr/employee_img/` 다.
|
||||
- 기존 매핑 원본은 `docs/references/file_rename_hash_results.csv` 다.
|
||||
- UUID 리네임 작업용 산출물은 `docs/references/profile_image_uuid_rename_candidates.csv` 다.
|
||||
- 2026-07-15 기준 기존 CSV `2457`건은 가족사 전체 `org-context` UUID와 전건 매핑 성공했다.
|
||||
- 2026-07-15 기준 UUID 파일명 공개 URL 샘플 2건은 `HTTP 200 image/jpeg` 응답을 확인했다.
|
||||
- 2026-07-15 기준 네이버웍스 사진 API는 `khkang@samaneng.com`에서 `404`, `thlee3@samaneng.com`에서 `302`를 확인했다.
|
||||
- 현재 운영 기본안은 `네이버웍스 -> UUID 파일명 이미지 -> 기본 아바타` 다.
|
||||
- 기존 `tdc114plus-auth + PostgreSQL` profile-image fallback 경로는 보류된 대안으로만 남긴다.
|
||||
- 2026-07-20 기준 네이버웍스 1순위 사진은 앱이 원본 `Location` URL을 직접 열지 않고 `tdc114plus-auth` 프록시를 통해 표시한다.
|
||||
- 2026-07-20 기준 `tdc114plus-auth`와 앱 테스트에서 1순위/2순위/3순위 fallback 및 NAVERWORKS 프록시 바이너리 응답을 검증했다.
|
||||
|
||||
다음날 또는 네트워크 장애 후 재개 순서는 아래를 기본으로 한다.
|
||||
|
||||
1. 5001 health와 `adb reverse 5001/5000`을 먼저 확인한다.
|
||||
2. 실기기에서 `NAVER_WORKS`, `BARON_UUID_R2`, `DEFAULT` source별 화면 검증을 확대한다.
|
||||
3. 직원 상세/조직도/즐겨찾기 화면에서도 동일 이미지 규칙이 유지되는지 확인한다.
|
||||
4. 필요 시 샘플 사용자 추가로 `{uuid}.jpg` 공개 URL 응답을 더 점검한다.
|
||||
|
||||
## 5-C. 2026-07-09 Baron SSO RP 확정값
|
||||
|
||||
| 항목 | 확정값/정책 |
|
||||
| --- | --- |
|
||||
| RP 유형 | PKCE 공개 클라이언트 |
|
||||
| OIDC issuer | `https://sso.hmac.kr/oidc` |
|
||||
| Discovery | `https://sso.hmac.kr/oidc/.well-known/openid-configuration` |
|
||||
| Authorization endpoint | `https://sso.hmac.kr/oidc/oauth2/auth` |
|
||||
| Token endpoint | `https://sso.hmac.kr/oidc/oauth2/token` |
|
||||
| UserInfo endpoint | `https://sso.hmac.kr/oidc/userinfo` |
|
||||
| Redirect URI | `https://114.hmac.kr/auth/callback` |
|
||||
| Client ID | `39d6190d-72f6-4a58-a84f-cdc5ece3e8af`를 APK 기본 설정에 포함하고 환경별로 `TDC114_OIDC_CLIENT_ID` 재정의 가능 |
|
||||
| Client Secret | 사용 금지. PKCE 앱에는 Client Secret이 없음 |
|
||||
|
||||
현재 반영 상태:
|
||||
|
||||
- Android callback host를 `114.hmac.kr`로 변경했다.
|
||||
- callback 화면과 `/auth/callback` 앱 라우트는 수신 준비 상태다.
|
||||
- OIDC issuer, redirect URI, Client ID 환경 주입 항목을 추가했다.
|
||||
- authorization 요청 생성, PKCE verifier 보관, code 교환은 다음 구현 단계다.
|
||||
- `114.hmac.kr` 서버의 Android App Link 위임 파일(`/.well-known/assetlinks.json`)이 준비되기 전에는 HTTPS 링크가 앱 대신 브라우저에서 열릴 수 있다.
|
||||
- 2026-07-09 최신 debug APK를 공기계에 설치하고 callback URL을 실행했으며, Android 앱 선택창이 표시되는 것까지 확인했다.
|
||||
- debug APK의 package/SHA-256 지문을 기준으로 `docs/references/assetlinks.debug.json`을 생성했다.
|
||||
- `https://114.hmac.kr/.well-known/assetlinks.json` 배포는 임시 Windows 테스트 서버 방식으로 검증한다.
|
||||
- 2026-07-09 임시 Windows 테스트 서버에서 `assetlinks.json`을 제공하고 외부 HTTPS HTTP 200/JSON 응답을 확인했다.
|
||||
- 구형 공기계는 자동 App Link 상태가 `undefined`여서 테스트 기본 앱을 지정했으며, callback URL이 TDC114PLUS `.MainActivity`를 직접 열고 `test-code`를 수신하는 것까지 확인했다.
|
||||
- RP 전체 Client ID를 APK 기본 설정에 반영했다.
|
||||
- 다음 작업은 authorization 요청 생성과 PKCE code 교환 구현이다.
|
||||
- 공식 headless API는 `private_key_jwt client_assertion`을 필수 요구하지만 등록 RP는 PKCE 공개 앱이므로, Flutter 앱의 기본 로그인 경로에서는 해당 API를 직접 호출하지 않는다.
|
||||
- 표준 PKCE 생성, state 검증, token 교환 계층을 우선 구현한다.
|
||||
|
||||
## 5-D. Phase 7-C 프로필 사진 식별자 매핑 검토 초안
|
||||
|
||||
현재 신규앱은 프로필 사진 파일을 자체 보관하지 않고, 외부 공개 경로의 이미지를 화면에 표시하는 방향을 기본 전제로 둔다.
|
||||
|
||||
현재 채택안의 핵심은 아래와 같다.
|
||||
|
||||
- 앱은 더 이상 `이메일 @앞부분.jpg` 파일명을 직접 만들지 않는다.
|
||||
- 앱은 해시 파일명도 직접 계산하지 않는다.
|
||||
- 2순위 프로필 이미지는 Baron SSO 조직도 `members[].id`를 파일명으로 사용하는 UUID 이미지다.
|
||||
- 공개 경로는 `https://baroncs.co.kr/employee_img/{uuid}.jpg` 규칙으로 고정한다.
|
||||
- 1순위는 네이버웍스, 3순위는 앱 기본 아바타다.
|
||||
|
||||
### 1. 목표
|
||||
|
||||
- 내부 파일명 규칙을 앱과 URL에서 직접 노출하지 않는다.
|
||||
- 기존 이미지 자산을 전면 재가공하지 않고도 단계적으로 재사용 가능하게 만든다.
|
||||
- 직원검색, 조직도, 직원 상세 화면에서 동일한 규칙으로 프로필 이미지를 노출한다.
|
||||
- 이미지가 없거나 매핑이 실패해도 기본 아바타로 안전하게 fallback 한다.
|
||||
|
||||
### 2. 외부서버(테이블) 측 단계별 작업 초안
|
||||
|
||||
1. 기존 이미지 파일을 Baron UUID 기준 `[uuid].jpg` 로 변경한다.
|
||||
2. 변경된 파일을 `employee_img/` 하위에 재배치한다.
|
||||
3. 샘플 사용자 여러 건의 공개 URL 응답을 검증한다.
|
||||
4. 네이버웍스 1순위 경로와 UUID 이미지 2순위 경로의 fallback 순서를 앱과 서버 역할에 맞게 반영한다.
|
||||
5. 이메일 변경이나 인사 이동이 생겨도 UUID 기준 파일명 정책이 유지되는지 운영 절차를 정리한다.
|
||||
|
||||
### 3. 신규앱 측 단계별 작업 초안
|
||||
|
||||
1. 현재 직원 DTO와 `org-context` 응답에서 `member.id`를 안정적으로 확보할 수 있는지 유지 확인한다.
|
||||
2. 앱은 `member.id` 또는 그와 동등한 Baron UUID를 이용해 2순위 이미지 URL을 만든다.
|
||||
2026-07-15 기준 앱 공통 resolver에서 기존 `GET /api/v1/profile-image` fallback 의존을 제거하고, `profileImageUrl -> https://baroncs.co.kr/employee_img/{uuid}.jpg -> 기본 아바타` 규칙으로 정리했다.
|
||||
3. 앱은 더 이상 이메일 기반 또는 해시 기반 파일명을 만들지 않는다.
|
||||
4. 화면별 fallback 처리
|
||||
이미지 조회 실패, key 누락, 외부서버 404, timeout 상황에서는 기본 아바타를 노출한다.
|
||||
프로필 사진 실패 때문에 직원검색/조직도 본문 데이터가 깨지거나 로딩이 멈추지 않도록 분리 처리한다.
|
||||
|
||||
5. 캐시 및 placeholder 정책 반영
|
||||
검색 결과 목록과 조직도는 동일 이미지가 반복 노출될 수 있으므로, 앱 이미지 캐시와 placeholder 표시 규칙을 함께 정리한다.
|
||||
|
||||
6. 테스트 시나리오 추가
|
||||
최소 검증 항목은 아래와 같다.
|
||||
- 네이버웍스 사진이 있을 때 1순위 이미지 노출
|
||||
- UUID 이미지가 있을 때 2순위 이미지 노출
|
||||
- UUID 이미지가 없을 때 기본 이미지 노출
|
||||
- 응답 지연 또는 timeout 시 화면 본문 기능 유지
|
||||
- 잘못된 사용자 이미지가 다른 직원에게 매핑되지 않는지 확인
|
||||
|
||||
### 4. 현재 판단 기준
|
||||
|
||||
- `이메일 @앞부분.jpg` 직접 조합 방식은 더 이상 채택하지 않는다.
|
||||
- 현재 기본안은 Baron SSO `members[].id` 기반 UUID 파일명 방식이다.
|
||||
- 가족사 전체 매핑 검증 결과 `2457/2457` 전건 대응이 확인됐으므로, 파일 재배치만 완료되면 운영 기준으로 사용할 수 있다.
|
||||
- 따라서 현재 Phase 7-C의 실질적 핵심은 `UUID 파일 실배치 완료`, `앱 공통 resolver 재정리`, 그리고 `tdc114plus-auth /api/v1/profile-image`를 `네이버웍스 -> UUID 이미지 -> 기본 아바타` 순서로 재정리한 뒤 실제 기동 검증까지 마무리하는 것이다.
|
||||
|
||||
### 5. 후속 확인 필요 항목
|
||||
|
||||
- 네이버웍스 개발자 계정 기준 실제 `GET /users/{userId}/photo` 응답 규칙
|
||||
- UUID 파일 재배치 완료 후 공개 URL 반영 시점
|
||||
- 퇴사자/미등록자 이미지 처리 기준
|
||||
- Baron UUID가 장기적으로 변경되지 않는지 운영 측 확인
|
||||
|
||||
## 5-A. 공기계 USB 테스트 전환 작업 순서
|
||||
|
||||
공기계 전환은 아래 순서로 진행한다. 예상 소요는 정책/스크립트 보강 20~30분, 실제 단말 연결 검증 10~20분이다.
|
||||
|
||||
1. 정책과 타임테이블에 공기계 USB 테스트 전환 단계를 먼저 반영한다.
|
||||
2. 실기기 전용 env 예시(`scripts/android-device.env.example`)를 추가한다.
|
||||
3. 실기기 preflight 스크립트(`scripts/check-android-device-env.sh`)를 추가한다.
|
||||
4. Windows ADB server 공유 방식에서 물리 단말이 `device`로 보이는지 확인한다.
|
||||
5. `adb reverse tcp:5000 tcp:5000`을 우선 적용하고, 실패하면 PC LAN IP 방식으로 fallback 한다.
|
||||
6. `manual-postlogin-run.sh`로 수동 기능점검을 먼저 안정화한다.
|
||||
7. 수동 점검이 통과하면 `integration_tests.sh`를 공기계 target으로 확장한다.
|
||||
8. 검증 결과를 test log와 관련 정책 문서에 기록한다.
|
||||
|
||||
## 5-B. USB 없는 독립형 실기기 테스트 전환 작업 순서
|
||||
|
||||
공기계에 앱이 설치되어 있어도, 현재처럼 `TDC114_API_BASE=http://127.0.0.1:5000`을 쓰는 실행 모드라면 USB를 뽑는 순간 로컬 Baron API 경로가 끊긴다. USB 없이도 동작하려면 아래 단계가 필요하다. 예상 소요는 환경 정리 20~30분, 실서버 APK 1차 검증 30~60분이다.
|
||||
|
||||
1. 실행 모드를 둘로 분리해 문서에 고정한다.
|
||||
- `로컬 개발 모드`: `adb reverse + http://127.0.0.1:5000`
|
||||
- `독립 실행 모드`: `https://<staging-or-production-host>`
|
||||
2. staging 또는 production 중 실제 실기기 검증에 사용할 Baron API base URL을 확정한다.
|
||||
3. 해당 환경에서 `headless phone-login`, `link/poll`, `integrations/org-context`, `public/orgchart`가 모두 공개 HTTPS 경로에서 정상 동작하는지 확인한다.
|
||||
4. 실기기 APK 전용 env 파일을 분리한다.
|
||||
- 예: `scripts/.env.android-device.staging.local`
|
||||
- 예: `scripts/.env.android-device.production.local`
|
||||
5. 로그인과 데이터 host를 분리해야 하면 아래 override를 함께 준비한다.
|
||||
- `TDC114_AUTH_API_BASE`
|
||||
- `TDC114_DIRECTORY_API_BASE`
|
||||
- `TDC114_ORGANIZATION_API_BASE`
|
||||
6. `manual-postlogin-run.sh` 또는 별도 실행 스크립트에서 실서버 URL과 필요한 override를 주입해 APK를 다시 설치한다.
|
||||
7. USB 연결 상태에서 1차 설치와 실행만 수행하고, 앱이 실행된 뒤 USB를 분리한다.
|
||||
8. USB 분리 후에도 Wi-Fi만으로 로그인, 직원검색, 조직도 조회가 유지되는지 확인한다.
|
||||
9. 실사용 폰 설치 전에는 아래를 추가 확인한다.
|
||||
- 앱 아이콘/앱명/버전 표기
|
||||
- cleartext 미사용 여부
|
||||
- staging/production 혼선이 없는지
|
||||
- headless 승인 로그인 수신 채널(문자/메일) 실제 도달 여부
|
||||
10. 실사용 폰 테스트 단계에서는 APK 전달, 설치, 로그인 승인, 검색/조직도/전화/문자 동작까지 한 번의 시나리오로 점검한다.
|
||||
|
||||
## 6. 작업 기록 원칙
|
||||
|
||||
- 새 작업이 생기면 본 문서의 `작업진행 절차` 또는 `다음 작업`에 반영한다.
|
||||
- 완료된 작업은 상태를 갱신하고 산출물 위치를 기록한다.
|
||||
- 중요 실행 결과는 `docs/test-logs/` 또는 `docs/daily-issues/`에 남긴다.
|
||||
- 과거 세부 이력은 보존하되, 현재 실행 기준은 본 문서의 최신 Phase 상태를 따른다.
|
||||
@@ -1,7 +1,7 @@
|
||||
# tdc114plus-auth 저장소 운영 정책
|
||||
|
||||
작성일: 2026-07-15
|
||||
상태: v1.0
|
||||
상태: v1.1
|
||||
|
||||
목적: `tdc114plus-auth` 중계서버의 공식 Gitea 저장소 위치와 저장소 경계 운영 기준을 고정한다.
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
- `tdc114plus-auth`는 별도 Gitea 저장소로 관리한다.
|
||||
- `tdc114plus` 앱 저장소 안에 서버 본체 코드를 함께 두지 않는다.
|
||||
- `baron-sso` 저장소 안에도 흡수하지 않는다.
|
||||
- 최종 배포 기준에서도 `tdc114plus-auth`는 독립 배포 단위로 유지한다.
|
||||
- 다만 현재 로컬 개발에 쓰는 `baron-sso-tdc114plus-api` worktree는 최종 배포 필수 구성으로 보지 않는다.
|
||||
- 최종 운영 구조는 Baron SSO 원본 `staging` 연동 안정화 후 Baron SSO 원본 `production` 연동으로 승격하는 방향을 기본값으로 삼는다.
|
||||
|
||||
공식 저장소:
|
||||
|
||||
@@ -186,6 +189,25 @@ ops(staging): adjust auth broker env defaults
|
||||
|
||||
예를 들어 `scripts/start-auth-server.sh`는 `tdc114plus-auth` worktree 경로를 참조하는 보조 도구로 유지할 수 있지만, 서버 구현 본체는 별도 저장소에 있어야 한다.
|
||||
|
||||
## 8-A. 로컬 Baron worktree와의 관계
|
||||
|
||||
현재 개발 과정에서는 아래 세 축이 함께 보일 수 있다.
|
||||
|
||||
- `tdc114plus`
|
||||
- `tdc114plus-auth`
|
||||
- `baron-sso-tdc114plus-api`
|
||||
|
||||
하지만 이 중 최종 배포 직접 대상은 아래 두 축으로 본다.
|
||||
|
||||
- `tdc114plus`
|
||||
- `tdc114plus-auth`
|
||||
|
||||
정리 원칙:
|
||||
|
||||
- `baron-sso-tdc114plus-api`는 개발 중 API 확인, 임시 연동, 로컬 재현을 위한 worktree로 본다.
|
||||
- 배포 직전에는 `tdc114plus-auth`가 어떤 기능을 계속 직접 수행해야 하는지와, 어떤 기능이 Baron SSO 원본 `staging/prod` 의존으로 남는지를 명확히 분리해야 한다.
|
||||
- 로컬 Baron worktree가 꺼져도 배포 구조 자체에는 영향이 없도록 정리하는 것이 목표다.
|
||||
|
||||
## 9. 최종 판단
|
||||
|
||||
- `tdc114plus-auth`는 별도 저장소가 필요한 독립 서비스다.
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
# tdc114plus 분리형 API 전환 정책
|
||||
|
||||
작성일: 2026-07-07
|
||||
상태: v1.3
|
||||
|
||||
목적: `tdc114plus` Flutter 앱을 Baron SSO 백엔드 소스 직접 의존 방식에서 분리하고, 공식 API 인터페이스 중심 구조로 전환하기 위한 작업 원칙과 단계별 진행 순서를 고정한다.
|
||||
|
||||
기준 인터페이스:
|
||||
|
||||
- Swagger/API Docs: `https://sadmin.hmac.kr/api/docs#/`
|
||||
|
||||
운영 전환 메모:
|
||||
|
||||
- 2026-07-10 팀장 지시 기준으로 Baron SSO 원본 참고 API 기준은 production(`admin.brsw.kr`)이 아니라 staging(`sadmin.hmac.kr`)으로 다시 본다.
|
||||
- 실제 배포 전까지 신규앱에서 사용하는 Baron SSO API 참고 기준은 staging Swagger(`https://sadmin.hmac.kr/api/docs#/`)다.
|
||||
- 조직/직원 데이터 검증은 staging `GET https://sadmin.hmac.kr/api/v1/integrations/org-context`를 우선 사용한다.
|
||||
- Baron SSO가 로그인 성공 후 조직도 API 연동 키를 내려주는 기능은 아직 미개발이므로, 앱은 받을 준비를 하되 현재 개발/검증은 로컬 비추적 env/Dart define의 staging 고정 키 fallback으로 진행한다.
|
||||
- 운영 `CLIENT ID`, `X-Baron-Key-Secret` 실제 값은 tracked 문서나 tracked 앱 코드에 넣지 않고 로컬 비추적 `.env`에만 저장한다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`
|
||||
|
||||
## 1. 최우선 원칙
|
||||
|
||||
- 신규 앱은 Baron SSO에 추가되는 별도 `RP(Relying Party)`로 간주한다.
|
||||
- 신규 앱은 Baron SSO 백엔드 소스를 직접 수정해서 맞추는 방식으로 개발하지 않는다.
|
||||
- 앱은 Swagger에 정의된 공식 Request/Response 계약을 기준으로만 통신 계층을 설계한다.
|
||||
- 백엔드 구현 완료 여부와 무관하게 Flutter 앱은 mock 데이터와 repository 추상화로 독립 개발 가능해야 한다.
|
||||
- 기존 코드가 동작하더라도 Swagger 계약과 다르면 계약 기준으로 재정렬한다.
|
||||
- Baron SSO 관련 명칭, 경로, DTO가 앱 내부에 과도하게 박혀 있으면 점진적으로 일반화한다.
|
||||
- 인증 기본 원칙은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`다.
|
||||
- Flutter 앱은 휴대폰번호/문자/메일 인증을 직접 처리하는 headless API 클라이언트가 아니라, Baron SSO 인증 URL을 열고 callback의 authorization code를 token으로 교환하는 공개 RP다.
|
||||
- 휴대폰번호 입력과 링크 발송/승인 처리는 Baron SSO Hosted Login 화면과 서버 내부 구현으로 둔다.
|
||||
- Swagger Auth 섹션의 `phone-login`, `headless`, `enchanted-link`, `sms`, `qr` 계열 API는 Baron SSO 화면/서버 내부 구현 참고사항으로 분류하고 앱 기본 로그인 구현에서 직접 조합하지 않는다.
|
||||
- 기존 `선진행 후확인` 방식은 신규 앱의 기본 로그인 정책으로 채택하지 않는다.
|
||||
- 현재 코드와 문서에 남아 있는 `/api/v1/tdc114plus/...` 전용 API 가정은 레거시 흔적으로 분류한다.
|
||||
- 레거시 흔적 제거는 한 번에 삭제하지 않고 `실제 사용처 확인 -> 대체 Swagger path 매핑 -> mock/real 테스트 통과 -> 제거` 순서로 진행한다.
|
||||
- 레거시 제거 과정에서 기능이 무너지지 않도록 기존 화면 동작, 로그인 흐름, 검색/조직 표시를 단계별로 검증한다.
|
||||
|
||||
## 2. 판단 결론
|
||||
|
||||
- 개발환경은 새로 갈아엎지 않는다.
|
||||
- 기존 Flutter 프로젝트 뼈대는 유지한다.
|
||||
- 다만 API 계층, 모델 계층, 환경설정, 테스트 기준은 분리 아키텍처에 맞게 중간 규모로 재정비한다.
|
||||
|
||||
즉, 이번 작업은 `재시작`이 아니라 `구조 개편형 마이그레이션`으로 본다.
|
||||
|
||||
## 3. 작업 범위
|
||||
|
||||
포함:
|
||||
|
||||
- Swagger 기준 API 목록 재정리
|
||||
- RP 관점의 인증 흐름 정리
|
||||
- Request/Response DTO 정리
|
||||
- API client/service/repository 계층 정리
|
||||
- mock 구현 및 테스트 데이터 정비
|
||||
- 화면이 repository interface만 의존하도록 연결 정리
|
||||
- 환경별 base URL 및 인증 헤더 주입 방식 정리
|
||||
- 문서/테스트/개발 순서 정리
|
||||
|
||||
제외:
|
||||
|
||||
- Baron SSO 운영 백엔드 내부 로직 직접 수정
|
||||
- Swagger에 없는 비공식 응답 구조 전제 개발
|
||||
- 화면 요구사항과 무관한 대규모 UI 재설계
|
||||
- 1차 범위 밖 기능 추가
|
||||
|
||||
## 4. 단계별 진행 순서
|
||||
|
||||
### Phase 1. 계약 기준 고정
|
||||
|
||||
작업:
|
||||
|
||||
- Swagger에서 신규 앱에 실제 필요한 endpoint만 1차 사용 목록으로 확정한다.
|
||||
- 신규 앱 RP 등록/식별에 필요한 인증 전제와 로그인 시작점을 함께 정리한다.
|
||||
- 각 endpoint별 method, path, request, response, error 형식을 앱 기준 표로 정리한다.
|
||||
- 기존 내부 문서와 Swagger가 다르면 Swagger를 우선 기준으로 명시한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 앱에서 사용할 API 목록과 필수 필드가 문서로 고정되어 있다.
|
||||
|
||||
### Phase 2. 앱 내부 의존성 분리 설계
|
||||
|
||||
작업:
|
||||
|
||||
- feature별로 `remote data source -> repository interface -> UI` 흐름을 고정한다.
|
||||
- 특정 백엔드 구현체 이름이 드러나는 타입명은 일반화 대상 목록으로 분류한다.
|
||||
- 인증, 직원검색, 조직도, 즐겨찾기 중 실제 API 의존 기능과 로컬 기능을 분리한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 어떤 레이어가 Swagger 계약에 직접 의존하고, 어떤 레이어가 추상화에 의존하는지 구조가 정리되어 있다.
|
||||
|
||||
### Phase 3. DTO 및 API 클라이언트 정렬
|
||||
|
||||
작업:
|
||||
|
||||
- 현재 Dart 모델을 Swagger 응답 구조 기준으로 재검토한다.
|
||||
- endpoint별 request/response DTO를 feature 단위로 정리한다.
|
||||
- 공통 에러 모델, 타임아웃, 인증 헤더, base URL 처리 방식을 통일한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 각 feature의 API 호출 코드가 Swagger 계약과 1:1로 대응된다.
|
||||
|
||||
### Phase 4. Repository 추상화 및 Mock 우선 개발
|
||||
|
||||
작업:
|
||||
|
||||
- repository interface를 기준으로 remote/mock 구현체를 분리한다.
|
||||
- 백엔드 미구현 또는 스펙 검증 전 단계에서는 mock repository로 화면 개발이 가능하도록 유지한다.
|
||||
- widget test와 unit test가 실제 네트워크 없이도 핵심 흐름을 검증하도록 구성한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- API가 불완전해도 화면 개발과 테스트가 계속 가능하다.
|
||||
|
||||
### Phase 5. 실제 API 연결
|
||||
|
||||
작업:
|
||||
|
||||
- 환경값으로 Swagger 대상 base URL을 주입한다.
|
||||
- mock 구현을 유지한 채 remote 구현을 교체 가능하게 연결한다.
|
||||
- 로그인, 직원검색, 조직도 등 우선 기능부터 실제 응답 정합성을 점검한다.
|
||||
- 로그인은 `authorization URL 생성 -> 외부 Hosted Login 완료 -> App Link callback 수신 -> state 검증 -> PKCE token 교환 -> session 저장` 완료 기준으로 본다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 동일한 UI가 mock/real repository 전환만으로 동작한다.
|
||||
|
||||
### Phase 6. 정리 및 고정
|
||||
|
||||
작업:
|
||||
|
||||
- Baron SSO 직접 의존 흔적, 임시 fallback, 오래된 계약 문구를 문서와 코드에서 정리한다.
|
||||
- `/api/v1/tdc114plus/...`처럼 전용 API를 전제한 레거시 경로는 `유지`, `교체`, `제거`로 분류한 뒤 순차적으로 없앤다.
|
||||
- 각 제거 단계마다 최소한 `로그인`, `직원검색`, `조직 탐색`, `조직도` 동작 확인을 먼저 수행한다.
|
||||
- 테스트 기준과 수동 점검 순서를 갱신한다.
|
||||
- 이후 신규 기능도 같은 패턴으로 추가하도록 개발 규칙을 고정한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 팀이 같은 방식으로 후속 기능을 이어서 개발할 수 있다.
|
||||
|
||||
## 5. 실제 실행 우선순위
|
||||
|
||||
가장 먼저 할 일:
|
||||
|
||||
1. Swagger 기준 1차 사용 API 목록 확정
|
||||
2. 현재 코드의 API/DTO/repository 구조와 Swagger 차이점 목록화
|
||||
3. 차이가 큰 feature부터 DTO와 repository interface 정리
|
||||
4. mock 구현 유지 상태에서 remote 구현 교체
|
||||
5. 실제 API smoke 및 화면 검증
|
||||
|
||||
## 6. 수정 방식 원칙
|
||||
|
||||
- 한 번에 전체 기능을 갈아엎지 않는다.
|
||||
- feature 단위로 `계약 확인 -> DTO 정리 -> repository 정리 -> mock 유지 -> UI 연결` 순서로 바꾼다.
|
||||
- 레거시 endpoint 제거는 `대체 endpoint 반영 -> 테스트 통과 -> 실제 화면 확인` 이후에만 진행한다.
|
||||
- 화면 코드가 API 응답 JSON 구조를 직접 해석하는 형태는 금지한다.
|
||||
- UI에서 HTTP, header, endpoint path를 직접 다루지 않는다.
|
||||
- mock 데이터는 임시 코드가 아니라 공식 개발 수단으로 유지한다.
|
||||
|
||||
## 7. 문서 반영 원칙
|
||||
|
||||
- Swagger 기준 변경사항이 생기면 문서와 코드 중 문서를 먼저 갱신한다.
|
||||
- 새 endpoint를 쓰기 시작하면 request/response 예시와 필수 필드를 문서에 남긴다.
|
||||
- 진행 상태가 바뀌면 `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`를 함께 갱신한다.
|
||||
|
||||
## 8. 이번 저장소에서의 즉시 적용 해석
|
||||
|
||||
현재 저장소는 아래 판단으로 진행한다.
|
||||
|
||||
- Flutter 앱 기본 프로젝트와 테스트 기반은 유지한다.
|
||||
- 기존 `auth`, `directory`, `organization`, `favorites` 구조는 재사용한다.
|
||||
- `BaronSso...`처럼 구현체 이름에 종속된 부분은 점진적으로 일반화한다.
|
||||
- 기존 Baron SSO 전용 계약 문서는 유지하되, 앞으로는 Swagger 기준 문서가 상위 실행 기준이 된다.
|
||||
- 앞으로의 구현 순서는 이 문서의 Phase 순서를 따른다.
|
||||
|
||||
## 9. 다음 작업 시작점
|
||||
|
||||
다음 작업은 아래 순서로 시작한다.
|
||||
|
||||
1. Swagger 기준 1차 사용 API를 문서로 고정한다.
|
||||
2. 현재 Flutter 코드에서 그 API를 쓰는 feature를 매핑한다.
|
||||
3. feature별 차이점과 수정 우선순위를 정리한다.
|
||||
4. 우선순위 1 feature부터 코드 개편을 시작한다.
|
||||
@@ -0,0 +1,121 @@
|
||||
# tdc114plus 개발 정책
|
||||
|
||||
작성일: 2026-07-02
|
||||
최종 개정일: 2026-07-10
|
||||
상태: v2.2
|
||||
|
||||
목적: `tdc114plus` 개발 시 Baron SSO 연동 원칙, Flutter 앱 구조, 문서 우선순위, 테스트 및 협업 기준을 고정한다.
|
||||
|
||||
상위 기준 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
|
||||
## 1. 서비스 및 인증 전제
|
||||
|
||||
- `tdc114plus` 신규 앱은 Baron SSO에 추가되는 별도 `RP(Relying Party)`다.
|
||||
- 앱 인증은 Baron SSO가 제공하는 공식 인증 절차를 소비하는 방식으로 설계한다.
|
||||
- 신규 앱의 기본 로그인 방식은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`다.
|
||||
- 신규 앱은 Baron SSO에 등록된 `PKCE 공개 클라이언트 RP`이며 Client Secret을 앱 코드, APK, 환경 파일에 저장하지 않는다.
|
||||
- `private_key_jwt` 서명용 개인키도 공개 모바일 APK에 포함하지 않는다.
|
||||
- Flutter 앱은 Baron headless API(`/api/v1/auth/headless/...`)를 직접 호출하지 않는다.
|
||||
- 휴대폰번호 입력, 문자/메일 링크 발송, 링크 승인 처리는 Baron SSO Hosted Login 화면과 Baron SSO 서버 내부 책임으로 본다.
|
||||
- RP의 OIDC issuer는 `https://sso.hmac.kr/oidc`, 인증 callback은 `https://114.hmac.kr/auth/callback`을 기준으로 한다.
|
||||
- 앱은 authorization 요청 전 PKCE `code_verifier`, `state`, `nonce`를 생성/보관하고, callback에서 `state` 검증 후 `code_verifier`로 authorization code를 교환한다.
|
||||
- 전체 Client ID `39d6190d-72f6-4a58-a84f-cdc5ece3e8af`는 공개 RP 식별자이므로 APK 기본 설정에 포함한다.
|
||||
- 환경별 RP가 달라질 경우 `TDC114_OIDC_CLIENT_ID` Dart define으로 기본값을 재정의할 수 있다.
|
||||
- 기본 로그인 순서는 `앱 -> Baron SSO 인증 URL 열기 -> Hosted Login 화면에서 휴대폰번호 입력 -> 문자/메일 링크 인증 -> https://114.hmac.kr/auth/callback -> 앱 복귀 -> code를 token으로 교환`이다.
|
||||
- 로그인 성공 후 Baron SSO가 조직도 API 호출에 필요한 연동 키 묶음을 전달하는 것을 최종 계약으로 준비한다.
|
||||
- 해당 Baron SSO 기능이 미개발인 동안에는 staging `org-context` 검증을 위해 로컬 비추적 env/Dart define에만 고정 키를 둘 수 있다.
|
||||
- 이 임시 고정 키는 tracked 문서, tracked 소스, 운영 APK 기본값에 넣지 않는다.
|
||||
- 기존 Baron SSO의 `선진행 후확인` 방식은 신규 앱의 기본 로그인 정책으로 사용하지 않는다.
|
||||
- 기존 `phone-login`이 남아 있더라도 개발용 fallback 또는 제한적 호환 경로로만 본다.
|
||||
|
||||
## 2. Baron SSO 연동 원칙
|
||||
|
||||
- 신규 앱은 Baron SSO 백엔드 소스를 직접 수정해서 맞추는 방식으로 개발하지 않는다.
|
||||
- 앱은 Swagger에 정의된 공식 Request/Response 계약을 기준으로만 통신 계층을 설계한다.
|
||||
- 실제 배포 전까지 앱이 참고하고 검증할 Baron SSO API 문서는 staging `https://sadmin.hmac.kr/api/docs#/`를 기준으로 한다.
|
||||
- 조직/직원 데이터 API는 staging `GET https://sadmin.hmac.kr/api/v1/integrations/org-context`를 우선 기준으로 검증한다.
|
||||
- Baron SSO 내부 구현은 참고 대상일 뿐, 앱의 상위 기준은 공식 인터페이스 문서다.
|
||||
- 기존 API 응답을 앱 요구사항에 맞게 임의로 바꾸는 것을 기본 전제로 삼지 않는다.
|
||||
- Baron SSO 관련 명칭, 경로, DTO가 앱 코드에 과도하게 박혀 있으면 점진적으로 일반화한다.
|
||||
- Baron SSO backend/orgFront 변경과 `tdc114plus` Flutter 앱 변경은 저장소와 커밋을 분리한다.
|
||||
|
||||
## 3. 인터페이스 중심 개발 원칙
|
||||
|
||||
- 프론트엔드와 백엔드는 API 계약을 먼저 고정한 뒤 병행 개발한다.
|
||||
- Flutter 앱은 `request/response DTO`, `API client`, `repository interface`, `UI`를 분리한다.
|
||||
- UI는 repository interface만 의존해야 하며, HTTP 세부사항을 직접 다루지 않는다.
|
||||
- 화면 코드가 JSON 응답 구조를 직접 해석하는 형태는 금지한다.
|
||||
- 백엔드 구현이 완료되지 않았더라도 mock 데이터와 mock repository로 화면 개발이 가능해야 한다.
|
||||
- API 계약이 바뀌면 문서, DTO, service, repository, test를 함께 갱신한다.
|
||||
|
||||
## 4. Flutter 공통 구현 원칙
|
||||
|
||||
- 공통 Flutter 코드는 처음부터 Android/iOS 모두를 고려해 작성한다.
|
||||
- 화면, 상태관리, API client, repository, model은 플랫폼 공통 코드로 우선 설계한다.
|
||||
- 플랫폼별 차이가 있는 기능은 공통 interface를 먼저 만들고 Android/iOS 구현체를 분리한다.
|
||||
- 인증 UI와 상태관리는 `SSO 로그인 시작 -> 외부 Hosted Login -> App Link callback -> state 검증 -> token 교환 -> 세션 저장` 흐름을 기준으로 설계한다.
|
||||
- Flutter 앱은 승인 링크 자체를 생성하거나 RP 비밀값, `client_assertion`, 개인키를 보관하지 않는다.
|
||||
- 화면 UX, 기본값, 조직 탐색 규칙은 `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`를 기준으로 삼는다.
|
||||
- 공지사항, 전자결재, 수신전화식별, 수신팝업은 1차 범위에서 보류한다.
|
||||
- 1차 범위는 직원검색, 전화번호검색, 가족사 필터, 조직도, 직원목록, 전화걸기, 문자보내기, 즐겨찾기에 집중한다.
|
||||
|
||||
## 5. 플랫폼별 구현 원칙
|
||||
|
||||
- 플랫폼별 네이티브 기능은 Android에서 먼저 PoC를 완성한 뒤 iOS로 확장한다.
|
||||
- iOS를 지나치게 늦게 검증하지 않는다.
|
||||
- 푸시, 생체 인증, 보안 저장소, bridge는 공통 인터페이스와 플랫폼 구현체를 분리한다.
|
||||
- 운영 배포 전에는 Android/iOS 모두 동일한 보안 기준을 통과해야 한다.
|
||||
|
||||
## 6. 개발 방식
|
||||
|
||||
- 작업은 `계약 확인 -> DTO 정리 -> repository 정리 -> mock 유지 -> UI 연결 -> 실제 API 검증` 순서로 진행한다.
|
||||
- 한 번에 전체 기능을 갈아엎지 않고 feature 단위로 점진 개편한다.
|
||||
- mock 데이터는 임시 코드가 아니라 병행 개발을 위한 공식 수단으로 유지한다.
|
||||
- 실제 API 연결 전에도 widget test와 unit test가 가능한 구조를 우선 만든다.
|
||||
- 구현체 이름이 강하게 박힌 타입명은 점진적으로 일반화한다.
|
||||
|
||||
## 7. 검증 원칙
|
||||
|
||||
Flutter 앱 변경 시 최소 검증:
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh analyze
|
||||
./scripts/flutter-docker.sh test
|
||||
```
|
||||
|
||||
상세 테스트 기준은 아래 문서를 따른다.
|
||||
|
||||
- `docs/00_policy_tdc114plus_testing_2026-07-02.md`
|
||||
|
||||
실제 API 연동 검증은 아래 기준을 따른다.
|
||||
|
||||
- Swagger 계약과 DTO 필드 일치 확인
|
||||
- Hosted Login authorization URL 생성, App Link callback 수신, `state` 검증, PKCE token 교환, 세션 저장, 로그인 후 첫 화면 진입 확인
|
||||
- mock 경로와 real API 경로가 동일한 UI 흐름을 유지하는지 확인
|
||||
|
||||
## 8. 질문 및 확인 원칙
|
||||
|
||||
작업 진행 중 판단이 필요하면 아래 순서로 진행한다.
|
||||
|
||||
1. 관련 정책 문서를 먼저 확인한다.
|
||||
2. 문서 기준으로 처리 가능한 것은 바로 진행한다.
|
||||
3. 정책 간 충돌, 해석 불명확, 보안 영향, 배포 영향이 있는 경우에만 질문한다.
|
||||
4. 질문 시에는 확인한 문서, 판단 포인트, 선택지, 권장안을 함께 정리한다.
|
||||
5. 새로운 결정이 내려지면 관련 문서와 타임테이블을 함께 갱신한다.
|
||||
|
||||
## 9. 문서 우선순위
|
||||
|
||||
개발 중 판단 기준은 아래 순서로 적용한다.
|
||||
|
||||
1. `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
2. `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
3. `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
4. `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`
|
||||
5. `docs/00_policy_tdc114plus_testing_2026-07-02.md`
|
||||
6. `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
7. `docs/guide_baron_sso_reference_source_2026-07-02.md`
|
||||
8. `docs/references/baron-safe-policies/`
|
||||
|
||||
참고 문서는 배경자료이며, 직접 정책보다 우선하지 않는다.
|
||||
@@ -0,0 +1,250 @@
|
||||
# tdc114plus 화면별/기능별 정책
|
||||
|
||||
작성일: 2026-07-07
|
||||
상태: v1.3
|
||||
|
||||
목적: `tdc114plus` 앱의 주요 화면과 기능이 어떤 규칙으로 동작해야 하는지 화면 단위로 고정한다. 구현 변경 시 이 문서를 기준으로 화면 UX와 상태 규칙을 판단한다.
|
||||
|
||||
운영 원칙:
|
||||
|
||||
- 앱 화면/기능을 수정하기 전에는 반드시 이 문서를 먼저 확인한다.
|
||||
- 수정 요청이 이 문서의 정책과 일치하는지 먼저 비교한다.
|
||||
- 문서 정책과 충돌하는 작업이 필요하면, 충돌 항목과 변경 영향 범위를 사용자에게 상세히 설명하고 명시 허락을 받은 뒤 진행한다.
|
||||
- 정책 변경이 확정된 뒤 구현을 바꾸는 경우, 정책 문서를 먼저 또는 같은 작업 단위 안에서 함께 갱신한다.
|
||||
- APK 빌드/실기기 설치는 사용자의 명시 허락 후 진행한다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
- `docs/policy_android_app_install_execution_2026-07-06.md`
|
||||
|
||||
## 1. 공통 원칙
|
||||
|
||||
- Baron SSO 로그인/세션 결과를 임의로 변형하지 않는다.
|
||||
- 가족사/조직 탐색은 Baron SSO `tenant` 계층을 기준으로 진행한다.
|
||||
- 직원검색 기본 첫 화면은 `본인 회사급 범위`를 기준으로 한다.
|
||||
- 사용자가 명시적으로 조직 탐색을 시작했을 때만 `전체 -> 회사 -> 하위조직 -> 개인` 단계형 탐색으로 전환한다.
|
||||
- 실제 API가 화면 정책을 충족하지 못하는 경우, fallback 동작을 문서화하고 필요한 API 보강 이슈를 별도로 작성해 병행 진행한다.
|
||||
- 화면 정책이 바뀌면 widget test와 정책 문서를 함께 갱신한다.
|
||||
|
||||
## 2. AuthGate 화면 정책
|
||||
|
||||
대상:
|
||||
|
||||
- 앱 첫 진입
|
||||
- 저장 세션 확인
|
||||
|
||||
규칙:
|
||||
|
||||
- 저장된 유효 세션이 있으면 `직원검색`으로 이동한다.
|
||||
- 저장 세션이 없으면 `Baron SSO 로그인` 화면으로 이동한다.
|
||||
- smoke/manual 실행에서 preauth session seed가 있으면 해당 세션을 그대로 사용한다.
|
||||
|
||||
## 3. 로그인 화면 정책
|
||||
|
||||
대상:
|
||||
|
||||
- `Baron SSO 로그인`
|
||||
|
||||
규칙:
|
||||
|
||||
- 신규 앱 기본 로그인 UX는 `전화번호 입력 -> 바론SSO 로그인 링크 발송 -> 문자 링크 클릭 -> 승인 완료 -> 앱으로 복귀 -> 앱 진입`이다.
|
||||
- 로그인 화면은 앱 내부에 전화번호 입력창을 제공한다.
|
||||
- 로그인 화면은 Baron SSO 화면과 유사한 어두운 카드형 디자인을 사용한다.
|
||||
- 로그인 화면 상단 중앙에는 `TDC114PLUS` 타이틀을 명확하게 노출한다.
|
||||
- 전화번호 입력은 `010-0000-0000` 형식의 입력/표현을 기본으로 한다.
|
||||
- 안내 문구는 짧고 명확하게 유지한다.
|
||||
- 로그인 화면 본문에서는 `입력하신 전화번호로 바론SSO 로그인 링크가 발송됩니다.` 문구를 중복 노출하지 않는다.
|
||||
- 로그인 화면은 문자 승인 후 앱으로 돌아오면 자동 로그인된다는 흐름을 우선 안내한다.
|
||||
- 전화번호 입력 중 키보드가 열려도 `로그인 링크 보내기` 버튼은 사용자가 바로 누를 수 있도록 화면에 계속 노출한다.
|
||||
- 앱은 링크 발송 후 pending 상태를 유지하며 poll로 승인 완료를 확인한다.
|
||||
- Baron SSO 공식 정책상 `/api/v1/auth/headless/link/init`은 승인 완료 후 redirect URL 필드를 지원하지 않는다.
|
||||
- Baron SSO 공식 정책상 문자 링크를 클릭한 모바일 브라우저는 verify-only approver로 동작하며, 승인 완료 후 `sso.hmac.kr/ko/verify-cc` 또는 승인 완료 화면에 머무른다.
|
||||
- 따라서 앱 화면은 `문자 링크 승인 후 TDC114PLUS 앱으로 돌아오면 자동 로그인됩니다` 흐름을 명확히 안내한다.
|
||||
- 사용자가 앱으로 돌아오면 앱은 저장된 pendingRef로 poll을 재개하고, 승인 완료가 확인되면 직원검색 화면으로 자동 이동해야 한다.
|
||||
- 사용자가 문자 링크를 클릭했을 때 앱이 바로 열리려면 Baron SSO 승인 완료 페이지가 앱 링크 또는 callback URL로 redirect하는 별도 정책/기능을 추가해야 한다.
|
||||
- Baron SSO가 `sso.hmac.kr/ko/verify-cc` 승인 완료 화면에 머무르는 경우, 앱 단독 코드만으로 Chrome을 자동으로 앱으로 전환할 수 없음을 정책상 명확히 둔다.
|
||||
- OIDC PKCE Hosted Login은 현재 기본 운영 UX가 아니며, 다시 적용하려면 별도 정책 변경 승인이 필요하다.
|
||||
- 로그인 실패 메시지는 사용자 존재 여부를 과도하게 노출하지 않는다.
|
||||
|
||||
## 4. 직원검색 화면 정책
|
||||
|
||||
대상:
|
||||
|
||||
- `직원검색`
|
||||
- 상단 조직 칩
|
||||
- 직원/조직도/즐겨찾기 segment
|
||||
|
||||
### 4.1 초기 기본값
|
||||
|
||||
- 초기 조회 범위는 로그인 사용자의 `회사급 tenantSlug`
|
||||
- 단, 초기 선택 상태는 가능하면 로그인 사용자의 `본인 팀 뱃지`가 실제 선택되도록 맞춘다.
|
||||
- 초기 화면은 직원 목록 중심으로 시작
|
||||
- 앱 최초 진입 시에는 조직 단계 표현에 필요한 상위 조직/내 팀 정보를 먼저 확보한다.
|
||||
- 최초 직원 목록은 가족사 전체가 아니라 `내 팀` 또는 현재 초기 선택 scope에 필요한 인원만 조회한다.
|
||||
- 초기 진입 또는 상단 뱃지 선택 시 직원 조회가 가족사 전체 조회로 새지 않도록 한다.
|
||||
- 하위 조직을 표시해야 하는 단계에서는 기본 직원 목록 조회를 실행하지 않는다. 단, 선택 조직의 직접 소속 인원을 `직접 소속` 구역에 표시하기 위한 제한 조회는 허용한다.
|
||||
- 자식 조직이 없는 leaf 조직 또는 검색 결과 표시가 필요한 상태에서만 직원 목록을 조회한다.
|
||||
- 초기 진입 직후 phone/name 재조회로 개인 1명 또는 하위 팀 1개로 자동 축소하지 않음
|
||||
- 초기 상단 칩에는 로그인 사용자의 `본인 팀 뱃지`를 함께 고정 노출한다.
|
||||
- 본인 팀 뱃지는 세션의 `department`와 tenant 계층의 조직명을 우선 매칭해 결정한다.
|
||||
- tenant 계층에 본인 팀 노드가 없더라도, 세션의 `department` 문자열로 본인 팀 뱃지를 synthetic chip 형태로 유지한다.
|
||||
|
||||
### 4.2 상단 칩 규칙
|
||||
|
||||
- 본인 소속 팀 칩이 있으면 상단 칩의 가장 앞에 노출한다.
|
||||
- 항상 `전체` 칩이 존재한다.
|
||||
- `전체` 칩은 본인팀 칩 다음 순서에 노출한다.
|
||||
- 회사급 칩은 항상 노출한다.
|
||||
- 본인 소속 팀 칩은 빠른 재선택용으로 유지한다.
|
||||
- 다른 회사 칩을 선택한 뒤에도 본인 팀 칩은 사라지지 않는다.
|
||||
- 현재 선택된 하위조직은 칩에서 사라지지 않아야 한다.
|
||||
- 현재 선택된 칩은 비선택 칩보다 더 강한 배경색과 외곽 표현으로 즉시 구분 가능해야 한다.
|
||||
- 상단 칩 수가 화면 폭을 넘으면 가로 스크롤로 계속 탐색 가능해야 한다.
|
||||
- 상단 칩 overflow는 줄바꿈보다 `한 줄 가로 스크롤 + 스크롤 가능 인지성`을 우선한다.
|
||||
|
||||
### 4.3 `<전체>` 클릭 규칙
|
||||
|
||||
`<전체>`를 클릭하면 단계형 조직 탐색 모드로 전환한다.
|
||||
|
||||
진행 규칙:
|
||||
|
||||
1. `전체` 선택
|
||||
- 가족사/회사 목록 표시
|
||||
2. 회사 선택
|
||||
- 해당 회사의 바로 아래 하위조직 목록 표시
|
||||
3. 하위조직 선택
|
||||
- 자식 조직이 있으면 그 다음 하위조직 목록 표시
|
||||
- 자식 조직이 없으면 해당 조직 소속 직원 목록 표시
|
||||
- leaf 조직이면 해당 조직 소속 직원 목록으로 진입
|
||||
4. breadcrumb
|
||||
- `전체 > 회사 > 하위조직` 경로를 클릭 가능하게 유지
|
||||
|
||||
즉, 상단 칩은 단순 필터가 아니라 조직 탐색 진입점 역할을 겸한다.
|
||||
|
||||
추가 표현 규칙:
|
||||
|
||||
- 상단 회사/고정팀 칩 영역과 하위 경로 칩 영역 사이에는 시각적 구분선을 둔다.
|
||||
- breadcrumb 영역과 segment 사이의 구분 표식은 선 중심으로 단순하게 유지하고, 중앙 강조 아이콘은 기본 표현으로 두지 않는다.
|
||||
- breadcrumb에서 현재 선택 중인 하위조직 칩은 비선택 칩보다 더 눈에 띄는 아이콘과 색으로 구분한다.
|
||||
- leaf 조직 선택 후 직원 목록 진입은 조직명 문자열 비교보다 `선택 tenantSlug` 기준 조회를 우선한다.
|
||||
- 하위조직 카드의 인원 수는 API 원문의 `memberCount`만 그대로 쓰지 않고, 해당 하위조직 자신과 모든 descendant 조직에 소속된 인원을 합산한 `subtree 인원 수`로 표시한다.
|
||||
- 선택한 조직 아래에 자식 조직이 하나라도 있으면 하위조직 목록을 우선 표시한다.
|
||||
- 선택한 조직에 직접 소속 인원이 있으면 하위조직 목록과 섞지 않고 별도 구역으로 표시한다.
|
||||
- 직접 소속 별도 구역의 제목은 사용자가 현재 선택한 조직을 알 수 있도록 `{선택 조직명} 조직 관리자` 형식으로 표시한다.
|
||||
- 직접 소속 별도 구역은 하위조직 목록보다 위에 표시한다.
|
||||
- `디비전장`, `센터장` 등 상위 조직에 직접 매핑되고 하위 팀/부서 소속값이 비어 있는 인원은 `직접 소속` 구역에서 누락 없이 노출한다.
|
||||
- 자식 조직이 없는 leaf 조직에 도달했을 때만 해당 조직에 직접 소속된 직원 목록을 표시한다.
|
||||
- 하위조직 목록을 표시하는 동안에는 하위조직 전체 직원 목록을 섞어 표시하지 않는다. 단, 선택 조직에 직접 매핑된 인원 확인을 위한 제한 조회는 허용한다.
|
||||
- leaf 조직의 직접 소속 인원이 0명이면 `검색 결과 없음` 표시가 가능하다. 단, 이 경우 실제 Baron SSO 조직 데이터상 해당 leaf에 members가 없는지 확인해야 한다.
|
||||
- 다만 실제 API가 하위 tenant subtree를 제공하지 않는 구간에서는, 회사 하위 상세 트리는 완전 복원하지 못할 수 있으며 이 경우 본인 팀 synthetic chip과 회사 단위 직원 목록을 fallback으로 유지한다.
|
||||
|
||||
### 4.4 검색어 입력 규칙
|
||||
|
||||
- 검색어가 비어 있으면 조직 탐색 규칙을 우선 적용한다.
|
||||
- 검색 범위는 항상 현재 선택된 상단 뱃지 scope를 기준으로 한다.
|
||||
- 검색어가 있으면 현재 선택된 scope 안에서 직원 검색 결과를 우선 표시한다.
|
||||
- 검색 중에는 drilldown 목록보다 검색 결과가 우선이다.
|
||||
- 직원검색 입력창은 한글 IME 조합 입력을 막지 않는 일반 텍스트 입력으로 유지한다.
|
||||
- 가족사 전인원 고정 검색은 기본 정책으로 사용하지 않는다.
|
||||
- 한글 이름 검색은 한글 1자 이상 입력 시 조회 가능하다.
|
||||
- 전화번호 검색은 숫자만 추출했을 때, 앞자리 `010`을 제외한 나머지가 2자리 이상일 때 조회 가능하다.
|
||||
- 최소 입력 조건에 미달하면 조회 요청을 보내지 않고 현재 scope 기본 목록 또는 drilldown 상태를 유지한다.
|
||||
- 최소 입력 조건 안내 문구를 사용자에게 짧게 노출할 수 있다.
|
||||
|
||||
### 4.5 즐겨찾기 규칙
|
||||
|
||||
- `즐겨찾기` 뷰는 조직 drilldown보다 즐겨찾기 결과 표시를 우선한다.
|
||||
- 현재 선택된 scope 안에서 즐겨찾기를 필터링할 수 있다.
|
||||
- 즐겨찾기 추가/해제는 직원 상세/목록 어느 쪽에서도 동일하게 동작해야 한다.
|
||||
|
||||
### 4.6 조직도 인원 정렬 규칙
|
||||
|
||||
- 조직도 그룹 내부 인원 정렬은 단순 API 수신 순서에 의존하지 않는다.
|
||||
- 같은 조직/부서 내부에서는 `isManager == true` 인원을 최우선으로 노출한다.
|
||||
- `isManager` 값이 없거나 false인 경우에 한해 `position`에 `팀장`이 포함된 인원을 보조적으로 장으로 판단할 수 있다.
|
||||
- 그 다음 순서는 직급/직위 우선순위를 반영한다.
|
||||
- 기본 우선순위는 `사장 > 부사장 > 수석(연구원) > 전무 > 상무 > 이사 > 책임(연구원) > 부장 > 선임(연구원) > 과장 > 대리 > 사원`으로 본다.
|
||||
- 위 기준이 같은 경우 마지막은 이름 가나다순으로 정렬한다.
|
||||
- `미지정` 부서 그룹이 있더라도 동일한 인원 정렬 규칙을 적용한다.
|
||||
|
||||
### 4.7 직원 리스트 스크롤 규칙
|
||||
|
||||
- 검색창, 상단 뱃지, breadcrumb, segment 영역은 결과 인원 증가 때문에 함께 밀려 올라가면 안 된다.
|
||||
- 하단 직원/조직 결과 영역만 독립적으로 세로 스크롤되어야 한다.
|
||||
- 직원 리스트는 `Expanded` 영역 안의 `ListView` 계열로 구성한다.
|
||||
- 인원이 많아도 상단 검색/뱃지/조직 탐색 영역은 같은 화면 안에서 유지되어야 한다.
|
||||
|
||||
## 5. 조직도 화면 정책
|
||||
|
||||
대상:
|
||||
|
||||
- `조직도` segment
|
||||
|
||||
규칙:
|
||||
|
||||
- 조직 drilldown 중 자식 조직이 있으면 하위조직 목록을 우선 보여준다.
|
||||
- 하위조직 목록의 각 카드에는 해당 하위조직 subtree 기준 인원 수를 표시한다.
|
||||
- leaf 조직에 도달하면 해당 leaf 조직에 직접 소속된 직원 목록/조직도 그룹 표시를 보여준다.
|
||||
- 비-leaf 조직에 직접 소속된 인원이 있으면 하위조직 목록과 직원 목록을 한 화면에 섞지 않고 `직접 소속` 가상 그룹으로 구분해 표시한다.
|
||||
- 조직도 화면은 직원검색 화면의 tenant navigation 상태를 공유한다.
|
||||
- breadcrumb 영역과 직원/조직도/즐겨찾기 segment 사이에는 위아래 영역을 구분하는 시각 표식을 둔다.
|
||||
|
||||
## 6. 직원 상세 기능 정책
|
||||
|
||||
대상:
|
||||
|
||||
- bottom sheet 상세
|
||||
- 전화/문자 버튼
|
||||
|
||||
규칙:
|
||||
|
||||
- 프로필 사진 URL이 있으면 직원 프로필 앞에 사진을 우선 노출한다.
|
||||
- 프로필 사진 URL이 없으면 이니셜 또는 기본 아바타 fallback을 사용한다.
|
||||
- 사번 기반 이미지 네이밍으로 사진을 연결하려면 직원 DTO에 사번 또는 사번으로 역매핑 가능한 안정 식별자가 있어야 한다.
|
||||
- 이메일만으로 사번 이미지를 역매핑하는 방식은 별도 매핑 테이블이나 명명 규칙이 확정되기 전까지 기본 정책으로 채택하지 않는다.
|
||||
- 전화번호가 없으면 전화/문자 버튼은 비활성화한다.
|
||||
- 직원 상세는 tenantName, department, 직급/직위, 직무를 우선 노출한다.
|
||||
- 즐겨찾기 토글은 상세에서도 가능해야 한다.
|
||||
|
||||
## 7. 구현 시 금지사항
|
||||
|
||||
- APK 직접 설치만으로 기능 검증이 끝났다고 판단하지 않는다.
|
||||
- 조직 탐색 정책과 초기 조회 범위를 같은 규칙으로 섞지 않는다.
|
||||
- 본인 확인 로직 때문에 초기 scope를 개인 1명으로 자동 축소하지 않는다.
|
||||
- 하위조직 칩 또는 본인팀 칩이 선택 전후로 사라지도록 두지 않는다.
|
||||
- 다른 회사를 눌렀다는 이유만으로 본인팀 뱃지를 제거하지 않는다.
|
||||
- 회사/팀 뱃지 선택 시 가족사 전체 직원 목록을 먼저 가져온 뒤 앱에서만 필터링하는 방식을 기본 구현으로 사용하지 않는다.
|
||||
- 하위조직 목록을 보여주는 단계에서 직원 목록 조회를 동시에 실행하지 않는다.
|
||||
|
||||
## 8. 변경 시 필수 검증
|
||||
|
||||
최소 검증:
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh test test/widget_test.dart test/directory/directory_filters_test.dart
|
||||
```
|
||||
|
||||
변경 후 확인할 항목:
|
||||
|
||||
- 로그인 후 기본 범위가 회사급인지
|
||||
- 로그인 후 본인팀 칩이 기본 노출되는지
|
||||
- `<전체>` 클릭 시 가족사 목록으로 들어가는지
|
||||
- 회사 선택 후 하위조직 목록이 나오는지
|
||||
- leaf 조직 선택 후 직원 목록이 나오는지
|
||||
- 하위조직 카드의 인원 수가 해당 하위조직 subtree 기준으로 합산되는지
|
||||
- 자식 조직이 있는 비-leaf 조직에서는 직원 목록보다 하위조직 목록이 우선 표시되는지
|
||||
- leaf 조직의 직접 소속 인원이 0명일 때만 `검색 결과 없음`이 표시되는지
|
||||
- 본인팀 칩/선택 조직 칩이 사라지지 않는지
|
||||
- 선택된 칩이 비선택 칩보다 명확히 구분되는지
|
||||
- 현재 선택된 breadcrumb 칩이 아이콘과 색으로 명확히 구분되는지
|
||||
- 칩이 많을 때 가로 스크롤로 끝까지 탐색 가능한지
|
||||
- 이름 1자 검색과 전화번호 `010 제외 2자리` 검색 규칙이 맞는지
|
||||
- 최소 입력 미달 시 조회를 남발하지 않고 현재 scope가 유지되는지
|
||||
- 조직도 그룹 내에서 팀장/직급/이름 순 정렬이 맞는지
|
||||
- 직원 목록이 많을 때 하단 결과 영역만 스크롤되는지
|
||||
- 하위조직 목록 표시 중 하위조직 전체 직원 목록이 섞여 나오지 않는지
|
||||
- 상위 조직 직접 소속 인원이 있으면 `직접 소속` 구역에 누락 없이 표시되는지
|
||||
- 회사/팀 뱃지 선택 시 가족사 전체 직원 조회로 새지 않는지
|
||||
- 정렬 기준이 `isManager -> 직급표 -> 이름` 순서와 일치하는지
|
||||
@@ -0,0 +1,194 @@
|
||||
# tdc114plus 테스트 정책
|
||||
|
||||
작성일: 2026-07-02
|
||||
최종 개정일: 2026-07-09
|
||||
상태: v2.1
|
||||
|
||||
목적: `tdc114plus` Flutter 앱의 mock 기반 개발, Swagger 계약 검증, 실제 API 연동 검증 기준을 단계별로 정의한다.
|
||||
|
||||
상위 기준 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
- `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
|
||||
## 1. 적용 범위
|
||||
|
||||
본 정책은 아래 영역에 적용한다.
|
||||
|
||||
- Flutter 앱 화면, 라우팅, 상태관리
|
||||
- API client, repository, provider
|
||||
- API 계약 기반 model, DTO, JSON 변환
|
||||
- Baron SSO Hosted Login + PKCE 시작/callback/token 교환 흐름
|
||||
- 직원검색, 조직도, 직원 상세
|
||||
- 즐겨찾기 로컬 저장
|
||||
- 전화걸기, 문자보내기 등 플랫폼 액션
|
||||
|
||||
## 2. 기본 검증 게이트
|
||||
|
||||
Flutter 앱 코드를 변경한 모든 작업은 아래 검증을 통과해야 한다.
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh analyze
|
||||
./scripts/flutter-docker.sh test
|
||||
```
|
||||
|
||||
필요 시 formatter를 적용한다.
|
||||
|
||||
```bash
|
||||
./scripts/format-dart.sh
|
||||
```
|
||||
|
||||
검증 실패 상태의 코드는 `main` 브랜치에 반영하지 않는다.
|
||||
|
||||
## 3. 테스트 레이어
|
||||
|
||||
### 3.1 Mock 레이어
|
||||
|
||||
목적:
|
||||
|
||||
- 백엔드 미구현 상태에서도 화면과 상태 흐름을 개발 가능하게 유지한다.
|
||||
|
||||
대상:
|
||||
|
||||
- widget test
|
||||
- fake/mock repository
|
||||
- local mock data
|
||||
|
||||
핵심 검증:
|
||||
|
||||
- 로그인 화면 표시
|
||||
- Baron SSO 로그인 시작 버튼 렌더링
|
||||
- 앱 내부에서 휴대폰번호를 직접 입력받지 않는지 확인
|
||||
- callback token 교환 완료 후 첫 화면 진입
|
||||
- 직원검색, 조직 탐색, 즐겨찾기, 상세 화면 흐름
|
||||
|
||||
### 3.2 계약 레이어
|
||||
|
||||
목적:
|
||||
|
||||
- Swagger 기준 request/response DTO와 앱 모델 간 불일치를 조기에 찾는다.
|
||||
|
||||
대상:
|
||||
|
||||
- `fromJson`, `toJson`
|
||||
- API error parsing
|
||||
- request body 생성
|
||||
- polling 상태값 파싱
|
||||
|
||||
핵심 검증:
|
||||
|
||||
- OIDC authorization URL query 생성
|
||||
- PKCE `state`, `nonce`, `code_verifier` 저장/검증
|
||||
- token endpoint 응답 DTO
|
||||
- 세션 저장 모델
|
||||
- directory/organization DTO
|
||||
- 400/401/403/429/timeout 처리
|
||||
|
||||
### 3.3 실제 API 레이어
|
||||
|
||||
목적:
|
||||
|
||||
- mock 구조가 실제 API와 동일한 사용자 흐름을 유지하는지 확인한다.
|
||||
|
||||
대상:
|
||||
|
||||
- smoke test
|
||||
- integration test
|
||||
- staging 또는 동등 환경 점검
|
||||
|
||||
핵심 검증:
|
||||
|
||||
- Hosted Login authorization endpoint 진입
|
||||
- App Link callback 수신
|
||||
- PKCE token 교환 후 세션 저장
|
||||
- 로그인 후 직원검색 첫 화면 진입
|
||||
- directory/organization 실제 응답 정합성
|
||||
|
||||
## 4. 우선 테스트 대상
|
||||
|
||||
강한 단위 테스트가 필요한 영역:
|
||||
|
||||
- API model `fromJson`, `toJson`
|
||||
- API error parsing
|
||||
- authorization URL 생성 규칙
|
||||
- 로그인 상태 전이
|
||||
- `state`, `nonce`, `code_verifier` 처리
|
||||
- 세션 저장/삭제/복원
|
||||
- 직원검색 query/filter 생성
|
||||
- 가족사/조직 필터 상태
|
||||
- 즐겨찾기 추가/삭제/조회
|
||||
- API 실패, 401, 403, 429, timeout 처리
|
||||
|
||||
화면 테스트가 필요한 영역:
|
||||
|
||||
- 앱 실행 후 로그인 화면 표시
|
||||
- 앱 내부 전화번호 입력창 미노출
|
||||
- callback 처리 완료 후 직원검색 진입
|
||||
- 직원 검색어 입력과 결과 표시
|
||||
- 가족사 필터 선택/해제
|
||||
- 조직도 탐색
|
||||
- 직원 상세 표시
|
||||
- 전화걸기/문자보내기 액션 노출
|
||||
- 즐겨찾기 토글
|
||||
|
||||
## 5. 단계별 테스트 전략
|
||||
|
||||
### 5.1 Phase A: Mock 우선 개발
|
||||
|
||||
목표:
|
||||
|
||||
- API 없이도 앱의 핵심 화면 흐름을 검증한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- `flutter analyze` 통과
|
||||
- `flutter test` 통과
|
||||
- mock repository 기반 주요 widget test 존재
|
||||
|
||||
### 5.2 Phase B: 계약 정합성 검증
|
||||
|
||||
목표:
|
||||
|
||||
- Swagger 기준 DTO와 앱 모델의 구조를 맞춘다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- DTO 파싱/직렬화 테스트 통과
|
||||
- 에러 응답 테스트 통과
|
||||
- 로그인 흐름 상태값 테스트 통과
|
||||
|
||||
### 5.3 Phase C: 실제 API 연동
|
||||
|
||||
목표:
|
||||
|
||||
- Hosted Login + PKCE 흐름이 실제 Baron SSO RP 설정과 맞물리는지 확인한다.
|
||||
|
||||
실행 원칙:
|
||||
|
||||
- 실제 API smoke는 환경 준비 확인 후 실행한다.
|
||||
- local, staging, 기타 검증 환경 중 어떤 환경을 쓰더라도 동일한 계약 기준을 적용한다.
|
||||
- 실제 검증은 `authorization URL 열기 -> Baron SSO Hosted Login에서 인증 -> App Link callback -> state 검증 -> token 교환 -> 세션 저장 -> 첫 화면 진입` 흐름 완료를 기준으로 본다.
|
||||
- `phone-login`, `link/poll`은 개발용 fallback 또는 Baron SSO 내부 구현 참고일 뿐, 신규 앱 기본 로그인 검증 완료로 간주하지 않는다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- authorization URL query 확인
|
||||
- callback 수신과 state 검증 확인
|
||||
- token 교환 후 세션 저장 확인
|
||||
- 로그인 후 첫 화면 진입 확인
|
||||
- directory/organization 응답 필드 정합성 확인
|
||||
|
||||
## 6. 수동 검증 원칙
|
||||
|
||||
- Android target 검증은 mock 검증과 별도로 본다.
|
||||
- 로그인 완료 가정 세션 주입 경로는 post-login 기능 점검용으로만 사용한다.
|
||||
- 실제 승인 완료 검증을 세션 bootstrap 경로로 대체하지 않는다.
|
||||
- staging 반영 검토 전에는 승인 완료 end-to-end를 최소 1회 이상 확인하는 것을 목표로 한다.
|
||||
|
||||
## 7. 문서 및 로그 반영 원칙
|
||||
|
||||
- 테스트 기준이 바뀌면 정책 문서를 먼저 갱신한다.
|
||||
- 중요한 실행 결과는 `docs/test-logs/`에 기록한다.
|
||||
- 실패 시에는 원인, 재현 조건, 후속 조치를 함께 남긴다.
|
||||
- mock 기준 통과와 real API 기준 통과를 구분해서 기록한다.
|
||||
@@ -0,0 +1,91 @@
|
||||
# 공기계 USB 테스트 시작 체크리스트
|
||||
|
||||
작성일: 2026-07-09
|
||||
상태: v1.0
|
||||
|
||||
목적: `tdc114plus` 신규앱을 공기계 USB 연결 기준으로 빠르게 기동하고 테스트를 시작하기 위한 최소 절차를 고정한다.
|
||||
|
||||
## 1. 전제
|
||||
|
||||
- 오늘 기본 테스트 대상은 `공기계 1대`다.
|
||||
- Android Studio는 필수가 아니다.
|
||||
- 기본 연결 방식은 `Windows ADB server 공유 + WSL/Docker Flutter`다.
|
||||
|
||||
## 2. 시작 순서
|
||||
|
||||
1. Windows에서 `일반 PowerShell`을 연다.
|
||||
2. WSL에서 `VS Code`와 `tdc114plus` 워크스페이스를 연다.
|
||||
3. 공기계를 USB로 연결한다.
|
||||
4. 공기계에서 `USB 디버깅 허용` 팝업이 뜨면 허용한다.
|
||||
5. 공기계 USB 용도는 `파일 전송`으로 둔다.
|
||||
|
||||
## 3. Windows 확인
|
||||
|
||||
일반 PowerShell에서 실행:
|
||||
|
||||
```powershell
|
||||
& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" devices
|
||||
```
|
||||
|
||||
기대 결과:
|
||||
|
||||
- 공기계 1대가 `device`
|
||||
|
||||
문제 시:
|
||||
|
||||
- `unauthorized`: 폰 화면에서 허용
|
||||
- `offline`: 케이블 재연결, USB 모드 재확인, 다시 `adb devices`
|
||||
|
||||
## 4. WSL startup
|
||||
|
||||
WSL 터미널에서 실행:
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --dry-run --wait=40
|
||||
```
|
||||
|
||||
dry-run 이상 없으면 실제 실행:
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --auto --wait=40
|
||||
```
|
||||
|
||||
## 5. startup 통과 기준
|
||||
|
||||
- Android target preflight 통과
|
||||
- Baron runtime 기동 완료
|
||||
- `check-baron-api-env.sh` 통과
|
||||
- `api-smoke.sh` 통과
|
||||
|
||||
## 6. 공기계 로컬 개발모드 준비
|
||||
|
||||
Windows 일반 PowerShell에서 실행:
|
||||
|
||||
```powershell
|
||||
& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" -s <DEVICE_ID> reverse tcp:5000 tcp:5000
|
||||
```
|
||||
|
||||
`<DEVICE_ID>`는 `adb devices`에 표시된 공기계 ID를 사용한다.
|
||||
|
||||
## 7. 앱 실행
|
||||
|
||||
WSL 터미널에서 실행:
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 \
|
||||
TDC114_FLUTTER_DEVICE_ID=<DEVICE_ID> \
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
## 8. 오늘 테스트 시작점
|
||||
|
||||
앱이 공기계에 뜨면 아래부터 점검을 시작한다.
|
||||
|
||||
- 로그인 흐름
|
||||
- 직원검색
|
||||
- 조직도
|
||||
- 즐겨찾기
|
||||
- 전화/문자 버튼 노출
|
||||
@@ -0,0 +1,167 @@
|
||||
# 퇴근 전 기동 종료 및 정리 체크리스트
|
||||
|
||||
**작성일**: 2026-07-06
|
||||
**최종 업데이트**: 2026-07-08
|
||||
|
||||
## 목적
|
||||
|
||||
전날 퇴근하면서 VS Code, 터미널, Android target, Docker 컨테이너 등 개발에 사용한 런타임을
|
||||
안정적으로 종료하여 다음날 아침에 원활히 재기동할 수 있도록 준비한다.
|
||||
|
||||
**핵심 정책**: 소스코드 변경을 요하지 않는 종료/정리 작업(컨테이너 중지, 권한 수정, 로그 수집, 임시파일 정리 등)은 사용자 승인 없이 자동으로 실행한다.
|
||||
|
||||
---
|
||||
|
||||
## 적용 대상
|
||||
|
||||
- 작업 디렉터리: `/home/ubuntu/workspace/tdc114plus`
|
||||
- Baron SSO API worktree: `/home/ubuntu/workspace/baron-sso-tdc114plus-api`
|
||||
- Android target (실기기 우선, emulator fallback) + WSL/Docker 환경
|
||||
- 로컬 Docker 엔진
|
||||
|
||||
---
|
||||
|
||||
## 간단 체크리스트 (퇴근 5분 요약)
|
||||
|
||||
1. 모든 작업 저장 및 커밋(필요시).
|
||||
2. 통합 테스트/빌드가 실행 중이면 중지.
|
||||
3. Android target 정리 및 필요 시 ADB 연결 해제.
|
||||
4. Docker 앱/컨테이너 정상 종료(아래 상세 절차).
|
||||
5. 로그/임시파일 수집 및 정리.
|
||||
6. VS Code 종료.
|
||||
|
||||
---
|
||||
|
||||
## 상세 종료 절차 (권장 순서)
|
||||
|
||||
1) 열린 작업 저장
|
||||
|
||||
- 변경 중인 파일을 저장하고 로컬 커밋을 권장. 소스 변경은 수동 승인 항목이므로 자동 처리하지 않는다.
|
||||
|
||||
2) 실행 중인 테스트/빌드 종료
|
||||
|
||||
```bash
|
||||
# 통합/로컬 테스트나 빌드 프로세스가 있으면 종료
|
||||
# (예: integration_tests.sh 백그라운드 프로세스 종료)
|
||||
pkill -f /home/ubuntu/workspace/tdc114plus/scripts/integration_tests.sh || true
|
||||
pkill -f /home/ubuntu/workspace/tdc114plus/scripts/flutter-docker.sh || true
|
||||
```
|
||||
|
||||
3) Android target 정리
|
||||
|
||||
- 실기기 우선 운영이면 USB 연결만 정리하고, emulator fallback을 썼다면 Windows에서 에뮬레이터를 끈다.
|
||||
- 당일 `TDC114_ADB_CONNECT_ADDRESS`를 알고 있을 때만 WSL에서 연결을 끊는다.
|
||||
|
||||
```bash
|
||||
# WSL에서 ADB 연결 해제: 당일 실제 주소로만 실행
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:<EMULATOR_PORT> \
|
||||
adb disconnect 172.21.128.1:<EMULATOR_PORT> 2>/dev/null || true
|
||||
```
|
||||
|
||||
- 주소를 모르면 ADB disconnect는 생략한다. 과거 포트(`5555`, `5559` 등)를 임의로 disconnect하지 않는다.
|
||||
- 필요시 포트포워드/portproxy 정리(Windows 측에서 수행 필요)
|
||||
|
||||
4) 로그 수집
|
||||
|
||||
- compose 로그는 `down` 전에 수집한다. 종료 후에는 컨테이너 로그가 사라질 수 있다.
|
||||
|
||||
```bash
|
||||
# 로그 저장(날짜별)
|
||||
mkdir -p /home/ubuntu/workspace/tdc114plus/logs/$(date +%F)
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml logs --no-color > /home/ubuntu/workspace/tdc114plus/logs/$(date +%F)/baron-compose.log 2>&1 || true
|
||||
```
|
||||
|
||||
5) Docker 컨테이너 및 스택 안전하게 중지
|
||||
|
||||
- Baron SSO 및 app 관련 스택을 정상적으로 내린다 (데이터베이스 유지 여부는 상황에 따름).
|
||||
|
||||
```bash
|
||||
# 권장: 모든 관련 compose 파일을 포함해 정상 중지 (데이터 유지)
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml down
|
||||
|
||||
# tdc114plus 앱 스택이 별도라면 종료
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
# (예: 앱 관련 compose가 있다면) docker compose down
|
||||
```
|
||||
|
||||
- 모든 관련 컨테이너 완전 제거(옵션, 재기동 시 네임 충돌 방지)
|
||||
|
||||
```bash
|
||||
# 선택적(정리 필요 시 실행)
|
||||
docker ps -a --format '{{.Names}}' | grep -iE "baron|ory|tdc114" | xargs -r docker rm -f || true
|
||||
```
|
||||
|
||||
6) 임시파일 정리
|
||||
|
||||
```bash
|
||||
# 임시 파일 정리 (docker cache 등)
|
||||
# (유지해야 하는 캐시는 삭제하지 않도록 주의)
|
||||
```
|
||||
|
||||
7) 권한/생성된 파일 기본 정리 (자동)
|
||||
|
||||
```bash
|
||||
# config 디렉터리 권한이 root로 생긴 경우 사용자가 쓸 수 있게 복구
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
chmod -R u+w config/.generated/ 2>/dev/null || true
|
||||
chown -R $(id -u):$(id -g) config/.generated/ 2>/dev/null || true
|
||||
```
|
||||
|
||||
8) VS Code 및 터미널 종료
|
||||
|
||||
- VS Code: 모든 변경 저장 후 종료.
|
||||
- 터미널 세션: 열린 터미널을 종료.
|
||||
|
||||
---
|
||||
|
||||
## 자동화 규칙 요약
|
||||
|
||||
- 자동 실행(승인 불필요): 대상 helper 프로세스 종료, 로그 수집, 컨테이너 중지, 임시파일 정리, 권한 복구, ADB 연결 해제
|
||||
- 수동 승인 필요: 소스코드 커밋/푸시, 설정 파일 수정, 환경 변수 변경, DB 마이그레이션
|
||||
|
||||
---
|
||||
|
||||
## 스크립트 사용법: `scripts/shutdown.sh`
|
||||
|
||||
이 문서의 절차는 자동화 스크립트 `scripts/shutdown.sh`로 실행할 수 있습니다. 스크립트는 기본적으로 **안전 모드(dry-run)**로 동작하며, 실제 종료 작업과 선택적 파괴적 정리(컨테이너 강제 제거 등)는 `--auto` 옵션을 사용해야 수행됩니다.
|
||||
|
||||
간단한 사용 예시:
|
||||
|
||||
```bash
|
||||
# 문법 검사
|
||||
bash -n scripts/shutdown.sh
|
||||
|
||||
# Dry-run (권장): 실제로 파괴적 명령을 실행하지 않고 어떤 작업을 수행할지 확인합니다.
|
||||
./scripts/shutdown.sh --dry-run
|
||||
|
||||
# 실제 실행 (주의): --auto 플래그는 컨테이너 강제 제거 같은 파괴적 정리를 허용합니다.
|
||||
./scripts/shutdown.sh --auto
|
||||
```
|
||||
|
||||
스크립트는 실행 로그를 `/home/ubuntu/workspace/tdc114plus/logs/<YYYY-MM-DD>/shutdown.log`에 기록합니다. 자동화된 종료를 CI나 cron에 등록할 경우 `--auto`를 사용하되, 로그 보관 정책과 백업을 확인하십시오.
|
||||
|
||||
|
||||
## 체크아웃/확인 항목 (퇴근 직전)
|
||||
|
||||
- [ ] 작업 내용 저장/커밋(또는 스태시)
|
||||
- [ ] 대상 helper 프로세스 종료 확인
|
||||
- [ ] Android target 정리 및 필요 시 ADB 연결 해제
|
||||
- [ ] `docker compose down` 실행 완료
|
||||
- [ ] 주요 로그가 `/home/ubuntu/workspace/tdc114plus/logs/$(date +%F)`에 보관되었는지 확인
|
||||
- [ ] `config/.generated` 쓰기 권한이 정상인지 확인
|
||||
- [ ] VS Code 종료
|
||||
|
||||
---
|
||||
|
||||
## 복구 지침 요약 (다음날 재기동 관련)
|
||||
|
||||
- 다음날 아침에는 `docs/checklist_morning_startup_runtime_2026-07-03.md`를 따라 재기동한다.
|
||||
- 자동으로 중지된 항목(컨테이너 등)은 사용자의 승인 없이 재기동 스크립트가 처리한다.
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
- v1.0 (2026-07-06): 초기 작성
|
||||
@@ -0,0 +1,474 @@
|
||||
# 출근 후 기동 확인 및 복구 체크리스트
|
||||
|
||||
**작성일**: 2026-07-03
|
||||
**최종 업데이트**: 2026-07-19
|
||||
**버전**: 2.5 (개발용 로컬 Baron worktree와 최종 배포 목표 구조 구분 반영)
|
||||
|
||||
## 목적
|
||||
|
||||
전날 퇴근하면서 VS Code, 터미널, Android target을 모두 종료한 뒤, 다음 출근 시 `tdc114plus` 작업을 빠르게 재개할 수 있도록 기동 확인과 복구 절차를 고정한다.
|
||||
|
||||
**핵심 정책**: 소스코드 변경을 요하지 않는 자동 복구(컨테이너 재시작, 충돌 컨테이너 정리, 권한 수정, 디렉터리 정리 등)는 사용자 승인 없이 자동으로 진행한다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 적용 대상
|
||||
|
||||
- 앱 저장소: `/home/ubuntu/workspace/tdc114plus`
|
||||
- Baron SSO API worktree: `/home/ubuntu/workspace/baron-sso-tdc114plus-api`
|
||||
- auth 중계서버 저장소: `/home/ubuntu/workspace/tdc114plus-auth`
|
||||
- Windows ADB 서버 공유 기반 Android target + WSL/Docker Flutter 조합
|
||||
|
||||
주의:
|
||||
|
||||
- 이 체크리스트는 `현재 개발/검증용 업무시작 기동` 기준이다.
|
||||
- 최종 배포 목표 구조에서는 로컬 `baron-sso-tdc114plus-api` 기동이 없어지는 방향을 목표로 한다.
|
||||
- 다만 2026-07-19 현재는 아직 일부 로그인/조직 연동 검증이 로컬 Baron worktree에 의존하므로, 업무 시작 기동 대상에서 바로 제거하지 않는다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 출근 후 기본 순서
|
||||
|
||||
아래 순서를 기본값으로 사용한다.
|
||||
|
||||
1. VS Code를 연다.
|
||||
2. 작업 기준 문서를 먼저 연다.
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- `docs/daily-issues/YYYY-MM-DD.md`
|
||||
3. Android target 선행 확인
|
||||
4. Baron SSO runtime 초기화 (아래 섹션 참고)
|
||||
5. `tdc114plus-auth` broker 기동 및 health 확인
|
||||
6. 1차 상태 확인 명령 실행
|
||||
7. Integration test 실행
|
||||
|
||||
현재 해석:
|
||||
|
||||
- `tdc114plus`와 `tdc114plus-auth`는 최종 배포 직접 대상이다.
|
||||
- `baron-sso-tdc114plus-api`는 현재 개발 중 연동 검증용 보조 worktree다.
|
||||
- Baron SSO 원본 `staging`/`production` 연동으로 완전히 전환되기 전까지는 이 보조 worktree 기동 여부가 앱 개발 중 동작에 직접 영향을 줄 수 있다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 런타임 초기화 및 1차 확인
|
||||
|
||||
### 3.0 Android target 선행 확인
|
||||
|
||||
`startup.sh`는 이제 **가장 먼저** Android target 상태를 확인한다. 실기기 또는 emulator가 `offline`, `unauthorized`, `connection refused` 중 하나면 Baron runtime 기동 전에 멈추고, Windows에서 무엇을 해야 하는지 단계별로 출력한다.
|
||||
|
||||
기본 정책:
|
||||
|
||||
- 기본 타깃은 실기기 1대다. emulator는 fallback일 때만 1대만 켠다.
|
||||
- Windows `adb.exe devices`에서 대상 Android target이 `device` 상태인지 먼저 확인한다.
|
||||
- 표준 연결 방식은 Windows ADB server 공유 방식인 `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037`을 사용한다.
|
||||
- 직접 emulator port 연결인 `TDC114_ADB_CONNECT_ADDRESS=<host>:<port>`는 Docker local ADB가 꼭 필요한 예외 상황에만 사용한다.
|
||||
- Windows 단독 `device` 상태가 확인되기 전에는 WSL/Docker Android 스크립트를 실행하지 않는다.
|
||||
|
||||
권장 실행:
|
||||
|
||||
```bash
|
||||
# Android preflight + startup 계획 확인
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --dry-run --wait=40
|
||||
|
||||
# 실제 기동
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --auto --wait=40
|
||||
```
|
||||
|
||||
Android target preflight 실패 시 사용자가 로컬 PC에서 최소한으로 해야 하는 일:
|
||||
|
||||
1. Windows에서 Android Studio를 연다.
|
||||
2. 실기기면 USB 디버깅 연결을 확인하고, emulator fallback이면 Device Manager에서 1대만 켠다.
|
||||
3. Windows PowerShell에서 `adb.exe devices`를 실행해 `device` 상태를 확인한다.
|
||||
4. 여전히 `offline`이면 대상 기기 또는 emulator를 재시작한다.
|
||||
5. Windows adb는 정상인데 WSL/Docker에서만 실패하면 우선 `5037 -> 127.0.0.1:5037` portproxy와 방화벽 rule을 확인한다.
|
||||
6. `5037` 공유 방식은 정상인데 특정 integration test에서만 막히면 그때 `<EMULATOR_PORT> -> 127.0.0.1:<EMULATOR_PORT>` 직접 연결 보조 경로를 검토한다.
|
||||
|
||||
이 단계는 Codex가 대신 할 수 없다.
|
||||
|
||||
Codex가 계속할 수 있는 작업:
|
||||
|
||||
- WSL/Docker에서 Android target 재인식 확인
|
||||
- Baron runtime 기동
|
||||
- API smoke 확인
|
||||
- integration/manual Android 명령 실행
|
||||
- `tdc114plus-auth` broker 기동 확인 및 자동 실행 시도
|
||||
|
||||
### 3.05 앱 직접 App Link callback 제거
|
||||
|
||||
2026-07-15 기준 신규 앱은 Baron SSO OIDC callback을 직접 받지 않는다.
|
||||
|
||||
기본 정책:
|
||||
|
||||
- 앱은 `https://114.hmac.kr/auth/callback` App Link를 사용하지 않는다.
|
||||
- 앱은 `tdc114plus-auth`의 `/api/v1/auth/link/init`, `/api/v1/auth/link/poll`만 호출한다.
|
||||
- Baron SSO OIDC callback은 `tdc114plus-auth`가 받는다.
|
||||
- 필요한 redirect URI는 `https://114-auth.hmac.kr/api/v1/auth/oidc/callback`이다.
|
||||
- Windows 로컬 App Link 테스트 서버는 업무 시작 기동 대상이 아니다.
|
||||
|
||||
참조 문서:
|
||||
|
||||
```text
|
||||
docs/00_guide_tdc114plus_auth_broker_redirect_flow_2026-07-15.md
|
||||
```
|
||||
|
||||
### 3.1 Baron SSO 런타임 전체 초기화
|
||||
|
||||
**중요**: Baron SSO는 인프라(PostgreSQL, Redis, ClickHouse)와 Ory 인증(Kratos, Hydra, Keto) 서비스가 **모두 필수**다.
|
||||
|
||||
단순히 `docker compose up -d`로는 불충분하다. **반드시 모든 compose 파일을 포함**해야 한다:
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
|
||||
# 모든 compose 파일 포함하여 안전 중지 후 재시작
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml down 2>/dev/null || true
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
|
||||
# compose up 실패 시(예: name conflict) 기존 관련 컨테이너 정리 후 1회 재시도
|
||||
docker ps -a --format '{{.Names}}' | grep -iE "baron|ory" | xargs -r docker rm -f
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
|
||||
# 서비스 안정화 대기 (인지 마이그레이션/헬스체크 완료)
|
||||
sleep 30
|
||||
|
||||
# tdc114plus로 돌아가기
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
```
|
||||
|
||||
### 3.2 1차 상태 확인 명령
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
|
||||
# Baron runtime 상태 확인 (스크립트로 자동 실행 가능)
|
||||
./scripts/check-baron-api-env.sh
|
||||
|
||||
# API smoke 테스트 (스크립트로 자동 실행 가능)
|
||||
./scripts/api-smoke.sh
|
||||
```
|
||||
|
||||
**실행 방법 (권장)**:
|
||||
- 수동: 위 명령을 복사해 실행
|
||||
- 자동(권장): `scripts/startup.sh`를 사용
|
||||
|
||||
**자동 실행 예 (dry-run 권장)**:
|
||||
```bash
|
||||
# Dry-run: Android preflight 포함, 어떤 작업을 할지 미리 확인
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --dry-run
|
||||
|
||||
# 실제 재기동(주의)
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --auto --wait=40
|
||||
```
|
||||
|
||||
**기대 결과**:
|
||||
- `check-baron-api-env.sh`: `"RESULT ready-ish: 0 failure(s), 0 warning(s)"`
|
||||
- `api-smoke.sh`: 성공 코드 0
|
||||
- `tdc114plus-auth` health: `{"jwks":"ok","provider":"baron","status":"ok"}`
|
||||
- `scripts/startup.sh --auto`: Android preflight, Baron runtime, `tdc114plus-auth`, smoke 조건 중 하나라도 충족하지 못하면 비정상 종료(exit 1)
|
||||
|
||||
---
|
||||
|
||||
## 4. 자동 복구 정책 및 규칙
|
||||
|
||||
### 4.1 자동 복구 대상 (사용자 승인 불필요)
|
||||
|
||||
다음 사항들은 소스 변경을 요하지 않으므로 **자동으로 복구**한다:
|
||||
|
||||
- **컨테이너 미실행**: 자동 재시작 또는 전체 재기동
|
||||
- **컨테이너 명 충돌**: 기존 컨테이너 강제 제거 후 1회 재시작
|
||||
- **권한 문제**: `chmod`, `chown` 자동 수정
|
||||
- **설정 디렉터리 부재**: 자동 생성 또는 복원
|
||||
- **헬스체크 실패 또는 warning**: 최대 6회 재시도
|
||||
- **서비스 안정화 대기**: 자동 진행 (최대 60초)
|
||||
|
||||
### 4.2 수동 개입 필요 (사용자 승인 필요)
|
||||
|
||||
다음 사항들은 설정 또는 소스 변경을 요하므로 **명시적 승인**을 받는다:
|
||||
|
||||
- 소스코드 수정
|
||||
- 환경 변수 값 변경
|
||||
- 설정 파일 내용 수정
|
||||
- 데이터베이스 마이그레이션 또는 초기화
|
||||
- API 엔드포인트 주소 변경
|
||||
|
||||
---
|
||||
|
||||
## 5. 실패 시 복구 순서
|
||||
|
||||
### 5.1 `check-baron-api-env.sh` 실패 또는 warning 다수
|
||||
|
||||
Baron SSO runtime 상태 확인 및 복구:
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
```
|
||||
|
||||
**자동 복구 절차** (순차 실행):
|
||||
|
||||
```bash
|
||||
# 1단계: 안전 중지 후 전체 재시작
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml down 2>/dev/null || true
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
|
||||
# 2단계: name conflict가 보이면 관련 컨테이너 정리 후 1회 재시작
|
||||
docker ps -a --format '{{.Names}}' | grep -iE "baron|ory" | xargs -r docker rm -f
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
|
||||
# 3단계: 서비스 안정화 대기
|
||||
sleep 30
|
||||
|
||||
# 4단계: 재확인
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
./scripts/check-baron-api-env.sh
|
||||
```
|
||||
|
||||
**상태 확인 명령어**:
|
||||
|
||||
```bash
|
||||
docker ps --format '{{.Names}} {{.Status}}' | grep -E "baron_backend|baron_gateway|ory_kratos|ory_postgres"
|
||||
```
|
||||
|
||||
**정상 기대 상태**:
|
||||
|
||||
| 서비스 | 상태 | 설명 |
|
||||
|--------|------|------|
|
||||
| `baron_backend` | Up (healthy) | 메인 백엔드 서비스 |
|
||||
| `baron_gateway` | Up | 리버스 프록시 |
|
||||
| `baron_postgres` | Up (healthy) | 메인 데이터베이스 |
|
||||
| `baron_redis` | Up | 캐시/세션 저장소 |
|
||||
| `ory_postgres` | Up (healthy) | Ory 데이터베이스 |
|
||||
| `ory_kratos` | Up | 사용자 관리/인증 |
|
||||
| `ory_hydra` | Up | OAuth2/OIDC 제공자 |
|
||||
| `ory_keto` | Up | 권한 관리 |
|
||||
|
||||
---
|
||||
|
||||
### 5.2 `api-smoke.sh` 실패 (HTTP 502/503)
|
||||
|
||||
#### 원인 분석
|
||||
|
||||
```bash
|
||||
# Ory Kratos 로그 확인 (인증 서비스)
|
||||
docker logs ory_kratos 2>&1 | tail -30
|
||||
|
||||
# Baron backend 로그 확인
|
||||
docker logs baron_backend 2>&1 | tail -30
|
||||
|
||||
# 전체 컨테이너 상태
|
||||
docker ps | grep -iE "baron|ory"
|
||||
```
|
||||
|
||||
#### 자동 복구
|
||||
|
||||
Ory 또는 Baron 서비스가 준비 완료되지 않은 경우:
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
|
||||
# 전체 재시작 (가장 안전한 방법)
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml down
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
sleep 40
|
||||
|
||||
# 재확인
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
./scripts/api-smoke.sh
|
||||
```
|
||||
|
||||
#### HTTP 401 (인증 오류)
|
||||
|
||||
```bash
|
||||
cat /home/ubuntu/workspace/tdc114plus/scripts/.env.smoke.local | grep -E "PHONE|PROVIDER"
|
||||
```
|
||||
|
||||
전화번호, provider 설정이 올바른지 확인. 변경 필요시 사용자 승인 후 수정.
|
||||
|
||||
---
|
||||
|
||||
## 6. Android target 확인
|
||||
|
||||
`startup.sh`가 이 단계를 먼저 수행하지만, 수동 재확인이 필요하면 아래 명령을 쓴다.
|
||||
|
||||
실기기 우선이면 USB 디버깅 연결을 먼저 확인하고, emulator fallback이면 Windows에서 Android Studio emulator를 켠다.
|
||||
|
||||
그 후 WSL/Docker 기준 확인:
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices
|
||||
```
|
||||
|
||||
**완료 기준**:
|
||||
|
||||
- `emulator-<PORT>` 또는 Android target이 표시된다.
|
||||
- 직접 emulator port 연결은 표준 방식이 실패하거나 integration test 보조 경로가 필요할 때만 사용한다.
|
||||
|
||||
### 6.1 Android device가 보이지 않을 때
|
||||
|
||||
우선 정책 문서를 참고한다:
|
||||
|
||||
- `docs/policy_android_studio_wsl_adb_2026-07-03.md`
|
||||
- `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
|
||||
가장 흔한 확인 포인트:
|
||||
|
||||
- Windows emulator가 실제로 켜져 있는가?
|
||||
- Windows `adb.exe devices`에서 대상이 `device` 상태인가?
|
||||
- 당일 emulator port에 맞는 portproxy가 살아 있는가?
|
||||
- Docker local ADB가 `device` 상태를 보는가?
|
||||
|
||||
---
|
||||
|
||||
## 7. Android SDK license 관련
|
||||
|
||||
현재 `scripts/flutter-docker.sh`에는 Android SDK license 선행 승인 로직이 들어 있다.
|
||||
|
||||
다음과 같은 오류가 나면 먼저 cache 상태를 의심한다:
|
||||
|
||||
- `ndk;28.2.13676358` license not accepted
|
||||
- `CMake 3.22.1` license not accepted
|
||||
|
||||
**확인 경로**:
|
||||
|
||||
```bash
|
||||
ls -la /home/ubuntu/workspace/tdc114plus/.docker-cache/flutter/android-sdk/licenses/
|
||||
```
|
||||
|
||||
이 디렉터리들이 비어 있지 않으면 재사용되는 것이 정상이다.
|
||||
|
||||
---
|
||||
|
||||
## 8. 정상 기대 상태
|
||||
|
||||
정상 재개 기준:
|
||||
|
||||
- ✅ `./scripts/check-baron-api-env.sh` 통과 (0 failures, 0 warnings)
|
||||
- ✅ `./scripts/api-smoke.sh` 통과 (성공 코드 0)
|
||||
- ✅ Android emulator device 인식 성공
|
||||
- ✅ integration test 통과
|
||||
|
||||
**Integration test에서 확인할 실제 홈화면 기대값**:
|
||||
|
||||
로그인 후 홈화면에는 `문형석`의 조직 slug `is-3` 기준 팀 직원목록이 보여야 한다:
|
||||
|
||||
- `직원검색`
|
||||
- `검색 결과`
|
||||
- `문형석`
|
||||
- `IS3`
|
||||
|
||||
---
|
||||
|
||||
## 9. 다음 조치
|
||||
|
||||
위 순서 중 어느 단계에서 실패했는지 `docs/daily-issues/YYYY-MM-DD.md`에 남긴다.
|
||||
|
||||
기록할 최소 항목:
|
||||
|
||||
- 실패 단계 (예: 3.2, 5.1, 5.2 등)
|
||||
- 첫 번째 에러 메시지
|
||||
- 수행한 자동 복구 명령
|
||||
- 복구 성공 여부
|
||||
- 추가 수동 개입 필요 여부 및 사유
|
||||
|
||||
**기록 예시**:
|
||||
|
||||
```
|
||||
## 2026-07-06 출근 재기동
|
||||
|
||||
### 진행 상황
|
||||
- [x] 3.1 Baron SSO 초기화: 성공
|
||||
- [x] 3.2 상태 확인: 초기 실패 (baron_backend not running)
|
||||
- [x] 5.1 자동 복구: docker compose 재시작 → 성공
|
||||
- [x] 5.2 api-smoke 재확인: 통과
|
||||
- [ ] 6.0 Android emulator: 미진행 (시간 부족)
|
||||
|
||||
### 실패 내역
|
||||
- Initial check-baron-api-env.sh: WARN baron_backend not running
|
||||
- Resolved with: docker compose -f ... up -d
|
||||
- No source code changes needed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 부록: 명령 치트시트
|
||||
|
||||
### 빠른 전체 초기화 (추천)
|
||||
|
||||
```bash
|
||||
# 1. Baron SSO 전체 재시작 (권장)
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml down 2>/dev/null || true
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
sleep 30
|
||||
|
||||
# 2. tdc114plus 상태 확인
|
||||
cd /home/ubuntu/workspace/tdc114plus
|
||||
./scripts/check-baron-api-env.sh && ./scripts/api-smoke.sh
|
||||
```
|
||||
|
||||
### 컨테이너 상태 모니터링
|
||||
|
||||
```bash
|
||||
# 실시간 로그 보기
|
||||
docker logs -f baron_backend # 백엔드 로그
|
||||
docker logs -f ory_kratos # 인증 로그
|
||||
|
||||
# 모든 baron/ory 컨테이너 상태
|
||||
docker ps | grep -iE "baron|ory"
|
||||
|
||||
# 전체 상태 요약
|
||||
docker ps --format '{{.Names}} {{.Status}}'
|
||||
```
|
||||
|
||||
### 긴급 초기화 (최후의 수단)
|
||||
|
||||
```bash
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
|
||||
# 모든 관련 컨테이너 강제 제거
|
||||
docker ps -a --format '{{.Names}}' | grep -iE "baron|ory|sso" | xargs -r docker rm -f
|
||||
|
||||
# 전체 재시작
|
||||
docker compose -f docker-compose.yaml -f compose.infra.yaml -f compose.ory.yaml up -d
|
||||
|
||||
# 서비스 안정화 대기
|
||||
sleep 40
|
||||
|
||||
# 상태 확인
|
||||
docker ps | grep -iE "baron_backend|ory_kratos"
|
||||
```
|
||||
|
||||
### 일반적인 문제 해결
|
||||
|
||||
```bash
|
||||
# 권한 문제 수정 (config 디렉터리 쓰기 불가)
|
||||
cd /home/ubuntu/workspace/baron-sso-tdc114plus-api
|
||||
chmod -R u+w config/.generated/ 2>/dev/null || true
|
||||
|
||||
# Ory 마이그레이션 재시도
|
||||
docker compose -f docker-compose.yaml -f compose.ory.yaml up kratos-migrate
|
||||
|
||||
# 특정 컨테이너만 재시작
|
||||
docker restart baron_backend
|
||||
docker restart ory_kratos
|
||||
|
||||
# 로그 대량 확인
|
||||
docker logs baron_backend 2>&1 | grep -i error | tail -20
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
### v2.0 (2026-07-06)
|
||||
|
||||
- 자동 복구 정책 섹션 추가 (섹션 4)
|
||||
- Ory 포함 필수 명시 (섹션 3.1)
|
||||
- 컨테이너 정리 자동화 (섹션 5.1)
|
||||
- 안정화 대기 시간 추가 (30~40초)
|
||||
- 권한 문제 자동 처리 설명 추가
|
||||
- 명령 치트시트 부록 추가
|
||||
- 문제 기록 템플릿 추가 (섹션 9)
|
||||
|
||||
### v1.0 (2026-07-03)
|
||||
|
||||
초기 버전: 기본 기동 절차 및 복구 순서
|
||||
@@ -0,0 +1,161 @@
|
||||
# pre-staging 수동 점검 체크리스트
|
||||
|
||||
작성일: 2026-07-06
|
||||
상태: v0.2 현재 상태 반영
|
||||
|
||||
목적: `tdc114plus` 신규 전화번호 승인 로그인 기능을 staging 반영 전에 로컬 runtime, Android target, 문서 기준으로 점검할 항목을 고정한다.
|
||||
|
||||
## 1. 사용 시점
|
||||
|
||||
아래 상황에서 이 문서를 사용한다.
|
||||
|
||||
- 팀장에게 staging 반영 검토를 요청하기 전
|
||||
- Android target 기준 수동 점검을 다시 수행할 때
|
||||
- local runtime과 staging runtime의 차이를 설명해야 할 때
|
||||
|
||||
## 2. 진행 순서
|
||||
|
||||
아래 순서로 점검한다.
|
||||
|
||||
1. 로컬 구현 고정 상태 확인
|
||||
2. 자동화 테스트 재확인
|
||||
3. 로컬 API 계약 점검
|
||||
4. Android target UI 점검
|
||||
5. Android target 실사용 흐름 점검
|
||||
6. 예외 시나리오 점검
|
||||
7. staging 반영 직전 확인
|
||||
|
||||
## 3. 점검 항목
|
||||
|
||||
### 3.1 로컬 구현 고정 상태
|
||||
|
||||
- [x] 신규 로그인 흐름이 기존 원본 소스에 직접 덮어쓰지 않고 신규 API 경로 중심으로 분리되었는가
|
||||
- [x] 기존 직원검색, 조직도, 직원 상세, 즐겨찾기 흐름이 회귀하지 않았는가
|
||||
- [x] 변경 파일 목록과 영향 범위를 설명할 수 있는가
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 앱과 backend 모두 기존 `phone-login`을 직접 덮어쓰지 않고 headless 승인 계약 기준으로 재정렬하는 방식으로 진행했다.
|
||||
- 회귀 여부는 Flutter test, backend test, Android target 기준 직원검색 진입 확인으로 1차 검증했다.
|
||||
|
||||
### 3.2 자동화 테스트 재확인
|
||||
|
||||
- [x] Flutter unit test 통과
|
||||
- [x] Flutter widget test 통과
|
||||
- [x] backend handler/server test 통과
|
||||
- [x] `scripts/api-smoke.sh` 기본 검증 통과
|
||||
- [ ] Android integration test 재실행 결과 기록 완료
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 단위/위젯/backend/smoke 기준의 기본 자동화는 확보되었다.
|
||||
- Android integration test 재실행은 시도했고, 결과도 로그에 남겼다.
|
||||
- 다만 2026-07-06 재시도는 `172.21.128.1:5555 offline`으로 Android target 연결이 실패해 기능점검 통과로는 반영하지 못했다.
|
||||
|
||||
### 3.3 로컬 API 계약 점검
|
||||
|
||||
- [x] headless 로그인 시작/승인조회 계약 존재 확인
|
||||
- [x] 레거시 경로와 신규 계약의 차이 설명 가능
|
||||
- [x] invalid 요청 기준 validation 응답 확인
|
||||
- [x] 임의 `pendingRef` 기준 expired 또는 pending 응답 확인
|
||||
- [x] local runtime에서 실제 승인 완료 E2E가 막히는 원인을 설명할 수 있는가
|
||||
|
||||
설명 기준:
|
||||
|
||||
- local Baron SSO runtime 안에 테스트 번호의 identity/user mirror가 없으면, 번호가 운영 또는 다른 환경에 등록되어 있어도 local 승인 완료 검증은 끝까지 진행되지 않는다.
|
||||
|
||||
### 3.4 Android target UI 점검
|
||||
|
||||
- [x] 로그인 화면이 정상 표시되는가
|
||||
- [x] 빈 전화번호 validation이 동작하는가
|
||||
- [x] `Baron SSO로 로그인` 버튼이 Hosted Login 화면을 여는가
|
||||
- [ ] 인증 대기 중 문구가 자연스럽게 표시되는가
|
||||
- [ ] 로딩 상태가 과도하게 길거나 멈춘 것처럼 보이지 않는가
|
||||
- [ ] 오류 메시지가 내부 시스템 상세를 노출하지 않는가
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 로그인 화면, 입력, 버튼 동작 자체는 확인했다.
|
||||
- 승인 대기 중 문구와 장시간 polling 체감, generic 오류 문구는 현재 단계에서 다시 한 번 화면 기준 점검이 필요하다.
|
||||
|
||||
### 3.5 Android target 실사용 흐름 점검
|
||||
|
||||
- [x] 로그인 성공 후 `직원검색` 첫 화면으로 진입하는가
|
||||
- [x] `검색 결과`와 기본 직원 목록이 표시되는가
|
||||
- [x] 직원 상세 화면 진입이 되는가
|
||||
- [x] 즐겨찾기 저장이 되는가
|
||||
- [x] 전화/문자 버튼이 노출되는가
|
||||
- [ ] 앱 재실행 후 세션 복원이 되는가
|
||||
- [ ] 인증 만료 시 재로그인 유도 흐름으로 돌아가는가
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 로그인 이후 핵심 탐색 흐름은 1차 확인했다.
|
||||
- 세션 복원과 인증 만료 후 복귀 흐름은 실제 기기/에뮬레이터 기준으로 한 번 더 확인이 필요하다.
|
||||
|
||||
로그인 완료 가정 점검 절차:
|
||||
|
||||
1. 실기기 우선이면 `scripts/.env.android-device.local`, emulator fallback이면 `scripts/.env.android-emulator.local`에 API base와 테스트 번호가 준비되어 있는지 확인한다.
|
||||
2. 필요 시 `TDC114_SMOKE_ASSUME_LOGGED_IN=1`을 사용해 테스트용 세션 bootstrap을 활성화한다.
|
||||
3. `./scripts/integration_tests.sh`를 Android target 연결 상태에서 실행한다.
|
||||
4. 앱이 로그인 화면이 아니라 `직원검색`으로 바로 진입하는지 확인한다.
|
||||
5. 직원 목록, 즐겨찾기, 직원 상세, 전화/문자 버튼 노출까지 이어서 확인한다.
|
||||
|
||||
보조 메모:
|
||||
|
||||
- local runtime이 유효 세션을 내주지 못하면, 기능점검용으로 mock directory fallback을 사용한다.
|
||||
- 이 경우에도 점검 목적은 "로그인 이후 앱 기능 확인"이며, 실제 승인 완료 검증을 대체하지는 않는다.
|
||||
|
||||
2026-07-06 추가 메모:
|
||||
|
||||
- local Baron SSO runtime에 테스트 번호 `010-9136-5338`용 identity/local user를 맞춘 뒤 host 기준 `./scripts/api-smoke.sh`는 다시 통과했다.
|
||||
- 확인 완료:
|
||||
- `phone-login` HTTP 200
|
||||
- headless 로그인 시작 HTTP 200
|
||||
- `link/poll` 첫 응답 `authorization_pending`
|
||||
- 추가 완료:
|
||||
- Windows emulator `emulator-5556 device` 복구
|
||||
- Windows `5557 -> 127.0.0.1:5557` portproxy 추가
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5557 ./scripts/integration_tests.sh` 통과
|
||||
|
||||
### 3.6 예외 시나리오 점검
|
||||
|
||||
- [ ] 미등록 번호 입력 시 generic 실패 안내가 보이는가
|
||||
- [x] 만료된 `pendingRef`에서 poll 종료 처리가 자연스러운가
|
||||
- [ ] polling 간격이 짧을 때 제한 또는 지연 안내가 되는가
|
||||
- [ ] 로그인 성공 직후 directory API 401 없이 첫 화면이 유지되는가
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 만료 `pendingRef`에 대한 backend 응답 자체는 확인했다.
|
||||
- 다만 앱 화면에서 그 응답이 자연스럽게 보이는지, 미등록 번호와 polling 제한이 generic UX로 이어지는지는 아직 미완료다.
|
||||
|
||||
### 3.7 staging 반영 직전 확인
|
||||
|
||||
- [ ] 정확한 staging `TDC114_API_BASE`를 확보했는가
|
||||
- [ ] staging에 headless 로그인 API와 `link/poll` API가 실제 반영되었는가
|
||||
- [ ] 테스트 번호로 실제 링크 수신이 가능한가
|
||||
- [ ] staging 로그 확인 위치와 담당자를 알고 있는가
|
||||
- [x] 실패 시 롤백 또는 회귀 확인 방법을 문서화했는가
|
||||
|
||||
현재 판단:
|
||||
|
||||
- `https://sso.hmac.kr`는 현재 확인 기준으로 `tdc114plus` API base가 아니므로, 정확한 staging base는 아직 미확보다.
|
||||
- staging 반영 실패 시 local 회귀 확인과 반영 전 점검 순서는 문서화되었지만, 실제 staging 담당자/로그 위치 확인은 남아 있다.
|
||||
|
||||
## 4. 현재 상태 메모
|
||||
|
||||
2026-07-06 현재 기준 메모:
|
||||
|
||||
- 앱과 backend의 기본 구현은 상당 부분 완료되었다.
|
||||
- local runtime에서 API route와 기본 오류 응답은 확인했다.
|
||||
- Android target 기준 로그인 화면과 직원검색 진입, 목록/상세/즐겨찾기/전화문자 버튼 노출은 1차 확인했다.
|
||||
- local runtime에는 이제 테스트 번호 `010-9136-5338`의 identity/local user가 맞춰져 있어 최소 로그인 시작 단계 검증은 가능하다.
|
||||
- 다만 실제 승인 완료 E2E는 여전히 staging 또는 동등 환경 검증이 필요하다.
|
||||
|
||||
## 5. 결과 기록 위치
|
||||
|
||||
점검 결과는 아래 문서에 누적한다.
|
||||
|
||||
- `docs/test-logs/2026-07-test-execution-log.md`
|
||||
- 필요 시 `docs/daily-issues/YYYY-MM-DD.md`
|
||||
@@ -0,0 +1,68 @@
|
||||
# WSL 2주 점검 체크리스트
|
||||
|
||||
작성일: 2026-07-16
|
||||
|
||||
목적: `WSL ext4.vhdx` 비대화로 인한 리로드/재연결 문제를 줄이기 위해, 업무시작 시 2주마다 점검 알림을 띄운다.
|
||||
|
||||
## 기준
|
||||
|
||||
- 기준일: `2026-07-16`
|
||||
- 주기: 14일
|
||||
- 업무시작 진입점: `scripts/startup.sh`
|
||||
- 점검 스크립트: `scripts/check-wsl-maintenance.sh`
|
||||
|
||||
## 동작 방식
|
||||
|
||||
`startup.sh`는 기동 초반에 `scripts/check-wsl-maintenance.sh status`를 실행한다.
|
||||
|
||||
- 아직 기한이 아니면 다음 예정일과 남은 일수를 로그에 출력한다.
|
||||
- 14일이 지났으면 일반 PowerShell / 관리자 PowerShell 작업 순서를 로그에 출력한다.
|
||||
- 실제 점검을 마친 뒤에는 아래 명령으로 완료 날짜를 기록한다.
|
||||
|
||||
```bash
|
||||
./scripts/check-wsl-maintenance.sh record
|
||||
```
|
||||
|
||||
## 사용 명령
|
||||
|
||||
상태 확인:
|
||||
|
||||
```bash
|
||||
./scripts/check-wsl-maintenance.sh status
|
||||
```
|
||||
|
||||
오늘 완료 처리:
|
||||
|
||||
```bash
|
||||
./scripts/check-wsl-maintenance.sh record
|
||||
```
|
||||
|
||||
기록 초기화:
|
||||
|
||||
```bash
|
||||
./scripts/check-wsl-maintenance.sh reset
|
||||
```
|
||||
|
||||
## 실제 점검 절차
|
||||
|
||||
일반 PowerShell:
|
||||
|
||||
```powershell
|
||||
wsl --shutdown
|
||||
```
|
||||
|
||||
관리자 PowerShell:
|
||||
|
||||
```powershell
|
||||
diskpart
|
||||
```
|
||||
|
||||
`DISKPART>` 안에서:
|
||||
|
||||
```text
|
||||
select vdisk file="%LOCALAPPDATA%\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx"
|
||||
attach vdisk readonly
|
||||
compact vdisk
|
||||
detach vdisk
|
||||
exit
|
||||
```
|
||||
@@ -0,0 +1,73 @@
|
||||
# 2026-07-03 작업 이슈 및 처리내역
|
||||
|
||||
## 목적
|
||||
|
||||
당일 작업 중 실제로 확인한 이슈, 처리 내용, 검증 결과, 남은 후속 작업을 기록한다.
|
||||
|
||||
## 이슈 1. 외부 org-context 직원 필터의 회사 subtree 누락
|
||||
|
||||
- 현상:
|
||||
- `GET /api/v1/tdc114plus/directory/employees?tenantSlug=hanmac` 호출 시 최초에는 1명만 반환됐다.
|
||||
- 원인:
|
||||
- 외부 `org-context` 기준 `tenantSlug` 필터가 회사 하위 조직 subtree가 아니라 direct match 위주로 처리되고 있었다.
|
||||
- 처리:
|
||||
- Baron backend `tdc114plus_handler.go`에서 외부 직원 필터를 ancestor/subtree 기준으로 보정했다.
|
||||
- 관련 handler test를 추가/보강했다.
|
||||
- 검증:
|
||||
- backend rebuild 후 `tenantSlug=hanmac` 결과가 `total=339`로 증가한 것을 실제 API로 확인했다.
|
||||
- 후속:
|
||||
- 실제 앱 초기 범위와 체감 성능 기준으로 추가 정합성 확인이 남아 있다.
|
||||
|
||||
## 이슈 2. 초기 범위를 회사보다 더 좁은 조직 slug로 축소 필요
|
||||
|
||||
- 현상:
|
||||
- 일부 가족사는 직원 수가 1000명 이상일 수 있어 회사 단위 초기 조회도 무거울 수 있다.
|
||||
- 판단:
|
||||
- 조직도 예시의 `name`, `slug` 조합은 팀/부서 단위 조직 slug로 볼 수 있다.
|
||||
- 처리:
|
||||
- 앱에서 로그인 사용자 회사 범위 안에서 자기 전화번호/이름으로 본인을 다시 검색해 실제 조직 slug를 식별하도록 구현했다.
|
||||
- 검증:
|
||||
- 실제 smoke 로그인 사용자 `문형석 / +821091365338`는 `tenantSlug=hanmac` 범위 재검색 시 조직 slug `is-3`, 조직명 `IS3`으로 식별됐다.
|
||||
- `tenantSlug=is-3` 기준 실제 직원목록은 총 6명으로 확인됐다.
|
||||
- 후속:
|
||||
- 초기 조직 slug 식별 실패 시 회사 slug fallback이 계속 적절한지 추가 확인이 필요하다.
|
||||
|
||||
## 이슈 3. Android emulator integration test의 NDK/CMake license blocker
|
||||
|
||||
- 현상:
|
||||
- Android integration test 실행 시 `ndk;28.2.13676358` license 미승인으로 `assembleDebug`가 실패했다.
|
||||
- 처리:
|
||||
- `scripts/flutter-docker.sh`에 Android SDK license 선행 승인 로직을 추가했다.
|
||||
- Docker cache 아래 Android SDK `licenses`, `ndk`, `cmake` 디렉터리가 유지되도록 재사용 경로를 활용했다.
|
||||
- 검증:
|
||||
- 재실행 시 NDK/CMake license가 승인되고 실제 설치가 완료됐다.
|
||||
- 이후 Android emulator integration test가 끝까지 통과했다.
|
||||
- 후속:
|
||||
- 첫 Android 빌드 시간이 여전히 길어 추가 warm-up 또는 캐시 최적화 여지는 있다.
|
||||
|
||||
## 이슈 4. 홈화면 직원목록 실제 노출 검증
|
||||
|
||||
- 목표:
|
||||
- 전화번호 로그인 후 홈화면에 본인 팀 소속 직원목록이 실제로 표시되는지 확인한다.
|
||||
- 처리:
|
||||
- integration test에 실제 API 로그인 후 홈화면에서 `검색 결과`, `문형석`, `IS3` 노출을 확인하는 검증을 추가했다.
|
||||
- 검증:
|
||||
- Android emulator integration test에서 실제 API 로그인 후 `직원검색`, `검색 결과`, `문형석`, `IS3`가 노출되는 것을 확인했다.
|
||||
- 결과적으로 홈화면 직원목록 노출 목표를 당일 기준 달성했다.
|
||||
- 후속:
|
||||
- 조직도 탭 표현과 정렬/요약 표시의 세부 UX 검토는 다음 작업 후보로 남는다.
|
||||
|
||||
## 이슈 5. 다음 출근 시 기동 확인 및 복구 절차 필요
|
||||
|
||||
- 배경:
|
||||
- 퇴근 시 VS Code, 터미널, Android emulator를 모두 종료하면 다음 출근 시 어떤 순서로 기동 확인과 복구를 해야 하는지 빠르게 참고할 문서가 필요하다.
|
||||
- 처리:
|
||||
- `docs/checklist_morning_startup_runtime_2026-07-03.md` 문서를 추가했다.
|
||||
- 포함 내용:
|
||||
- Baron runtime 확인
|
||||
- API smoke 확인
|
||||
- Android emulator/device 인식 확인
|
||||
- integration test 실행
|
||||
- 실패 시 복구 순서
|
||||
- 후속:
|
||||
- 실제 다음 출근 시 이 문서로 재개하면서 부족한 부분이 있으면 보완한다.
|
||||
@@ -0,0 +1,193 @@
|
||||
# 2026-07-14 업무 인계 메모
|
||||
|
||||
작성 시각: 2026-07-14 16:54 KST
|
||||
|
||||
## 오늘 최종 상태
|
||||
|
||||
- 실기기 로그인 흐름은 Baron SSO 공식 정책에 맞춰 동작 확인했다.
|
||||
- 사용자는 앱에서 전화번호 입력 후 문자 링크를 받는다.
|
||||
- 문자 링크를 누르면 Chrome에서 Baron SSO 승인 완료 화면에 머문다.
|
||||
- 사용자가 직접 TDC114PLUS 앱으로 돌아오면 앱이 저장된 pendingRef로 poll을 재개하고 직원검색 메인 화면에 진입한다.
|
||||
- Baron SSO 정책상 문자 링크 클릭 후 Chrome이 자동으로 앱으로 돌아오는 기능은 현재 지원되지 않는다.
|
||||
- 직원검색 화면의 직원/조직 정보 호출은 `tdc114plus-auth` 5001 서버의 `/api/v1/integrations/org-context`를 사용한다.
|
||||
- 실기기에서 직원목록 표시 확인 완료:
|
||||
- IS3 중복 뱃지 제거 확인
|
||||
- 전화번호 `010-0000-0000` 형식 표시 확인
|
||||
- 직원목록 표시 확인
|
||||
|
||||
## 오늘 발생한 주요 이슈
|
||||
|
||||
### 1. 로그인 승인 후 앱 복귀 UX
|
||||
|
||||
현상:
|
||||
- 문자 링크 클릭 후 Chrome의 `로그인 승인 완료` 화면에 머물렀다.
|
||||
- 사용자가 `로그인 창으로 이동하기` 버튼을 누르면 Baron SSO 로그인창/대시보드 흐름으로 이동해 앱 메인 진입 흐름과 맞지 않았다.
|
||||
|
||||
확인된 정책:
|
||||
- Baron SSO 개발자 답변 기준, `/api/v1/auth/headless/link/init`에는 post-verify redirect 필드가 없다.
|
||||
- SMS 링크를 누른 브라우저는 verify-only approver로 동작한다.
|
||||
- 승인 완료 후 브라우저가 앱 callback/App Link로 자동 이동하는 정책은 없다.
|
||||
|
||||
현재 대응:
|
||||
- 앱 문구를 “문자 승인 후 앱으로 돌아오면 자동 로그인됩니다” 흐름으로 맞췄다.
|
||||
- 앱 복귀 시 저장된 pendingRef로 poll을 재개하도록 처리했다.
|
||||
|
||||
내일 확인할 것:
|
||||
- 사용자가 앱 복귀 시 즉시 메인으로 들어가는지 반복 테스트한다.
|
||||
- 자동 앱 복귀가 꼭 필요하면 Baron SSO 쪽 정책/기능 추가 요청 사안으로 분리한다.
|
||||
|
||||
### 2. `auth_provider_unavailable`
|
||||
|
||||
현상:
|
||||
- 로그인 화면에서 `승인 상태 확인 실패: auth_provider_unavailable` 발생.
|
||||
|
||||
원인:
|
||||
- 5001 `tdc114plus-auth` 서버가 Baron SSO `link/poll` 완료 후 OIDC redirect/consent/token exchange를 처리하는 구간에서 실패할 수 있었다.
|
||||
- 이후 서버를 최신 소스 기준으로 재기동하고 로그를 직접 확인했다.
|
||||
|
||||
확인 로그:
|
||||
- `link/init` 성공
|
||||
- `link/poll` pending 반복
|
||||
- `link/poll status=ok`
|
||||
- `/consent` redirect 감지
|
||||
- consent accept 성공
|
||||
- callback URL에 code 포함
|
||||
- token exchange 성공
|
||||
|
||||
결론:
|
||||
- 최신 `tdc114plus-auth` 소스와 올바른 환경값으로 실행하면 login -> poll -> consent -> token exchange는 정상 동작한다.
|
||||
|
||||
### 3. 직원검색 화면 로딩 지속
|
||||
|
||||
현상:
|
||||
- 직원검색 화면에 진입했지만 중앙 로딩만 표시되고 직원목록이 나오지 않았다.
|
||||
|
||||
확인:
|
||||
- 5001 서버 로그에 `GET /api/v1/integrations/org-context`가 여러 번 찍혔다.
|
||||
- 즉 앱이 직원/조직 API를 호출하지 않은 것이 아니라, 호출은 하고 있었다.
|
||||
|
||||
원인:
|
||||
- 5001 auth 서버를 수동 재기동하면서 조직도 연동 키 환경값을 빠뜨렸다.
|
||||
- 누락된 값:
|
||||
- `BARON_ORG_CONTEXT_KEY_ID`
|
||||
- `BARON_ORG_CONTEXT_KEY_SECRET`
|
||||
|
||||
조치:
|
||||
- `scripts/.env.android-device.local`에 있는 값을 기준으로 5001 서버를 기동하도록 자동화했다.
|
||||
- 새 스크립트 추가:
|
||||
- `scripts/start-auth-server.sh`
|
||||
- `scripts/startup.sh`에서 업무시작 시 `start-auth-server.sh --restart`를 자동 호출하도록 연결했다.
|
||||
- `scripts/shutdown.sh`에서 5001 auth 서버도 종료하도록 연결했다.
|
||||
- `scripts/.env.android-device.local`, staging env 파일 권한을 `600`으로 조정했다.
|
||||
|
||||
검증:
|
||||
|
||||
```bash
|
||||
./scripts/start-auth-server.sh --restart
|
||||
curl -fsSL --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{"jwks":"ok","provider":"baron","status":"ok"}
|
||||
```
|
||||
|
||||
실기기 화면:
|
||||
- 직원검색 화면에서 직원목록 정상 표시 확인.
|
||||
|
||||
## 내일 업무 시작 순서
|
||||
|
||||
1. Windows 관리자 PowerShell에서 ADB portproxy/방화벽 상태 확인이 필요하면 기존 절차대로 확인한다.
|
||||
2. Windows 일반 PowerShell에서 실기기 ADB 연결 확인:
|
||||
|
||||
```powershell
|
||||
cd $env:LOCALAPPDATA\Android\Sdk\platform-tools
|
||||
.\adb.exe devices
|
||||
```
|
||||
|
||||
3. WSL에서 업무시작 기동:
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/startup.sh --auto --wait=40
|
||||
```
|
||||
|
||||
4. 5001 auth 서버 확인:
|
||||
|
||||
```bash
|
||||
curl -fsSL --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
정상 기준:
|
||||
|
||||
```json
|
||||
{"jwks":"ok","provider":"baron","status":"ok"}
|
||||
```
|
||||
|
||||
5. 실기기 reverse 확인:
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh adb -s R5CT42QTCNX reverse --list
|
||||
```
|
||||
|
||||
필수:
|
||||
|
||||
```text
|
||||
tcp:5000 tcp:5000
|
||||
tcp:5001 tcp:5001
|
||||
```
|
||||
|
||||
6. 앱 실행 후 확인:
|
||||
- 로그인 세션이 남아 있으면 직원검색 화면 진입
|
||||
- 직원목록이 바로 표시되는지 확인
|
||||
- 로딩이 지속되면 5001 로그 확인
|
||||
|
||||
```bash
|
||||
tail -n 120 logs/$(date +%F)/tdc114plus-auth.log
|
||||
```
|
||||
|
||||
## 내일 우선 점검할 항목
|
||||
|
||||
- `startup.sh`가 `start-auth-server.sh --restart`를 정상 호출하는지 확인한다.
|
||||
- 직원검색 화면 진입 시 `GET /api/v1/integrations/org-context`가 5001 로그에 찍히는지 확인한다.
|
||||
- 직원목록 로딩이 다시 멈추면 가장 먼저 아래를 확인한다:
|
||||
- 5001 health
|
||||
- `scripts/.env.android-device.local` 존재 여부
|
||||
- `TDC114_BARON_KEY_ID`, `TDC114_BARON_KEY_SECRET` 값 누락 여부
|
||||
- adb reverse `tcp:5001 tcp:5001`
|
||||
|
||||
## 오늘 변경된 주요 파일
|
||||
|
||||
- `scripts/start-auth-server.sh`
|
||||
- 5001 `tdc114plus-auth` 로컬 서버 기동 스크립트.
|
||||
- `scripts/.env.android-device.local`에서 조직도 키를 읽어 `BARON_ORG_CONTEXT_*`로 주입한다.
|
||||
|
||||
- `scripts/startup.sh`
|
||||
- 업무시작 기동 시 `tdc114plus-auth` 5001 서버를 자동 기동하도록 연결.
|
||||
|
||||
- `scripts/shutdown.sh`
|
||||
- 업무종료 시 5001 auth 서버도 종료하도록 연결.
|
||||
|
||||
- `app/lib/src/features/auth/presentation/login_screen.dart`
|
||||
- 문자 승인 후 앱 복귀 안내 문구 반영.
|
||||
- pendingRef 복원/poll 오류 표시 개선.
|
||||
|
||||
- `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`
|
||||
- Baron SSO 공식 verify-only 정책과 앱 복귀 방식 반영.
|
||||
|
||||
## 주의 사항
|
||||
|
||||
- `scripts/.env.android-device.local`에는 실제 연동 키가 들어 있으므로 외부 공유 금지.
|
||||
- 내일 APK를 다시 빌드할 때는 반드시 auth base define을 포함한다.
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh build apk --debug \
|
||||
--dart-define=TDC114_API_BASE=http://127.0.0.1:5000 \
|
||||
--dart-define=TDC114_AUTH_API_BASE=http://127.0.0.1:5001 \
|
||||
--dart-define=TDC114_DIRECTORY_API_BASE=http://127.0.0.1:5000 \
|
||||
--dart-define=TDC114_ORGANIZATION_API_BASE=http://127.0.0.1:5000 \
|
||||
--dart-define=TDC114_ORG_CONTEXT_API_BASE=http://127.0.0.1:5001
|
||||
```
|
||||
|
||||
- 직원검색의 실제 직원/조직 조회는 현재 5001 auth broker를 통해 `/api/v1/integrations/org-context`로 간다.
|
||||
- 5000의 예전 `/api/v1/tdc114plus/employees` 류 경로는 현재 직원검색의 주 경로가 아니다.
|
||||
@@ -0,0 +1,189 @@
|
||||
# 2026-07-15 업무 인계 메모
|
||||
|
||||
작성 시각: 2026-07-15 KST
|
||||
|
||||
## 오늘 최종 상태
|
||||
|
||||
- 실기기 직원검색 화면에서 실제 프로필 사진 노출을 확인했다.
|
||||
- 현재 프로필 이미지 정책은 아래 순서로 정리된 상태다.
|
||||
1. 네이버웍스 프로필 사진
|
||||
2. Baron SSO `members[].id` 기준 UUID 파일명 이미지
|
||||
3. 앱 기본 아바타
|
||||
- `tdc114plus-auth`의 `GET /api/v1/profile-image`는 `NAVER_WORKS -> BARON_UUID_R2 -> DEFAULT` 순서로 동작하도록 정리했다.
|
||||
- 앱은 `GET /api/v1/profile-image`를 우선 호출하고, 응답 실패 또는 미발견 시 `https://baroncs.co.kr/employee_img/{uuid}.jpg` 경로를 보조 fallback으로 사용하도록 보강했다.
|
||||
- 실기기 캡처 기준으로 직원목록의 여러 사용자가 기본 이니셜 원이 아니라 실제 사진으로 표시되는 것을 확인했다.
|
||||
|
||||
## 오늘 진행한 핵심 작업
|
||||
|
||||
### 1. 네이버웍스 1순위 경로 실검증
|
||||
|
||||
확인 내용:
|
||||
|
||||
- 서비스 계정 자격값을 최신값으로 다시 반영했다.
|
||||
- 토큰 발급이 실제로 성공하는지 재검증했다.
|
||||
- `GET /users/{userId}` 와 `GET /users/{userId}/photo`를 실제 호출해 `302`, `404` 동작을 다시 확인했다.
|
||||
|
||||
확인 결과:
|
||||
|
||||
- `thlee3@samaneng.com`
|
||||
- 프로필 조회 `HTTP 200`
|
||||
- 사진 조회 `HTTP 302`
|
||||
- `khkang@samaneng.com`
|
||||
- 프로필 조회 `HTTP 200`
|
||||
- 사진 조회 `HTTP 404`
|
||||
|
||||
의미:
|
||||
|
||||
- 네이버웍스 사진이 있는 사용자는 1순위 경로로 바로 쓸 수 있다.
|
||||
- 네이버웍스 사진이 없는 사용자는 2순위 UUID 이미지로 내려가면 된다.
|
||||
|
||||
### 2. Baron UUID 기반 2순위 경로 재확정
|
||||
|
||||
확인 내용:
|
||||
|
||||
- `org-context` 실응답의 `members[].id`가 실제 UUID 형식인지 다시 확인했다.
|
||||
- 기존 CSV와 가족사 전체 응답을 대조한 매핑 결과를 기준으로 UUID 파일명 정책을 유지하기로 정리했다.
|
||||
- 외부 공개 경로는 `https://baroncs.co.kr/employee_img/{uuid}.jpg` 규칙으로 본다.
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 2순위 식별자는 이메일 local-part나 해시명이 아니라 Baron UUID로 보는 것이 가장 안정적이다.
|
||||
- 프로필 이미지 전용 DB는 운영 기본안으로 채택하지 않고 보류 대안으로만 남긴다.
|
||||
|
||||
### 3. `tdc114plus-auth` 프로필 이미지 endpoint 보강
|
||||
|
||||
오늘 반영한 내용:
|
||||
|
||||
- `GET /api/v1/profile-image`에 네이버웍스 1순위 조회를 연결했다.
|
||||
- 네이버웍스에서 사진이 없으면 Baron UUID 기준 공개 이미지 경로를 2순위로 판단하게 정리했다.
|
||||
- 기존 PostgreSQL 매핑 경로는 최후 예비안 수준으로만 남겼다.
|
||||
|
||||
실검증 결과:
|
||||
|
||||
- `GET /api/v1/profile-image?email=thlee3@samaneng.com`
|
||||
- `found=true`
|
||||
- `source=NAVER_WORKS`
|
||||
- `GET /api/v1/profile-image?email=khkang@samaneng.com`
|
||||
- `found=true`
|
||||
- `source=BARON_UUID_R2`
|
||||
|
||||
의미:
|
||||
|
||||
- 서버 레벨에서는 1순위/2순위 fallback이 실제 응답으로 이미 확인된 상태다.
|
||||
|
||||
### 4. 앱 프로필 이미지 resolver 보강
|
||||
|
||||
오늘 반영한 내용:
|
||||
|
||||
- 앱은 다시 `tdc114plus-auth /api/v1/profile-image`를 우선 호출하도록 정리했다.
|
||||
- 응답 실패, 미발견, 또는 세션 문제 상황에서는 UUID 형식 `employee.id`가 있으면 공개 UUID 이미지 경로를 직접 fallback 하도록 보강했다.
|
||||
- 관련 단위 테스트를 추가하고 통과시켰다.
|
||||
|
||||
테스트 결과:
|
||||
|
||||
- `app/test/directory/profile_image_api_client_test.dart`
|
||||
- auth endpoint 경유 성공
|
||||
- 이메일 없음 시 기본 null 처리
|
||||
- auth 미발견 시 UUID 공개 경로 fallback
|
||||
- 테스트 통과 확인
|
||||
|
||||
### 5. 실기기 반영 및 화면 확인
|
||||
|
||||
실행 내용:
|
||||
|
||||
- auth 서버 기동 상태 확인
|
||||
- APK 빌드 및 실기기 설치
|
||||
- 공기계에서 직원검색 화면 재진입
|
||||
- 실기기 화면 캡처로 실제 사진 표시 여부 확인
|
||||
|
||||
최종 확인:
|
||||
|
||||
- 직원검색 목록에서 여러 사용자 사진이 실제로 표시됨
|
||||
- 오늘 목표였던 “실기기에서 사진 뜨는지 확인”은 완료
|
||||
|
||||
## 오늘 발생한 보조 이슈
|
||||
|
||||
### 1. 실기기 재실행 중 bootstrap 일시 실패
|
||||
|
||||
현상:
|
||||
|
||||
- 일부 재실행 구간에서 `127.0.0.1:5000` bootstrap 연결 실패 메시지가 한 차례 있었다.
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 이후 권한 포함 재실행에서는 정상 bootstrap 후 앱이 다시 올라왔다.
|
||||
- 오늘 최종 결과는 실기기 사진 표시 성공으로 본다.
|
||||
|
||||
### 2. Docker/ADB 권한 및 대기 시간 이슈
|
||||
|
||||
현상:
|
||||
|
||||
- 일부 재실행 또는 조회 명령은 Docker 권한/ADB 응답 지연 때문에 중간 확인이 매끄럽지 않았다.
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 기능 자체의 blocker는 아니었다.
|
||||
- 최종적으로 실기기 캡처까지 확보했으므로 오늘 작업 결론에는 영향 없다.
|
||||
|
||||
## 오늘 변경 및 반영한 주요 파일
|
||||
|
||||
- `app/lib/src/features/directory/data/profile_image_api_client.dart`
|
||||
- auth endpoint 우선 호출
|
||||
- UUID 직접 fallback 추가
|
||||
- debug 로그 보강
|
||||
|
||||
- `app/test/directory/profile_image_api_client_test.dart`
|
||||
- UUID fallback 관련 테스트 추가
|
||||
|
||||
- `scripts/start-auth-server.sh`
|
||||
- 네이버웍스 env를 함께 읽어 auth 서버 기동 시 반영되도록 정리
|
||||
|
||||
- `docs/00_guide_tdc114plus_profile_image_identifier_mapping_2026-07-14.md`
|
||||
- 오늘 실검증 결과와 실기기 성공 결과 반영
|
||||
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- 오늘 진행 상태와 다음 검증 포인트 반영
|
||||
|
||||
## 내일 바로 이어서 볼 항목
|
||||
|
||||
1. 현재 화면에 뜬 각 프로필 사진이 `NAVER_WORKS`인지 `BARON_UUID_R2`인지 source별로 구분 검증한다.
|
||||
2. 직원검색뿐 아니라 직원 상세/조직도 화면에서도 같은 규칙으로 사진이 표시되는지 확인한다.
|
||||
3. `DEFAULT` 케이스도 샘플로 잡아 기본 아바타 fallback이 자연스러운지 확인한다.
|
||||
4. 필요 시 프로필 이미지 관련 debug 로그를 더 짧게 정리하거나 제거한다.
|
||||
|
||||
## 내일 업무 시작 순서
|
||||
|
||||
1. auth 서버 상태 확인
|
||||
|
||||
```bash
|
||||
curl -fsSL --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
2. 실기기 reverse 상태 확인
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh adb -s R5CT42QTCNX reverse --list
|
||||
```
|
||||
|
||||
3. 필요 시 auth 서버 재기동
|
||||
|
||||
```bash
|
||||
./scripts/start-auth-server.sh --restart --env-file=/home/ubuntu/workspace/tdc114plus/scripts/.env.android-device.local
|
||||
```
|
||||
|
||||
4. 필요 시 실기기 앱 재실행
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 TDC114_FLUTTER_DEVICE_ID=R5CT42QTCNX TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local ./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
5. 첫 확인 포인트
|
||||
- 직원검색 목록 진입
|
||||
- 사진이 계속 노출되는지 확인
|
||||
- source별 구분 검증 대상으로 사용자 샘플 확보
|
||||
|
||||
## 오늘 결론
|
||||
|
||||
- 오늘 작업의 핵심 목표였던 “실기기에서 프로필 사진이 실제로 뜨는지 확인”은 완료했다.
|
||||
- 현재 구조는 `네이버웍스 -> Baron UUID 이미지 -> 기본 아바타` 정책과 실제 코드/실기기 화면이 서로 맞물리는 상태다.
|
||||
- 내일은 새로운 구현보다, 오늘 붙인 구조를 source별로 더 명확히 검증하고 화면 범위를 넓히는 단계로 이어가면 된다.
|
||||
@@ -0,0 +1,83 @@
|
||||
# 2026-07-16 아침 시작 체크리스트
|
||||
|
||||
목적: 오늘 작업을 바로 이어가기 위해, 가장 먼저 확인할 항목만 짧게 정리한다.
|
||||
|
||||
## 1. 먼저 볼 기준
|
||||
|
||||
- 현재 프로필 이미지 정책:
|
||||
1. 네이버웍스
|
||||
2. Baron UUID 이미지
|
||||
3. 기본 아바타
|
||||
- 전날 최종 상태:
|
||||
- 실기기 직원검색 화면에서 실제 프로필 사진 노출 확인 완료
|
||||
- 앱은 `tdc114plus-auth /api/v1/profile-image` 우선 호출
|
||||
- 실패 또는 미발견 시 `https://baroncs.co.kr/employee_img/{uuid}.jpg` fallback 사용
|
||||
|
||||
## 2. 아침 시작 순서
|
||||
|
||||
### 1) auth 서버 상태 확인
|
||||
|
||||
```bash
|
||||
curl -fsSL --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
정상 기준:
|
||||
|
||||
```json
|
||||
{"jwks":"ok","provider":"baron","status":"ok"}
|
||||
```
|
||||
|
||||
### 2) reverse 상태 확인
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh adb -s R5CT42QTCNX reverse --list
|
||||
```
|
||||
|
||||
필수 확인:
|
||||
|
||||
```text
|
||||
tcp:5000 tcp:5000
|
||||
tcp:5001 tcp:5001
|
||||
```
|
||||
|
||||
### 3) 필요 시 auth 서버 재기동
|
||||
|
||||
```bash
|
||||
./scripts/start-auth-server.sh --restart --env-file=/home/ubuntu/workspace/tdc114plus/scripts/.env.android-device.local
|
||||
```
|
||||
|
||||
### 4) 필요 시 실기기 앱 재실행
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 TDC114_FLUTTER_DEVICE_ID=R5CT42QTCNX TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local ./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
## 3. 첫 확인 포인트
|
||||
|
||||
- 직원검색 목록 진입되는가
|
||||
- 사진이 계속 표시되는가
|
||||
- 어떤 사용자가 `NAVER_WORKS`인지, 어떤 사용자가 `BARON_UUID_R2`인지 샘플을 잡을 수 있는가
|
||||
|
||||
## 4. 오늘 바로 이어서 할 일
|
||||
|
||||
1. 실기기 기준 `NAVER_WORKS` 케이스 확인
|
||||
2. 실기기 기준 `BARON_UUID_R2` 케이스 확인
|
||||
3. `DEFAULT` 기본 아바타 케이스 확인
|
||||
4. 직원 상세/조직도 화면에서도 같은 규칙 유지 확인
|
||||
|
||||
## 5. 문제 생기면 먼저 볼 것
|
||||
|
||||
- `5001 health` 정상 여부
|
||||
- `adb reverse`에 `5000`, `5001` 둘 다 있는지
|
||||
- `scripts/.env.android-device.local` 경로와 값 누락 여부
|
||||
- 필요 시 auth 로그 확인
|
||||
|
||||
```bash
|
||||
tail -n 120 logs/$(date +%F)/tdc114plus-auth.log
|
||||
```
|
||||
|
||||
## 6. 참고 문서
|
||||
|
||||
- [2026-07-15_work_handoff.md](/home/ubuntu/workspace/tdc114plus/docs/daily-issues/2026-07-15_work_handoff.md)
|
||||
- [00_guide_tdc114plus_profile_image_identifier_mapping_2026-07-14.md](/home/ubuntu/workspace/tdc114plus/docs/00_guide_tdc114plus_profile_image_identifier_mapping_2026-07-14.md)
|
||||
- [00_guide_tdc114plus_work_progress_timetable_2026-07-02.md](/home/ubuntu/workspace/tdc114plus/docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md)
|
||||
@@ -0,0 +1,224 @@
|
||||
# 2026-07-16 업무 인계 메모
|
||||
|
||||
작성 시각: 2026-07-16 KST
|
||||
|
||||
## 오늘 최종 상태
|
||||
|
||||
- 실기기 로그인은 다시 정상 진행됐다.
|
||||
- 문자 링크 승인 후 앱 복귀 시 직원검색 목록이 다시 표시되는 것까지 확인했다.
|
||||
- 오늘 최종 복구 기준은 `로그인 성공 -> 직원검색 목록 표시 성공`이다.
|
||||
- 다만 프로필 사진 1순위/2순위/3순위 화면 검증은 아직 오늘 완료 범위에 포함하지 않는다.
|
||||
|
||||
## 오늘 발생한 주요 이슈와 원인
|
||||
|
||||
### 1. 로그인 후 직원검색이 다시 무너지는 문제
|
||||
|
||||
현상:
|
||||
|
||||
- 로그인 링크 발송은 되지만 앱 진입 후 직원검색 화면이 비거나 로딩만 지속됐다.
|
||||
- 잠시 후 `로그인이 만료되었거나 권한을 확인할 수 없습니다.` 화면으로 떨어졌다.
|
||||
|
||||
중간에 확인한 사실:
|
||||
|
||||
- 앱 SharedPreferences 안에는 세션 토큰이 실제로 저장되고 있었다.
|
||||
- 저장된 토큰은 Baron access token이 아니라 `tdc114plus-auth`가 발급한 app session token 형식이었다.
|
||||
- 저장된 user 정보는 아래처럼 fallback 값이었다.
|
||||
- `id = baron-user`
|
||||
- `name = Baron User`
|
||||
- `tenantSlug = ""`
|
||||
|
||||
의미:
|
||||
|
||||
- 세션 토큰이 전혀 저장되지 않는 문제는 아니었다.
|
||||
- 다만 user 메타데이터는 충분하지 않았고, 동시에 org-context 중계 경로도 깨져 있었다.
|
||||
|
||||
### 2. 핵심 장애 원인: 5001 auth broker의 org-context self-recursion
|
||||
|
||||
현상:
|
||||
|
||||
- `tdc114plus-auth` 로그에 `/api/v1/integrations/org-context` 요청이 들어온 뒤,
|
||||
같은 5001 서버가 다시 자기 자신의 `/api/v1/integrations/org-context`를 호출하는 패턴이 반복됐다.
|
||||
- 내부 재호출 요청에는 `Authorization`, `X-App-Session` 헤더가 없어서 결국 unauthorized 흐름으로 무너졌다.
|
||||
|
||||
실제 확인값:
|
||||
|
||||
- 실행 중인 5001 프로세스 환경변수에서 아래를 직접 확인했다.
|
||||
|
||||
```text
|
||||
BARON_ORG_CONTEXT_BASE_URL=http://127.0.0.1:5001
|
||||
```
|
||||
|
||||
즉:
|
||||
|
||||
- 원래 의도는 `https://sadmin.hmac.kr`를 upstream으로 호출해야 하는데,
|
||||
- 실제 실행 중 프로세스는 자기 자신 `http://127.0.0.1:5001`을 upstream으로 잡고 있었다.
|
||||
|
||||
근본 원인:
|
||||
|
||||
- `scripts/start-auth-server.sh`가
|
||||
`TDC114_AUTH_UPSTREAM_ORG_CONTEXT_API_BASE` 값을 env 파일 `source` 전에 먼저 읽고 있었다.
|
||||
- 그래서 `scripts/.env.android-device.local` 안에
|
||||
`TDC114_AUTH_UPSTREAM_ORG_CONTEXT_API_BASE=https://sadmin.hmac.kr`
|
||||
가 있어도 반영되지 않았다.
|
||||
- 그 결과 fallback으로 `TDC114_ORG_CONTEXT_API_BASE=http://127.0.0.1:5001`를 사용하면서 self-recursion이 발생했다.
|
||||
|
||||
### 3. 오늘 복구 조치
|
||||
|
||||
수정 파일:
|
||||
|
||||
- `scripts/start-auth-server.sh`
|
||||
|
||||
수정 내용:
|
||||
|
||||
- `UPSTREAM_ORG_CONTEXT_BASE` 읽는 위치를 env 파일 `source` 뒤로 옮겼다.
|
||||
- 이후 5001 auth broker를 재기동했다.
|
||||
|
||||
재기동 후 직접 확인한 실행 환경:
|
||||
|
||||
```text
|
||||
PORT=5001
|
||||
APP_SESSION_SECRET=tdc114plus-dev-session
|
||||
BARON_ORG_CONTEXT_BASE_URL=https://sadmin.hmac.kr
|
||||
BARON_ORG_CONTEXT_TENANT_SLUG=hanmac-family
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
- self-recursion 원인이 제거됐다.
|
||||
- 다시 로그인 후 실기기 직원검색 목록이 정상 표시됐다.
|
||||
|
||||
## 오늘 추가로 확인한 기술 메모
|
||||
|
||||
### 1. `baron-user / Baron User` 생성 위치
|
||||
|
||||
파일:
|
||||
|
||||
- `/home/ubuntu/workspace/tdc114plus-auth/cmd/server/main.go`
|
||||
|
||||
확인 내용:
|
||||
|
||||
- `link/poll` 완료 후 `poll.User`에 값이 없을 때 fallback으로 아래 값이 채워진다.
|
||||
- `baron-user`
|
||||
- `Baron User`
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 이 값은 오늘 새로 생긴 회귀가 아니라 기존 구조였다.
|
||||
- 오늘의 실장애 원인은 이것 자체보다 `org-context upstream 오배선`이었다.
|
||||
|
||||
### 2. `tenantSlug` 누락 구조는 후속 개선 대상
|
||||
|
||||
현재 확인 결과:
|
||||
|
||||
- `tdc114plus-auth`의 `link/poll` 응답 user 모델에는 `tenantSlug`, `tenantId`, `tenantName`이 없다.
|
||||
- 앱은 세션 user의 `tenantSlug`가 비어 있으면 후속 조직도/초기 선택 계산에서 fallback을 더 많이 타게 된다.
|
||||
|
||||
중요 판단:
|
||||
|
||||
- 오늘 직원검색이 완전히 무너진 직접 원인은 self-recursion이었다.
|
||||
- 하지만 `tenantSlug` 누락 구조는 다음 작업에서 별도로 정리해야 한다.
|
||||
|
||||
## 오늘 수정/추가한 파일
|
||||
|
||||
- `scripts/start-auth-server.sh`
|
||||
- org-context upstream env 읽는 순서를 수정했다.
|
||||
|
||||
- `app/lib/src/core/config/app_environment.dart`
|
||||
- 빌드 시각 define 표시용 항목을 유지했다.
|
||||
|
||||
- `app/lib/src/features/auth/presentation/login_screen.dart`
|
||||
- 실기기에서 최신 APK 식별을 위해 빌드 시각 표시를 유지했다.
|
||||
|
||||
## 확인 완료한 테스트
|
||||
|
||||
1. 5001 health 확인
|
||||
|
||||
```bash
|
||||
curl -i --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
```json
|
||||
{"jwks":"ok","provider":"baron","status":"ok"}
|
||||
```
|
||||
|
||||
2. 실행 중 5001 프로세스 환경변수 확인
|
||||
|
||||
- `BARON_ORG_CONTEXT_BASE_URL=https://sadmin.hmac.kr` 반영 확인
|
||||
|
||||
3. 실기기 세션 저장 확인
|
||||
|
||||
- SharedPreferences 안에 app session token 저장 확인
|
||||
- user fallback 값 저장 확인
|
||||
|
||||
4. 실기기 재로그인 후 직원검색 확인
|
||||
|
||||
- 문자 링크 승인 성공
|
||||
- 앱 복귀 성공
|
||||
- 직원검색 목록 표시 성공
|
||||
|
||||
## 내일 업무 시작 순서
|
||||
|
||||
1. 전일 인계 문서 먼저 확인
|
||||
|
||||
- `docs/daily-issues/2026-07-16_work_handoff.md`
|
||||
|
||||
2. 5001 auth broker health 확인
|
||||
|
||||
```bash
|
||||
curl -fsSL --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
3. 실행 중 5001 프로세스 upstream 값 확인
|
||||
|
||||
```bash
|
||||
ss -ltnp '( sport = :5001 )'
|
||||
tr '\0' '\n' < /proc/<PID>/environ | rg 'BARON_ORG_CONTEXT_BASE_URL|BARON_ORG_CONTEXT_TENANT_SLUG'
|
||||
```
|
||||
|
||||
정상 기준:
|
||||
|
||||
```text
|
||||
BARON_ORG_CONTEXT_BASE_URL=https://sadmin.hmac.kr
|
||||
BARON_ORG_CONTEXT_TENANT_SLUG=hanmac-family
|
||||
```
|
||||
|
||||
4. 실기기 ADB 연결 및 reverse 확인
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh adb -s R5CT42QTCNX reverse --list
|
||||
```
|
||||
|
||||
5. 앱 재로그인 후 첫 확인
|
||||
|
||||
- 직원검색 목록이 바로 뜨는지
|
||||
- 30초 뒤에도 만료 화면으로 떨어지지 않는지
|
||||
|
||||
## 내일 우선 점검할 항목
|
||||
|
||||
1. `org-context` self-recursion이 정말 재발하지 않는지 먼저 확인한다.
|
||||
2. `tenantSlug` 누락 구조를 `tdc114plus-auth` 응답 모델 기준으로 정리한다.
|
||||
3. 프로필 사진 우선순위 검증을 아래 순서로 이어간다.
|
||||
- NAVER_WORKS
|
||||
- BARON_UUID_R2
|
||||
- DEFAULT
|
||||
4. 직원검색 외에 조직도/상세/즐겨찾기 화면도 같은 세션 상태에서 유지되는지 확인한다.
|
||||
|
||||
## 보안상 주의사항
|
||||
|
||||
- 아래 값들은 문서에 실제 값을 남기지 않는다.
|
||||
- NAVER WORKS 서비스 계정 자격값
|
||||
- Baron org-context key id / secret
|
||||
- private key 경로 및 원문
|
||||
|
||||
- `scripts/.env.android-device.local`
|
||||
- `secrets/naver_works_service_account.local.env`
|
||||
|
||||
위 두 파일은 계속 비공개 로컬 파일로만 유지한다.
|
||||
|
||||
## 내일 첫 판단 기준
|
||||
|
||||
- 내일 첫 목표는 “또 고치는 것”이 아니라 “오늘 복구한 5001 upstream 상태가 유지되는지 먼저 검증”이다.
|
||||
- 그 상태가 유지되면 사진 정책 검증으로 넘어가고,
|
||||
- 유지되지 않으면 가장 먼저 `start-auth-server.sh`와 실행 중 프로세스 환경변수부터 다시 본다.
|
||||
@@ -0,0 +1,305 @@
|
||||
# 2026-07-20 업무 인계 메모
|
||||
|
||||
작성 시각: 2026-07-20 KST
|
||||
|
||||
## 오늘 핵심 결론
|
||||
|
||||
- `tdc114plus` 앱과 로컬 `tdc114plus-auth:5001` 연결은 정상 확인했다.
|
||||
- 실기기 `adb reverse tcp:5001 tcp:5001`도 정상 확인했다.
|
||||
- 앱에서 `link/init` 호출 후 `pendingRef` 생성, 이후 `link/poll` 반복까지 서버 로그로 확인했다.
|
||||
- 즉 오늘 로그인 막힘의 핵심은 `앱 <-> 로컬 중계서버` 구간이 아니라 `Baron SSO 문자 링크 실제 발송/SMS 연계 구간`으로 판단했다.
|
||||
|
||||
## 오늘 확인한 최종 상태
|
||||
|
||||
### 1. 로컬 auth broker 상태
|
||||
|
||||
정상 확인값:
|
||||
|
||||
```bash
|
||||
curl -i --max-time 5 http://127.0.0.1:5001/health
|
||||
```
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{"jwks":"ok","provider":"baron","status":"ok"}
|
||||
```
|
||||
|
||||
의미:
|
||||
|
||||
- 로컬 `tdc114plus-auth` 5001은 떠 있었다.
|
||||
- 최소한 health 기준으로는 죽어 있지 않았다.
|
||||
|
||||
### 2. 실기기 reverse 상태
|
||||
|
||||
사용자 확인 결과:
|
||||
|
||||
```text
|
||||
adb reverse --list
|
||||
UsbFfs tcp:5001 tcp:5001
|
||||
```
|
||||
|
||||
의미:
|
||||
|
||||
- 실기기에서 `127.0.0.1:5001`로 가는 호출은 PC 로컬 5001로 붙는 상태였다.
|
||||
- 따라서 실기기에서 auth broker 접속이 안 되는 상태는 아니었다.
|
||||
|
||||
### 3. 앱이 실제로 5001에 요청을 보내는지 확인
|
||||
|
||||
서버 로그에서 아래를 직접 확인했다.
|
||||
|
||||
```text
|
||||
linkInit body={"phoneNumber":"01091365338","device":{"platform":"android","appVersion":"0.1.0","deviceName":"android"}}
|
||||
```
|
||||
|
||||
그리고 이어서:
|
||||
|
||||
```text
|
||||
POST /api/v1/auth/link/init
|
||||
POST /api/v1/auth/link/poll
|
||||
```
|
||||
|
||||
반복 확인했다.
|
||||
|
||||
의미:
|
||||
|
||||
- 앱에서 로그인 버튼을 눌렀을 때 요청이 실제로 로컬 auth broker까지 도달했다.
|
||||
- `pendingRef` 생성도 정상 진행됐다.
|
||||
|
||||
### 4. 앱 내부 pending 상태 저장 확인
|
||||
|
||||
실기기 SharedPreferences에서 아래 항목을 직접 확인했다.
|
||||
|
||||
- `flutter.tdc114plus.auth.pending.ref`
|
||||
- `flutter.tdc114plus.auth.pending.expiresAt`
|
||||
|
||||
의미:
|
||||
|
||||
- 앱이 로그인 요청 직후 pending 상태를 저장하지 못하는 문제는 아니었다.
|
||||
- 앱 내부 상태 저장까지는 정상으로 봐도 된다.
|
||||
|
||||
## 오늘 발생한 실제 장애
|
||||
|
||||
현상:
|
||||
|
||||
- 앱에서는 `승인 대기 중` 화면으로 넘어간다.
|
||||
- 하지만 사용자 휴대폰에는 실제 문자 링크가 도착하지 않는다.
|
||||
- 재전송 시도 후에도 동일하다.
|
||||
|
||||
중요 판단:
|
||||
|
||||
- 앱 요청 실패 아님
|
||||
- 로컬 auth broker 연결 실패 아님
|
||||
- `adb reverse` 누락 문제 아님
|
||||
- 현재 가장 의심되는 구간은 Baron SSO 쪽 `문자 링크 실제 발송 처리` 또는 그 뒤 SMS 연계 구간이다.
|
||||
|
||||
## 오늘 중간에 있었던 혼선 정리
|
||||
|
||||
### 1. `auth_provider_unavailable`
|
||||
|
||||
한 시점에는 앱에 아래 문구가 보였다.
|
||||
|
||||
```text
|
||||
로그인 링크 요청 실패: auth_provider_unavailable
|
||||
```
|
||||
|
||||
이때 직접 확인한 사실:
|
||||
|
||||
- 같은 시각 `sso.hmac.kr /oidc/oauth2/auth`가 `502 Bad Gateway`를 반환하던 구간이 있었다.
|
||||
- 이후 재확인 시 다시 `302 Location: /login?login_challenge=...`로 정상 응답했다.
|
||||
|
||||
의미:
|
||||
|
||||
- Baron SSO upstream authorization 시작점이 한때 불안정했다.
|
||||
- 하지만 이후 복구된 뒤에도 최종적으로는 `문자 미수신` 문제가 남았다.
|
||||
|
||||
### 2. callback URL 혼선
|
||||
|
||||
아래 주소는 현재 직접 열면 `404 page not found`가 보인다.
|
||||
|
||||
```text
|
||||
https://114-auth.hmac.kr/api/v1/auth/oidc/callback
|
||||
```
|
||||
|
||||
정리:
|
||||
|
||||
- 이 URL은 브라우저에서 직접 여는 진입 URL이 아니라 OIDC 최종 code 수신용 callback 경로다.
|
||||
- 현재 `문자 미수신` 문제의 직접 원인으로 확정한 상태는 아니다.
|
||||
- 다만 라우트 정합성은 후속 점검 대상으로 계속 유지한다.
|
||||
|
||||
## 오늘 외부 전달용 요약
|
||||
|
||||
Baron SSO 개발자에게 전달할 핵심은 아래였다.
|
||||
|
||||
```text
|
||||
- 신규앱 -> 로컬 tdc114plus-auth(5001) 요청 정상
|
||||
- adb reverse 정상
|
||||
- auth 서버 로그상 link/init, pendingRef 생성, link/poll 반복 정상
|
||||
- 그런데 실제 문자 링크가 사용자 휴대폰에 도착하지 않음
|
||||
- 따라서 Baron SSO 쪽 문자 링크 실제 발송 처리 또는 SMS 연계 구간 확인 필요
|
||||
```
|
||||
|
||||
## 오늘 기준 남아 있는 작업
|
||||
|
||||
### 1. 문자 미수신 이슈 답변 대기
|
||||
|
||||
- Baron SSO 개발자 확인 결과를 받아야 한다.
|
||||
- 그 전까지는 앱/로컬 중계서버 쪽에서 더 고쳐도 문자 미수신 문제를 끝낼 수 없다.
|
||||
|
||||
### 2. 프로필 사진 route 상태 정리
|
||||
|
||||
현재 확인 상태:
|
||||
|
||||
- 앱은 `/api/v1/profile-image`를 먼저 시도한다.
|
||||
- 하지만 현재 5001 서버는 해당 route에 `404`를 반환한다.
|
||||
|
||||
의미:
|
||||
|
||||
- 사진 1순위/2순위/3순위 실기기 검증은 아직 시작 조건이 완전히 갖춰지지 않았다.
|
||||
|
||||
### 3. 로그인 화면 상태 문구 정리
|
||||
|
||||
관찰된 화면:
|
||||
|
||||
- 실패 문구
|
||||
- 승인 대기 박스
|
||||
- 재전송 카운트
|
||||
|
||||
이 조합이 시점별로 다르게 보였다.
|
||||
|
||||
후속 과제:
|
||||
|
||||
- 요청 시작 시 이전 에러 문구를 항상 지우는지
|
||||
- pending 복원 시 에러 상태를 같이 끌고 오지 않는지
|
||||
- 문자 미수신과는 별개로 화면 상태 표현이 꼬이지 않는지
|
||||
|
||||
## 외부 답변 대기 중 내부 진행 순서
|
||||
|
||||
문자 발송 구간 답변이 오기 전에도 아래 순서로는 내부 작업을 진행할 수 있다.
|
||||
|
||||
1. `tdc114plus-auth` 응답 메타데이터 정합성 재확인
|
||||
- `tenantSlug`, `tenantId`, `tenantName`, `department`, `grade`, `position`, `jobTitle`
|
||||
- 앱이 실제로 어떤 필드를 저장하고 소비하는지 확인
|
||||
|
||||
2. 로그인 화면 상태 표현 정리
|
||||
- `실패 문구`와 `승인 대기 UI`가 동시에 남지 않도록 정리
|
||||
- pending 복원 시 문구 초기화 조건 확인
|
||||
|
||||
3. `/api/v1/profile-image` route 복구 준비
|
||||
- 현재 앱 호출 형식 고정
|
||||
- auth 서버 route 부재 상태 문서화
|
||||
- 복구 시 필요한 응답 형태 확정
|
||||
|
||||
4. 프로필 사진 검증 대상 사용자 표 준비
|
||||
- NAVER WORKS 1순위 예상 사용자
|
||||
- UUID 이미지 2순위 예상 사용자
|
||||
- DEFAULT 3순위 예상 사용자
|
||||
|
||||
5. `baron-sso-tdc114plus-api` 제거 마이그레이션 표 세분화
|
||||
- 남은 기능이 진짜 필요한지
|
||||
- `tdc114plus-auth`에 흡수할지
|
||||
- 완전히 제거할지 분류
|
||||
|
||||
## 2026-07-20 메타데이터 정합성 재확인 결과
|
||||
|
||||
확인 결과:
|
||||
|
||||
- `tdc114plus-auth`가 내보내는 사용자 메타데이터 JSON 키와
|
||||
- `tdc114plus` 앱이 저장/사용하는 JSON 키는 현재 서로 맞는다.
|
||||
|
||||
확인한 키:
|
||||
|
||||
- `tenantId`
|
||||
- `tenantName`
|
||||
- `tenantSlug`
|
||||
- `department`
|
||||
- `grade`
|
||||
- `position`
|
||||
- `jobTitle`
|
||||
|
||||
정리:
|
||||
|
||||
1. 중계서버 출력
|
||||
- `tdc114plus-auth/cmd/server/main.go`
|
||||
- `readUser(...)`가 위 항목들을 읽는다.
|
||||
- `issueAppSessionToken(...)`가 같은 키명으로 JWT `user` 클레임에 넣는다.
|
||||
|
||||
2. 앱 수신/저장
|
||||
- `app/lib/src/features/auth/domain/auth_models.dart`
|
||||
- `LoginUser.fromJson(...)`가 같은 키명으로 파싱한다.
|
||||
- `app/lib/src/features/auth/data/auth_session_store.dart`
|
||||
- 세션 저장 시 `response.user.toJson()` 그대로 SharedPreferences에 저장한다.
|
||||
|
||||
3. 앱 소비 위치
|
||||
- `app/lib/src/features/directory/presentation/directory_screen.dart`
|
||||
- `tenantSlug`가 있으면 초기 회사 선택에 바로 사용한다.
|
||||
- `tenantSlug`가 비어 있으면 조직도 조회 fallback으로 현재 사용자 소속을 다시 찾는다.
|
||||
- `department`가 있으면 초기 부서 고정에도 바로 사용한다.
|
||||
- `profile_image_api_client.dart`에서도 `tenantSlug`/`tenantName`를 회사코드 추정에 사용한다.
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 구조적 키 mismatch 문제는 아니다.
|
||||
- 진짜 남은 위험은 `Baron upstream 응답에서 값이 비어 들어오는 경우`다.
|
||||
- 특히 `tenantSlug`가 비면 앱은 fallback으로 버티지만, 초기 선택과 사진 1차 lookup 정확도는 떨어질 수 있다.
|
||||
|
||||
## 2026-07-20 프로필 사진 검증 대상 표
|
||||
|
||||
현재 문서와 과거 실검증 이력을 기준으로, source별 우선 확인 대상은 아래처럼 정리한다.
|
||||
|
||||
| 우선순위 | 예상 source | 사용자 | 근거 | 현재 상태 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1순위 | `NAVER_WORKS` | `thlee3@samaneng.com` | 2026-07-15 네이버웍스 사진 조회 `HTTP 302` 확인 이력 | route 복구 후 실기기 재검증 필요 |
|
||||
| 2순위 | `BARON_UUID_R2` | `khkang@samaneng.com` | 2026-07-15 네이버웍스 사진 조회 `HTTP 404`, UUID 공개 이미지 fallback 이력 | route 복구 후 실기기 재검증 필요 |
|
||||
| 3순위 | `DEFAULT` | 미확정 | 실제 운영 사용자 중 `네이버웍스 없음 + UUID 이미지 없음` 샘플을 아직 확정하지 못함 | 샘플 대상 추가 선정 필요 |
|
||||
|
||||
현재 판단:
|
||||
|
||||
- 1순위와 2순위는 과거 실검증 이력이 있는 샘플이 이미 있다.
|
||||
- 3순위는 억지로 추정하지 말고, route 복구 후 실제 미보유 샘플을 한 명 확정하는 것이 안전하다.
|
||||
|
||||
## 2026-07-20 `/api/v1/profile-image` 복구 진행 결과
|
||||
|
||||
이번 복구에서 반영한 범위:
|
||||
|
||||
- `tdc114plus-auth`에 `GET /api/v1/profile-image` route를 다시 등록했다.
|
||||
- 현재 복구 로직은 아래 순서로 동작한다.
|
||||
1. `NAVER_WORKS`
|
||||
2. `BARON_UUID_R2`
|
||||
3. `DEFAULT`
|
||||
|
||||
구체 복구 내용:
|
||||
|
||||
- 네이버웍스 서비스 계정 env가 있으면 `GET /users/{email}/photo`의 `302/404` 규칙을 사용한다.
|
||||
- 네이버웍스에서 사진이 없으면 `org-context`에서 email 기준 Baron UUID를 찾는다.
|
||||
- UUID가 있으면 `https://baroncs.co.kr/employee_img/{uuid}.jpg` 공개 경로 존재 여부를 확인한다.
|
||||
- 둘 다 없으면 `found=false`, `source=DEFAULT`를 반환한다.
|
||||
|
||||
검증 결과:
|
||||
|
||||
- `go test ./cmd/server` 통과
|
||||
- 로컬 5001 재기동 완료
|
||||
- 무인증 호출 기준 이전 `404 page not found`가 아니라 아래처럼 바뀐 것을 확인했다.
|
||||
|
||||
```json
|
||||
{"error":"unauthorized","message":"앱 세션을 확인하세요."}
|
||||
```
|
||||
|
||||
현재 판단:
|
||||
|
||||
- route 자체는 현재 기동 서버에 복구됐다.
|
||||
- 즉 이전처럼 endpoint 자체가 없는 상태는 아니다.
|
||||
- 다음 실제 확인은 `로그인된 앱 세션` 상태에서 1순위/2순위/3순위 화면 검증으로 넘어가면 된다.
|
||||
|
||||
## 내일 또는 다음 작업 시작 시 우선 순서
|
||||
|
||||
1. `5001 health` 먼저 확인
|
||||
2. `adb reverse --list` 먼저 확인
|
||||
3. 앱에서 `link/init` 로그가 실제로 찍히는지 확인
|
||||
4. 문자 수신 여부를 먼저 확인
|
||||
5. 문자 미수신이면 앱 수정으로 우회하지 말고 Baron SSO 답변 상태부터 확인
|
||||
6. 문자 문제가 외부에서 정리되면 그 다음에 프로필 사진 검증으로 넘어간다
|
||||
|
||||
## 한 줄 요약
|
||||
|
||||
2026-07-20 기준 로그인 막힘의 핵심은 `앱이 요청을 못 보내는 문제`가 아니라 `요청은 정상인데 실제 문자 링크가 사용자에게 도착하지 않는 문제`다.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Daily Handoff Policy
|
||||
|
||||
## 목적
|
||||
|
||||
매일 업무 시작 시 전날 작업 흐름, 남은 이슈, 테스트 상태를 먼저 확인해서 같은 문제를 반복하지 않도록 한다.
|
||||
|
||||
## 필수 규칙
|
||||
|
||||
1. 업무 시작 전 `docs/daily-issues/`의 최신 전일 작업 인계 MD 파일을 먼저 확인한다.
|
||||
2. `scripts/startup.sh`는 런타임 기동 전에 최신 전일 인계 문서를 로그에 출력한다.
|
||||
3. 전일 인계 문서가 없으면 기본적으로 startup을 중단한다.
|
||||
4. 예외 복구 상황에서만 아래 환경값으로 강제 진행할 수 있다.
|
||||
|
||||
```bash
|
||||
TDC114_REQUIRE_DAILY_HANDOFF=false ./scripts/startup.sh --auto --wait=40
|
||||
```
|
||||
|
||||
## 작성 규칙
|
||||
|
||||
오늘 업무 종료 전에는 반드시 아래 내용을 포함한 MD 파일을 남긴다.
|
||||
|
||||
- 오늘 최종 상태
|
||||
- 오늘 발생한 주요 이슈와 원인
|
||||
- 오늘 수정/추가한 파일
|
||||
- 확인 완료한 테스트
|
||||
- 내일 업무 시작 순서
|
||||
- 내일 우선 점검할 항목
|
||||
- 보안상 공유하면 안 되는 값 또는 주의사항
|
||||
|
||||
## 파일명
|
||||
|
||||
```text
|
||||
YYYY-MM-DD_work_handoff.md
|
||||
```
|
||||
|
||||
예:
|
||||
|
||||
```text
|
||||
2026-07-14_work_handoff.md
|
||||
```
|
||||
+17
-2
@@ -145,6 +145,21 @@ lib/
|
||||
6. Gitea Actions 또는 수동 빌드 절차를 정리한다.
|
||||
7. 개발 중간 산출물 기준 APK 배포 방식을 결정한다.
|
||||
|
||||
### 3.8 Android emulator / WSL ADB 연동 기준
|
||||
|
||||
Windows Android Studio emulator를 WSL 또는 Docker 기반 Flutter CLI에서 사용할 때는 별도 ADB 연동 정책을 따른다.
|
||||
|
||||
- 정책 문서: `docs/troubleshooting/policy_android_studio_wsl_adb_2026-07-03.md`
|
||||
- 실행 기록: `docs/troubleshooting/android-studio-wsl-adb-timetable-260703.md`
|
||||
- 통합테스트 시나리오: `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
|
||||
핵심 기준:
|
||||
|
||||
- `adb -a -P 5037 nodaemon server`는 1차 시도만 한다.
|
||||
- `10048` bind 실패가 재현되면 즉시 Windows `portproxy` 방식으로 전환한다.
|
||||
- Android emulator에서 host API는 `127.0.0.1`이 아니라 `10.0.2.2`를 사용한다.
|
||||
- Docker Flutter에서 Windows ADB를 사용할 때는 `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037`을 명시한다.
|
||||
|
||||
## 4. 작업 원칙
|
||||
|
||||
- 1차 개발은 전화번호부/조직도 기본 기능 완성에 집중한다.
|
||||
@@ -158,7 +173,7 @@ lib/
|
||||
|
||||
`tdc114plus` 저장소 골격이 갖춰지면 아래 문서를 복사 이관한다.
|
||||
|
||||
- `docs/tdc114plus-development-decision-brief-2026-07-01.md`
|
||||
- `docs/tdc114plus-development-environment-setup-plan-2026-07-02.md`
|
||||
- `docs/guide_tdc114plus_development_decision_brief_2026-07-01.md`
|
||||
- `docs/dev_env_tdc114plus_setup_plan_2026-07-02.md`
|
||||
|
||||
이관 후 Baron SSO 저장소의 문서는 회의 및 초기 검토 기록으로 보존한다.
|
||||
@@ -0,0 +1,238 @@
|
||||
# Baron Org Context API 연동 참고
|
||||
|
||||
작성일: 2026-07-03
|
||||
|
||||
목적: `tdc114plus` 개발 중 Baron SSO 계열 조직/사용자 데이터를 어떤 API로 조회하는지, 인증 방식은 무엇인지, 실제 호출 예시와 응답 구조는 어떠한지 빠르게 참고할 수 있도록 정리한다.
|
||||
|
||||
## 1. 결론
|
||||
|
||||
`tdc114plus`에서 참고할 Baron 조직도 API는 아래 둘 중 하나처럼 보일 수 있다.
|
||||
|
||||
- 공개 공유링크 방식: `GET /api/v1/public/orgchart?token=...`
|
||||
- API Key 방식: `GET /api/v1/integrations/org-context`
|
||||
|
||||
실제 확인 결과, 팀에서 전달받은 값은 `public/orgchart`용 `token`이 아니라 `integrations/org-context`용 `X-Baron-Key-ID`, `X-Baron-Key-Secret` 조합이다.
|
||||
|
||||
즉 현재 기준의 실제 연동 대상은 아래 API다.
|
||||
|
||||
```http
|
||||
GET https://sadmin.hmac.kr/api/v1/integrations/org-context
|
||||
X-Baron-Key-ID: {key id}
|
||||
X-Baron-Key-Secret: {key secret}
|
||||
```
|
||||
|
||||
2026-07-10 기준:
|
||||
|
||||
- 실제 배포 전까지 Baron SSO API 참고 기준은 staging `https://sadmin.hmac.kr/api/docs#/`다.
|
||||
- Baron SSO가 로그인 성공 후 조직도 API 호출용 ID/Secret을 내려주는 기능은 아직 미개발이다.
|
||||
- 앱은 향후 이 값을 받을 준비를 하되, 현재 개발/검증은 로컬 비추적 env/Dart define에 설정한 staging 고정 키 fallback으로 진행한다.
|
||||
|
||||
## 2. 확인 결과
|
||||
|
||||
실제 테스트 결과:
|
||||
|
||||
- `GET /api/v1/public/orgchart?token={ID}`: `401 Unauthorized`
|
||||
- `GET /api/v1/public/orgchart?token={SECRET}`: `401 Unauthorized`
|
||||
- 응답 body:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "invalid or expired share link",
|
||||
"code": "invalid_session"
|
||||
}
|
||||
```
|
||||
|
||||
- `GET /api/v1/integrations/org-context`에 `X-Baron-Key-ID`, `X-Baron-Key-Secret` header 사용: `200 OK`
|
||||
|
||||
따라서 현재 `tdc114plus`는 공유 링크 token 방식이 아니라 API Key 방식의 `org-context`를 원본 조직/사용자 데이터 소스로 본다.
|
||||
|
||||
## 3. Swagger 문서 위치
|
||||
|
||||
Swagger UI:
|
||||
|
||||
```text
|
||||
https://sadmin.hmac.kr/api/docs#/Integrations/get_api_v1_integrations_org_context
|
||||
```
|
||||
|
||||
OpenAPI YAML:
|
||||
|
||||
```text
|
||||
https://sadmin.hmac.kr/api/openapi.yaml
|
||||
```
|
||||
|
||||
Swagger에서 직접 확인할 때는 우측 상단 `Authorize`에 아래 값을 입력한다.
|
||||
|
||||
- `X-Baron-Key-ID`
|
||||
- `X-Baron-Key-Secret`
|
||||
|
||||
## 4. 호출 방식
|
||||
|
||||
기본 호출 예시:
|
||||
|
||||
```bash
|
||||
curl "https://sadmin.hmac.kr/api/v1/integrations/org-context?tenantSlug=hanmac-family&includeUsers=true&includeUserIds=true" \
|
||||
-H "X-Baron-Key-ID: {KEY_ID}" \
|
||||
-H "X-Baron-Key-Secret: {KEY_SECRET}"
|
||||
```
|
||||
|
||||
주요 query parameter:
|
||||
|
||||
| 이름 | 필수 | 기본값 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `tenantSlug` | N | `hanmac-family` | 조회할 subtree root tenant slug |
|
||||
| `includeUsers` | N | `true` | `false`이면 사용자 목록 없이 조직만 반환 |
|
||||
| `includeUserIds` | N | `false` | `true`이면 사용자 `id`, `phone` 포함 |
|
||||
|
||||
## 5. 응답 구조
|
||||
|
||||
응답 최상위 구조:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "baron.org-context.v1",
|
||||
"issuedAt": "2026-07-03T02:31:37Z",
|
||||
"scope": {
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantSlug": "hanmac-family"
|
||||
},
|
||||
"tree": {
|
||||
"id": "tenant-uuid",
|
||||
"type": "COMPANY_GROUP",
|
||||
"name": "한맥가족",
|
||||
"slug": "hanmac-family",
|
||||
"members": [],
|
||||
"children": []
|
||||
},
|
||||
"tenants": [
|
||||
{
|
||||
"id": "tenant-uuid",
|
||||
"type": "ORGANIZATION",
|
||||
"name": "플랫폼팀",
|
||||
"slug": "platform-team",
|
||||
"parentId": "root-uuid",
|
||||
"status": "active",
|
||||
"memberCount": 3,
|
||||
"members": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
사용자 필드 예시:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"email": "user@example.com",
|
||||
"name": "홍길동",
|
||||
"phone": "+821012345678",
|
||||
"department": "플랫폼팀",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발",
|
||||
"isOwner": false,
|
||||
"isLeader": true,
|
||||
"isPrimary": true
|
||||
}
|
||||
```
|
||||
|
||||
핵심 해석:
|
||||
|
||||
- `tree`: 실제 조직 트리 구조
|
||||
- `tenants`: flatten된 조직 목록
|
||||
- `members`: 각 조직에 직접 소속된 사용자 목록
|
||||
- `memberCount`: 각 조직의 직접 소속 인원 수로 해석
|
||||
- `totalMemberCount`: 응답에서 보장되는 값이 아니므로 앱에서 descendant를 포함해 계산
|
||||
- `scope.tenantSlug`: 이번 조회의 기준 루트 slug
|
||||
|
||||
화면 표시 규칙:
|
||||
|
||||
- 하위조직 카드의 `n명`은 `memberCount`가 아니라 앱이 계산한 `totalMemberCount`를 사용한다.
|
||||
- `totalMemberCount`는 해당 조직 직접 소속 인원과 모든 하위조직 직접 소속 인원을 합산한다.
|
||||
- 자식 조직이 있는 비-leaf 조직에서는 직원 목록보다 하위조직 목록을 우선 표시한다.
|
||||
- 자식 조직이 없는 leaf 조직에 도달했을 때만 해당 leaf의 직접 소속 직원 목록을 표시한다.
|
||||
- leaf 조직의 직접 소속 인원이 0명이면 `검색 결과 없음`이 정상일 수 있다.
|
||||
|
||||
## 6. 보안 및 저장 위치
|
||||
|
||||
이 API는 query parameter가 아니라 header 인증을 사용한다.
|
||||
|
||||
```http
|
||||
X-Baron-Key-ID
|
||||
X-Baron-Key-Secret
|
||||
```
|
||||
|
||||
따라서 다음 원칙을 지킨다.
|
||||
|
||||
- tracked 모바일 Flutter 앱 소스와 tracked 문서에 실제 키를 넣지 않는다.
|
||||
- 브라우저 주소창 query string으로 시크릿을 넣지 않는다.
|
||||
- Baron SSO backend, 별도 서버, 또는 개발자 로컬 비추적 env/Dart define에만 저장한다.
|
||||
- 실제 키 값은 저장소 tracked 파일에 커밋하지 않는다.
|
||||
- 운영 배포 전에는 로그인 성공 후 받은 session credential 또는 안전한 서버 중계 구조로 전환한다.
|
||||
|
||||
현재 로컬 Baron SSO worktree에서는 아래 환경변수 이름으로 정리했다.
|
||||
|
||||
```env
|
||||
TDC114PLUS_ORG_CONTEXT_BASE_URL=https://sadmin.hmac.kr
|
||||
TDC114PLUS_ORG_CONTEXT_KEY_ID=
|
||||
TDC114PLUS_ORG_CONTEXT_KEY_SECRET=
|
||||
TDC114PLUS_ORG_CONTEXT_TENANT_SLUG=hanmac-family
|
||||
TDC114PLUS_ORG_CONTEXT_INCLUDE_USERS=true
|
||||
TDC114PLUS_ORG_CONTEXT_INCLUDE_USER_IDS=true
|
||||
```
|
||||
|
||||
로컬 반영 위치:
|
||||
|
||||
- Baron SSO API worktree: `/home/ubuntu/workspace/baron-sso-tdc114plus-api/.env`
|
||||
|
||||
## 7. tdc114plus 반영 상태
|
||||
|
||||
2026-07-03 기준 반영 상태:
|
||||
|
||||
- 이 문서의 기준 API는 Baron 원본 `org-context`다.
|
||||
- 앱 코드와 문서에 남아 있는 `tdc114plus` 전용 endpoint 가정은 레거시 흔적이며, 신규 정책의 공식 기준이 아니다.
|
||||
|
||||
현재 구현 동작:
|
||||
|
||||
- 외부 `org-context` 호출 성공 시: 외부 조직/사용자 응답을 앱 내부 DTO로 매핑
|
||||
- 환경변수 미설정 시: 기존 로컬 fallback 동작이 남아 있을 수 있으므로 단계적 제거 대상이다
|
||||
|
||||
현재 매핑 결과:
|
||||
|
||||
- `tenants`는 `org-context`의 tenant 목록 기준
|
||||
- `employees`는 각 tenant `members` 기준
|
||||
- 중복 사용자는 `id`, `email`, `phone`, `name` 순으로 dedupe
|
||||
- `cache.source`는 외부 연동일 때 `org-context`
|
||||
|
||||
## 8. 브라우저 확인 방법
|
||||
|
||||
브라우저 주소창만으로는 header를 넣을 수 없으므로 직접 호출은 불가능하다.
|
||||
|
||||
확인 방법:
|
||||
|
||||
1. Swagger UI에서 `Authorize` 사용
|
||||
2. 브라우저 개발자도구 console에서 `fetch` 사용
|
||||
3. 터미널에서 `curl` 사용
|
||||
|
||||
예시 `fetch`:
|
||||
|
||||
```js
|
||||
fetch("https://sadmin.hmac.kr/api/v1/integrations/org-context?tenantSlug=hanmac-family&includeUsers=true&includeUserIds=true", {
|
||||
headers: {
|
||||
"X-Baron-Key-ID": "YOUR_KEY_ID",
|
||||
"X-Baron-Key-Secret": "YOUR_KEY_SECRET"
|
||||
}
|
||||
}).then(r => r.json()).then(console.log)
|
||||
```
|
||||
|
||||
## 10. 운영 전환 메모
|
||||
|
||||
- 2026-07-10부터 팀장 지시에 따라 신규 앱 개발 시 Baron 원본 참고 API는 production host가 아니라 staging host `https://sadmin.hmac.kr/` 기준으로 다시 본다.
|
||||
- 운영 키(`CLIENT ID`, `X-Baron-Key-Secret`)는 회전될 수 있으므로 tracked 문서에 박아두지 않고 로컬 비추적 `.env`에만 보관한다.
|
||||
|
||||
## 9. 후속 작업 메모
|
||||
|
||||
- 앱 내부 직원검색 모델
|
||||
- 앱 내부 직원상세 모델
|
||||
|
||||
현재 이 두 경로는 기존 로컬 DB 기반이며, 조직도와 동일한 외부 `org-context` 소스로 완전히 통일할지는 후속 판단이 필요하다.
|
||||
@@ -0,0 +1,153 @@
|
||||
# Baron SSO org-context identity mirror 복구 요청 문서
|
||||
|
||||
작성일: 2026-07-03
|
||||
|
||||
목적: `tdc114plus` 앱의 직원검색/조직도 API가 외부 Baron SSO `org-context` 사용자 데이터를 정상적으로 조회할 수 있도록, Baron SSO 담당 개발자에게 현재 장애 상태와 필요한 조치 사항을 명확히 전달하기 위한 요청 문서다.
|
||||
|
||||
## 1. 요청 요약
|
||||
|
||||
현재 `tdc114plus` 연동 경로에서 Baron SSO 외부 `org-context` API의 조직 트리 조회는 가능하지만, 사용자 포함 조회가 아래 오류로 실패하고 있다.
|
||||
|
||||
```json
|
||||
{"error":"identity mirror is not ready","code":"internal_error"}
|
||||
```
|
||||
|
||||
따라서 Baron SSO 원본 서비스 `sadmin.hmac.kr` 측에서 `org-context` 사용자 조회에 필요한 identity mirror를 `ready` 상태로 복구하거나 재구성해 주는 조치가 필요하다.
|
||||
|
||||
## 2. 요청 목적
|
||||
|
||||
이번 요청의 목적은 아래와 같다.
|
||||
|
||||
- `tdc114plus`가 Baron backend를 통해 한맥가족 전체 직원 데이터를 정상 조회할 수 있도록 함
|
||||
- 앱의 직원검색/조직도 데이터 소스를 `org-context` 기준으로 안정화
|
||||
|
||||
즉 외부 `org-context` 원본 사용자 데이터를 기준으로 앱 내부 데이터 구성이 가능하도록 복구함
|
||||
|
||||
## 3. 현재 확인된 사실
|
||||
|
||||
### 3-1. 인증 정보 자체는 정상
|
||||
|
||||
- 팀에서 전달받은 값은 `public/orgchart?token=...`용 token이 아니라 `GET /api/v1/integrations/org-context`용 API Key이다.
|
||||
- 로컬 Baron SSO API worktree `.env`에는 아래 값이 반영되어 있다.
|
||||
- `TDC114PLUS_ORG_CONTEXT_BASE_URL`
|
||||
- `TDC114PLUS_ORG_CONTEXT_KEY_ID`
|
||||
- `TDC114PLUS_ORG_CONTEXT_KEY_SECRET`
|
||||
- `TDC114PLUS_ORG_CONTEXT_TENANT_SLUG=hanmac-family`
|
||||
- `TDC114PLUS_ORG_CONTEXT_INCLUDE_USERS=true`
|
||||
- `TDC114PLUS_ORG_CONTEXT_INCLUDE_USER_IDS=true`
|
||||
|
||||
### 3-2. 로컬 Baron backend 최신 코드/환경 반영은 확인
|
||||
|
||||
- `tdc114plus` 연동 handler는 외부 `org-context`를 우선 사용하도록 이미 반영했다.
|
||||
- `baron_backend` 컨테이너 rebuild/recreate 후 실행 중 env에도 `TDC114PLUS_ORG_CONTEXT_*` 값이 주입된 것을 확인했다.
|
||||
|
||||
### 3-3. 현재 실제 장애 양상
|
||||
|
||||
외부 API를 직접 확인한 결과는 아래와 같다.
|
||||
|
||||
1. `includeUsers=false`
|
||||
|
||||
- 요청:
|
||||
- `GET /api/v1/integrations/org-context?tenantSlug=hanmac-family&includeUsers=false&includeUserIds=false`
|
||||
- 결과:
|
||||
- `200 OK`
|
||||
- 해석:
|
||||
- 조직 트리/tenant 구조 자체는 조회 가능
|
||||
|
||||
2. `includeUsers=true`
|
||||
|
||||
- 요청:
|
||||
- `GET /api/v1/integrations/org-context?tenantSlug=hanmac-family&includeUsers=true&includeUserIds=true`
|
||||
- 결과:
|
||||
- `500 Internal Server Error`
|
||||
- 응답:
|
||||
|
||||
```json
|
||||
{"error":"identity mirror is not ready","code":"internal_error"}
|
||||
```
|
||||
|
||||
- 해석:
|
||||
- 사용자 포함 `org-context` 조회 시 Baron SSO 원본 서비스 쪽 identity mirror가 준비되지 않아 실패
|
||||
|
||||
### 3-4. tdc114plus에서 보이는 영향
|
||||
|
||||
- `baron_backend` 최신 코드 반영 후 앱 연동 직원조회 경로는 `503 dependency_unavailable`로 실패
|
||||
- backend 로그:
|
||||
|
||||
```text
|
||||
[Tdc114Plus] external org-context employee load failed error="org-context status 500"
|
||||
```
|
||||
|
||||
- 즉, 현재 `tdc114plus`는 외부 사용자 org-context를 쓰려 하지만 원본 서비스가 `500`을 반환해 앱에서 전체 직원 정보를 검증할 수 없는 상태다.
|
||||
|
||||
## 4. Baron SSO 담당 개발자에게 요청할 내용
|
||||
|
||||
아래 내용을 요청한다.
|
||||
|
||||
1. `sadmin.hmac.kr`의 `GET /api/v1/integrations/org-context`에서 `includeUsers=true` 요청이 정상적으로 동작하도록 복구해 달라.
|
||||
2. 현재 `identity mirror is not ready`가 발생하는 원인을 확인해 달라.
|
||||
3. 필요한 경우 Kratos 기준 identity mirror warmup/full rebuild/recovery/reconciliation 작업을 수행해 달라.
|
||||
4. 복구 후 아래 조건으로 재검증해 달라.
|
||||
- `tenantSlug=hanmac-family`
|
||||
- `includeUsers=true`
|
||||
- `includeUserIds=true`
|
||||
5. 복구 완료 후 응답이 `200 OK`로 내려오고, `tenants[].members`에 실제 사용자 데이터가 포함되는지 확인해 달라.
|
||||
|
||||
## 5. Baron SSO 쪽에서 필요한 처리 방향
|
||||
|
||||
현재 코드/운영 정책 문서 기준으로 예상되는 처리 방향은 아래와 같다.
|
||||
|
||||
1. `sadmin.hmac.kr` 원본 backend 로그에서 identity mirror warmup 실패 여부 확인
|
||||
2. Redis identity mirror 상태 확인
|
||||
- `identity:mirror:state`
|
||||
3. Kratos Admin 연결/조회 가능 상태 확인
|
||||
4. identity mirror warmup 또는 full rebuild 수행
|
||||
5. 필요 시 repair / reconciliation / drift report 수행
|
||||
6. 복구 후 `includeUsers=true` org-context 재검증
|
||||
|
||||
코드상 참고 포인트:
|
||||
|
||||
- 서버 시작 시 identity mirror warmup 수행 경로:
|
||||
- `backend/cmd/server/main.go`
|
||||
- identity mirror rebuild 경로:
|
||||
- `backend/internal/handler/user_handler.go`
|
||||
- org-context member export가 identity mirror 상태를 사용한다는 점:
|
||||
- `backend/internal/handler/tenant_handler.go`
|
||||
|
||||
## 6. 이 요청이 처리되면 바로 이어서 가능한 작업
|
||||
|
||||
Baron SSO 쪽 복구가 완료되면 `tdc114plus` 쪽에서는 아래 작업을 바로 이어서 진행할 수 있다.
|
||||
|
||||
1. 앱 연동 조직도 데이터가 `cache.source=org-context`로 전환됐는지 확인
|
||||
2. 앱 연동 직원검색 데이터가 한맥가족 전체 직원 데이터를 반환하는지 검증
|
||||
3. 앱 연동 직원상세 데이터가 외부 사용자 id 기준으로 정상 조회되는지 검증
|
||||
4. 중복 사용자, 다중 소속, tenant 없는 사용자 처리 정책 재점검
|
||||
5. Flutter 앱에서 직원검색/조직도 실데이터 진입 검증
|
||||
|
||||
## 7. 요청 결과가 성공일 때의 완료 기준
|
||||
|
||||
아래 조건이 만족되면 이번 요청이 해결된 것으로 본다.
|
||||
|
||||
- `GET /api/v1/integrations/org-context?tenantSlug=hanmac-family&includeUsers=true&includeUserIds=true`
|
||||
- `200 OK`
|
||||
- 응답 body에 `tenants[].members[]` 실제 사용자 데이터가 포함됨
|
||||
- `tdc114plus` 앱 연동 데이터가 `org-context` 기준으로 정상 구성됨
|
||||
|
||||
## 8. 전달용 짧은 요청 문안
|
||||
|
||||
아래 문안을 Baron SSO 담당 개발자에게 전달하면 된다.
|
||||
|
||||
```text
|
||||
tdc114plus 연동 중 Baron org-context 사용자 포함 조회가 실패하고 있습니다.
|
||||
|
||||
- tenantSlug=hanmac-family
|
||||
- includeUsers=false: 200 OK
|
||||
- includeUsers=true: 500 {"error":"identity mirror is not ready","code":"internal_error"}
|
||||
|
||||
로컬 Baron backend 최신 코드와 org-context env 반영까지는 확인했습니다.
|
||||
현재는 sadmin.hmac.kr 원본 org-context의 identity mirror가 ready가 아니어서
|
||||
tdc114plus의 직원검색/조직도 사용자 조회가 막혀 있습니다.
|
||||
|
||||
org-context 사용자 조회에 필요한 identity mirror warmup / rebuild / recovery를 확인해 주시고,
|
||||
복구 후 includeUsers=true 요청이 200으로 내려오도록 조치 부탁드립니다.
|
||||
```
|
||||
@@ -0,0 +1,411 @@
|
||||
# 신규앱과 Baron SSO 연동 쉬운 설명
|
||||
|
||||
작성일: 2026-07-08
|
||||
상태: 초안 v1
|
||||
|
||||
목적: 신규앱과 Baron SSO의 관계, 데이터 연동 방식, Hosted Login + PKCE 로그인, 모바일 배포 형태를 다른 팀원도 쉽게 이해할 수 있게 설명한다.
|
||||
|
||||
관련 근거:
|
||||
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
- `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`
|
||||
- `docs/scenario_staging_baron_sso_login_verification_2026-07-06.md`
|
||||
- `docs/policy_android_app_install_execution_2026-07-06.md`
|
||||
- `app/lib/src/features/auth/data/auth_api_client.dart`
|
||||
- `app/lib/src/features/auth/domain/auth_models.dart`
|
||||
- `app/lib/src/features/auth/data/auth_repository.dart`
|
||||
|
||||
## 1. 한 줄 요약
|
||||
|
||||
`tdc114plus` 신규앱은 Baron SSO 자체가 아니라, Baron SSO를 로그인/사용자정보/조직정보 제공자로 사용하는 별도의 모바일 앱이다.
|
||||
|
||||
쉽게 말하면:
|
||||
|
||||
- 신규앱 = 사용자가 설치해서 실행하는 앱
|
||||
- Baron SSO = 로그인과 사용자/조직 데이터를 제공하는 서버
|
||||
- 두 시스템은 API로 데이터를 주고받는다
|
||||
|
||||
## 2. 신규앱과 Baron SSO의 관계
|
||||
|
||||
### 2.1 무엇이 누구인가
|
||||
|
||||
- 신규앱은 Flutter로 만든 Android/iOS 공통 모바일 앱이다.
|
||||
- Baron SSO는 사용자 인증과 조직/직원 데이터를 관리하는 서버 쪽 시스템이다.
|
||||
- 신규앱은 Baron SSO에 등록되는 별도 `RP(Relying Party)`로 본다.
|
||||
|
||||
여기서 `RP`는 쉽게 말하면:
|
||||
|
||||
- "SSO를 믿고 로그인 기능을 맡기는 서비스"
|
||||
- 즉, 로그인 자체를 새로 만들지 않고 Baron SSO를 통해 인증받는 앱
|
||||
|
||||
그래서 신규앱은 Baron SSO의 일부 화면이 아니라, Baron SSO를 사용하는 별도 서비스라고 이해하면 된다.
|
||||
|
||||
## 3. 설치되는 앱 실행파일은 무엇인가
|
||||
|
||||
### 3.1 Android
|
||||
|
||||
Android에서 실제 기기에 설치되는 파일은 보통 아래 둘 중 하나다.
|
||||
|
||||
- `APK`
|
||||
- `AAB`에서 스토어가 기기별로 풀어 배포한 설치 패키지
|
||||
|
||||
개발/테스트 단계에서는 보통:
|
||||
|
||||
- `flutter run`
|
||||
- debug `APK`
|
||||
|
||||
를 사용한다.
|
||||
|
||||
운영 배포 관점에서는 보통:
|
||||
|
||||
- 사내 직접 배포면 `APK`
|
||||
- Play Store 배포면 `AAB`
|
||||
|
||||
형태를 생각하면 된다.
|
||||
|
||||
현재 저장소 문맥상 Android 테스트에서는 debug APK를 직접 깔 수도 있지만, 기능 검증은 `flutter run` 중심으로 하도록 정책이 잡혀 있다. 이유는 이 앱이 실행 시점에 `TDC114_API_BASE` 같은 환경값을 함께 받아야 하기 때문이다.
|
||||
|
||||
### 3.2 iOS
|
||||
|
||||
iOS에서 실제 설치/배포에 쓰이는 것은 보통:
|
||||
|
||||
- 개발기기 설치용 app bundle
|
||||
- TestFlight/App Store 배포용 `IPA`
|
||||
|
||||
라고 보면 된다.
|
||||
|
||||
즉 정리하면:
|
||||
|
||||
- Android는 주로 `APK` 또는 스토어용 `AAB`
|
||||
- iOS는 주로 `IPA` 또는 TestFlight/App Store 배포
|
||||
|
||||
다.
|
||||
|
||||
## 4. 앱 실행파일 자체가 RP인가
|
||||
|
||||
이 질문은 자주 헷갈릴 수 있는데, 가장 쉬운 답은 아래와 같다.
|
||||
|
||||
- "앱 실행파일 그 자체"를 좁게 보면 그냥 설치 패키지다.
|
||||
- 하지만 "그 앱 서비스 전체"를 넓게 보면 Baron SSO 입장에서는 하나의 `RP`다.
|
||||
|
||||
즉:
|
||||
|
||||
- `APK`, `IPA`는 설치물이다.
|
||||
- 그 설치물을 통해 동작하는 `tdc114plus` 앱 서비스가 Baron SSO에 연동되는 `RP`다.
|
||||
|
||||
따라서 팀 내 설명에서는 아래처럼 말하면 가장 덜 헷갈린다.
|
||||
|
||||
`tdc114plus` 모바일 앱은 Baron SSO에 등록된 별도 RP이며, 사용자는 Android/iOS 기기에 그 RP의 클라이언트 앱을 설치해 사용한다.
|
||||
|
||||
## 5. 앱이 설치된 뒤 실제로 어떻게 동작하는가
|
||||
|
||||
네, 큰 흐름은 아래 이해가 맞다.
|
||||
|
||||
1. 사용자가 각 모바일 디바이스에 신규앱을 설치한다.
|
||||
2. 사용자가 앱을 실행한다.
|
||||
3. 앱은 Baron SSO authorization endpoint를 브라우저/커스텀탭으로 연다.
|
||||
4. Baron SSO Hosted Login 화면에서 휴대폰번호 입력과 문자/메일 링크 인증을 처리한다.
|
||||
5. 인증 완료 후 Baron SSO가 `https://114.hmac.kr/auth/callback`으로 authorization code를 돌려준다.
|
||||
6. 앱은 PKCE `code_verifier`로 token을 교환하고 세션을 저장한다.
|
||||
7. 앱은 그 세션으로 직원검색, 조직도, 사용자 표시 정보를 다시 조회한다.
|
||||
8. 앱 화면은 Baron SSO가 준 로그인 결과와 조직/직원 데이터를 사용자에게 보여준다.
|
||||
|
||||
즉, "설치된 실행파일이 Baron SSO와 데이터를 주고받으면서 로그인과 표시 내용을 가져온다"는 이해는 맞다.
|
||||
|
||||
다만 더 정확히 말하면:
|
||||
|
||||
- 로그인 결과 일부는 앱 내부에 저장된다
|
||||
- 이후 필요한 화면 데이터는 Baron SSO 연동 API를 다시 호출해서 가져온다
|
||||
|
||||
## 6. 어떤 데이터들을 주고받는가
|
||||
|
||||
## 6.1 로그인 시작 시 앱 -> Baron SSO
|
||||
|
||||
신규앱은 로그인 시작 시 headless API를 직접 호출하지 않는다.
|
||||
앱은 PKCE 값을 만든 뒤 Baron SSO Hosted Login 화면을 연다.
|
||||
|
||||
```http
|
||||
GET https://sso.hmac.kr/oidc/oauth2/auth
|
||||
```
|
||||
|
||||
주요 query:
|
||||
|
||||
```text
|
||||
client_id=tdc114plus-rp-client-id
|
||||
redirect_uri=https://114.hmac.kr/auth/callback
|
||||
response_type=code
|
||||
scope=openid profile email tenants
|
||||
state=random-state
|
||||
nonce=random-nonce
|
||||
code_challenge=S256-code-challenge
|
||||
code_challenge_method=S256
|
||||
```
|
||||
|
||||
의미:
|
||||
|
||||
- `client_id`: Baron SSO에 등록된 TDC114PLUS RP 식별자
|
||||
- `redirect_uri`: 인증 후 앱으로 돌아오기 위한 App Link 주소
|
||||
- `state`: callback 위조를 막기 위한 임시 검증값
|
||||
- `code_challenge`: 앱이 가진 `code_verifier`를 해시한 PKCE 값
|
||||
|
||||
즉 앱은 "로그인 화면을 직접 만들지 않고", Baron SSO가 제공하는 로그인 화면으로 사용자를 보낸다.
|
||||
|
||||
## 6.2 Baron SSO Hosted Login 화면
|
||||
|
||||
휴대폰번호 입력, 문자/메일 링크 발송, 링크 승인 여부 확인은 Baron SSO 화면과 서버가 처리한다.
|
||||
|
||||
앱은 아래 정보를 직접 다루지 않는다.
|
||||
|
||||
- 휴대폰번호 인증 UI
|
||||
- 승인 링크 생성
|
||||
- `client_assertion`
|
||||
- RP 개인키 또는 client secret
|
||||
- headless `pendingRef` polling
|
||||
|
||||
이렇게 해야 공개 모바일 앱에 비밀키를 넣지 않는 PKCE 보안 모델과 맞다.
|
||||
|
||||
## 6.3 인증 완료 callback
|
||||
|
||||
인증이 끝나면 Baron SSO는 등록된 redirect URI로 이동한다.
|
||||
|
||||
```http
|
||||
GET https://114.hmac.kr/auth/callback?code={authorization-code}&state={state}
|
||||
```
|
||||
|
||||
앱은 Android App Link 또는 iOS Universal Link 설정을 통해 이 URL을 받아야 한다.
|
||||
|
||||
앱에서 확인할 것:
|
||||
|
||||
- callback의 `state`가 앱이 저장한 값과 같은지
|
||||
- `code`가 존재하는지
|
||||
- 오류 파라미터가 있으면 token 교환을 중단할지
|
||||
|
||||
## 6.4 token 교환
|
||||
|
||||
앱은 callback으로 받은 authorization code를 token endpoint에 보낸다.
|
||||
|
||||
```http
|
||||
POST https://sso.hmac.kr/oidc/oauth2/token
|
||||
```
|
||||
|
||||
요청 핵심:
|
||||
|
||||
```text
|
||||
grant_type=authorization_code
|
||||
client_id=tdc114plus-rp-client-id
|
||||
code={authorization-code}
|
||||
code_verifier={stored-code-verifier}
|
||||
redirect_uri=https://114.hmac.kr/auth/callback
|
||||
```
|
||||
|
||||
중요:
|
||||
|
||||
- PKCE 공개 앱이므로 client secret을 보내지 않는다.
|
||||
- 앱이 처음 만든 `code_verifier`가 있어야 token 교환이 성공한다.
|
||||
- token 교환 성공 후 앱은 access token, 만료시간, 사용자 기본 정보를 저장한다.
|
||||
|
||||
## 6.5 로그인 완료 후 앱 세션
|
||||
|
||||
token 교환이 성공하면 앱은 아래 정보를 세션으로 보관한다.
|
||||
|
||||
- access token
|
||||
- 만료시간
|
||||
- id token 또는 userinfo에서 얻은 사용자 기본 정보
|
||||
|
||||
이 사용자 정보는 아래처럼 쓰인다.
|
||||
|
||||
- `name`: 화면에 보여줄 사용자명
|
||||
- `tenantName`, `tenantSlug`: 어느 회사/테넌트 소속인지
|
||||
- `department`: 본인 부서
|
||||
- `grade`, `position`, `jobTitle`: 직급/직위/직무
|
||||
|
||||
## 6.6 로그인 후 조회하는 업무 데이터
|
||||
|
||||
로그인 후에는 아래 같은 업무 데이터를 Baron SSO 연동 API에서 조회한다.
|
||||
|
||||
- 직원 목록
|
||||
- 조직/가족사 목록
|
||||
- 조직도
|
||||
- 직원 상세 정보
|
||||
|
||||
현재 기준 원본 조회 API 메모:
|
||||
|
||||
- `GET /api/v1/integrations/org-context`
|
||||
- `GET /api/v1/public/orgchart`
|
||||
|
||||
레거시 `/api/v1/tdc114plus/...` 데이터 경로는 과거 흔적으로만 보고 단계적으로 제거한다.
|
||||
|
||||
문서 기준 주요 데이터 API는 아래와 같다.
|
||||
|
||||
- `GET /api/v1/integrations/org-context`
|
||||
- `GET /api/v1/public/orgchart`
|
||||
|
||||
즉 Baron SSO는 로그인만 해주는 것이 아니라, 앱이 필요한 직원/조직 데이터도 함께 제공하는 역할을 한다.
|
||||
|
||||
## 7. 데이터 형식은 무엇인가
|
||||
|
||||
기본 형식은 HTTP + JSON 이다.
|
||||
|
||||
조금 더 풀면:
|
||||
|
||||
- 통신 방식: 모바일 앱이 HTTPS API 호출
|
||||
- 요청 본문 형식: JSON
|
||||
- 응답 본문 형식: JSON
|
||||
- 헤더: 보통 `Content-Type: application/json`, `Accept: application/json`
|
||||
|
||||
즉 이 앱은 웹페이지를 긁어오는 방식이 아니라, 구조화된 JSON API를 호출해서 데이터를 받는다.
|
||||
|
||||
## 8. 세션은 앱 안에 어떻게 저장되는가
|
||||
|
||||
코드상 현재 앱은 로그인 성공 시 아래 정보를 저장한다.
|
||||
|
||||
- `token`
|
||||
- `expiresAt`
|
||||
- `user`
|
||||
|
||||
저장 위치는 앱 내부 저장소(`SharedPreferences`)다.
|
||||
|
||||
그래서 앱을 다시 켰을 때:
|
||||
|
||||
- 저장된 세션이 아직 유효하면 로그인 화면을 건너뛴다
|
||||
- 세션이 없거나 만료되면 다시 Baron SSO 로그인으로 보낸다
|
||||
|
||||
즉 앱은 매 화면마다 처음부터 새 로그인하는 것이 아니라, 받은 세션을 보관했다가 재사용한다.
|
||||
|
||||
## 9. 헤드리스 로그인(headless login)은 무엇이고, 왜 기본 방식이 아닌가
|
||||
|
||||
가장 쉬운 설명부터 하면:
|
||||
|
||||
헤드리스 로그인은 "앱 안에 Baron SSO의 로그인 웹화면을 직접 띄우지 않고, 앱이 API로 로그인 절차를 진행하는 방식"이다.
|
||||
|
||||
`headless`를 직역하면 "머리/화면이 없는" 느낌인데, 여기서는:
|
||||
|
||||
- 로그인용 별도 웹페이지 중심이 아니라
|
||||
- 백그라운드 API 호출 중심으로 로그인 절차를 진행한다
|
||||
|
||||
는 뜻으로 이해하면 된다.
|
||||
|
||||
다만 현재 TDC114PLUS 기본 로그인 방식은 headless가 아니다.
|
||||
현재 기준은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`다.
|
||||
|
||||
이유는 간단하다.
|
||||
|
||||
- Flutter 모바일 앱은 공개 클라이언트라서 비밀키를 안전하게 숨길 수 없다.
|
||||
- Baron Swagger의 headless API는 `client_assertion` 같은 confidential client 성격의 값을 요구한다.
|
||||
- 앱이 headless API를 직접 호출하려면 APK 안에 비밀값 또는 개인키를 넣는 위험한 구조가 될 수 있다.
|
||||
- Hosted Login + PKCE는 모바일 앱 표준 보안 모델과 더 잘 맞는다.
|
||||
|
||||
## 10. 이번 신규앱 로그인은 왜 특별한가
|
||||
|
||||
이번 신규앱 기본 로그인은 단순한 "전화번호 넣고 바로 로그인"이 아니다.
|
||||
|
||||
흐름은 아래와 같다.
|
||||
|
||||
1. 앱이 Baron SSO Hosted Login 화면을 브라우저/커스텀탭으로 연다.
|
||||
2. 사용자가 Baron SSO 화면에서 휴대폰번호를 입력한다.
|
||||
3. Baron SSO가 문자 또는 메일로 승인 링크를 발송한다.
|
||||
4. 사용자가 그 링크를 열어 승인한다.
|
||||
5. Baron SSO가 `https://114.hmac.kr/auth/callback`으로 authorization code를 돌려준다.
|
||||
6. 앱이 PKCE 방식으로 token을 교환한다.
|
||||
7. 앱이 세션 저장 후 첫 화면으로 진입한다.
|
||||
|
||||
즉 핵심은:
|
||||
|
||||
- 앱은 로그인 화면을 직접 구현하지 않는다.
|
||||
- 휴대폰번호 입력과 링크 승인은 Baron SSO가 맡는다.
|
||||
- 앱은 callback code를 받아 PKCE token 교환만 수행한다.
|
||||
|
||||
이다.
|
||||
|
||||
## 11. 왜 굳이 Hosted Login + PKCE로 하나
|
||||
|
||||
장점은 아래처럼 설명할 수 있다.
|
||||
|
||||
- 앱이 비밀번호, 휴대폰번호 인증 로직, 승인 링크를 직접 만지지 않는다.
|
||||
- Baron SSO가 인증 UI와 인증 절차를 책임진다.
|
||||
- 앱에는 client secret이나 개인키를 넣지 않아도 된다.
|
||||
- Android/iOS 모두 표준 OIDC + PKCE 방식으로 확장하기 쉽다.
|
||||
- 로그인 정책이 바뀌어도 Baron SSO Hosted Login 쪽을 중심으로 바꾸면 된다.
|
||||
|
||||
하지만 주의할 점도 있다.
|
||||
|
||||
- 앱 코드만 있다고 로그인 검증이 끝나지 않는다.
|
||||
- Baron SSO RP 등록, redirect URI, App Link, PKCE token endpoint가 모두 맞아야 한다.
|
||||
- staging/운영 환경에서 실제 테스트 번호와 링크 수신 경로가 맞아야 end-to-end 검증이 된다.
|
||||
|
||||
## 12. Hosted Login + PKCE와 headless 방식 차이
|
||||
|
||||
Hosted Login + PKCE:
|
||||
|
||||
1. 로그인 페이지로 이동
|
||||
2. Baron SSO 화면에서 인증수단 입력
|
||||
3. 문자/메일 링크 승인
|
||||
4. App Link callback으로 앱 복귀
|
||||
5. PKCE token 교환
|
||||
6. 로그인 완료
|
||||
|
||||
headless 직접 호출:
|
||||
|
||||
1. 앱 화면에서 전화번호 입력
|
||||
2. 앱이 API 호출
|
||||
3. 사용자는 외부로 받은 링크를 열어 승인
|
||||
4. 앱은 API로 상태를 확인
|
||||
5. 완료되면 앱이 세션을 저장
|
||||
|
||||
현재 앱 기본 정책은 첫 번째, 즉 Hosted Login + PKCE다.
|
||||
headless 직접 호출은 별도 신뢰 백엔드가 생기거나 Baron SSO가 모바일 공개 RP용 계약을 제공할 때만 재검토한다.
|
||||
|
||||
## 13. "전화번호만 넣으면 바로 로그인"과 같은가
|
||||
|
||||
아니다. 이번 기본 흐름은 그것과 다르다.
|
||||
|
||||
이번 기본 흐름은:
|
||||
|
||||
- Baron SSO 로그인 화면 진입
|
||||
- 전화번호 입력
|
||||
- 링크 발송
|
||||
- 사용자 승인
|
||||
- App Link callback
|
||||
- PKCE token 교환 후 세션 발급
|
||||
|
||||
이다.
|
||||
|
||||
즉 전화번호 입력만으로 즉시 로그인시키는 구조가 아니라, 승인 단계를 끼운 비동기 로그인 구조다.
|
||||
|
||||
## 14. 팀원들이 가장 헷갈리지 않게 설명하는 표현
|
||||
|
||||
아래 표현을 권장한다.
|
||||
|
||||
`tdc114plus`는 Baron SSO에 등록된 별도 모바일 RP 앱이다. 사용자는 Android나 iPhone에 앱을 설치하고, 앱은 Baron SSO Hosted Login 화면을 브라우저/커스텀탭으로 열어 로그인한다. 전화번호 입력과 문자/메일 링크 승인은 Baron SSO 화면과 서버가 처리하며, 인증 완료 뒤 `https://114.hmac.kr/auth/callback` App Link로 앱에 돌아온다. 앱은 callback의 authorization code를 PKCE 방식으로 token 교환한 뒤 직원검색/조직도 같은 데이터를 Baron SSO 연동 API에서 조회해 화면에 표시한다.
|
||||
|
||||
## 15. 자주 나오는 질문에 대한 짧은 답
|
||||
|
||||
### Q1. 신규앱은 Baron SSO 안에 들어가는가
|
||||
|
||||
아니라기보다, Baron SSO를 사용하는 별도 앱이다.
|
||||
|
||||
### Q2. 앱 실행파일 자체가 RP인가
|
||||
|
||||
설치파일 자체보다는, 그 설치파일로 동작하는 앱 서비스 전체를 RP라고 보는 것이 더 정확하다.
|
||||
|
||||
### Q3. Android는 APK로 배포하는가
|
||||
|
||||
개발/사내 배포는 APK가 가능하고, 스토어 배포는 보통 AAB를 사용한다.
|
||||
|
||||
### Q4. iOS는 APK처럼 설치하는가
|
||||
|
||||
아니다. 보통 IPA 또는 TestFlight/App Store 방식이다.
|
||||
|
||||
### Q5. 앱이 설치된 뒤 Baron SSO와 계속 통신하는가
|
||||
|
||||
그렇다. 로그인할 때도 통신하고, 로그인 후 직원/조직 데이터를 가져올 때도 통신한다.
|
||||
|
||||
### Q6. 헤드리스 로그인은 화면이 아예 없다는 뜻인가
|
||||
|
||||
아니다. 사용자 화면은 있을 수 있다. 다만 현재 TDC114PLUS 기본 방식은 headless가 아니라 Baron SSO Hosted Login 화면을 브라우저/커스텀탭으로 여는 방식이다.
|
||||
|
||||
## 16. 결론
|
||||
|
||||
이번 신규앱은 단말에 설치되는 일반 모바일 앱이지만, 인증과 주요 사용자/조직 데이터는 Baron SSO와의 API 연동에 의존한다. 따라서 이 앱은 "독립 실행은 되지만 독립 인증은 하지 않는 RP 앱"이라고 이해하면 가장 정확하다.
|
||||
|
||||
또한 이번 로그인은 단순 즉시 로그인 방식이 아니라 `Hosted Login -> 문자/메일 링크 인증 -> App Link callback -> PKCE token 교환 -> 세션 저장` 흐름이다. 그래서 앱 실행파일만 설치되었다고 끝나는 것이 아니라, Baron SSO RP 설정, callback 도메인, App Link, token 교환이 함께 정상 동작해야 비로소 로그인과 첫 화면 진입이 완성된다.
|
||||
@@ -0,0 +1,571 @@
|
||||
# 신규어플 부서 대시보드 입력용 프로젝트/업무계획 정리
|
||||
|
||||
작성일: 2026-07-14
|
||||
용도: 부서 대시보드의 `기본정보`, `업무 계획`, `업무 관리`, `로드맵`, `변경사항` 입력용 초안
|
||||
|
||||
## 0. 캡처 화면 기준 빠른 입력 매칭표
|
||||
|
||||
캡처에 보이는 입력 항목명을 기준으로 바로 매칭했다.
|
||||
|
||||
### 0.1 기본정보 화면
|
||||
|
||||
| 캡처상 입력 항목명 | 넣을 내용 |
|
||||
| --- | --- |
|
||||
| 프로젝트명 | `TDC114 신규앱 구축` |
|
||||
| 프로젝트 시작일 | `2026-07-02` |
|
||||
| 프로젝트 종료일 | `2026-08-28` |
|
||||
| 분야 | `시스템화` |
|
||||
| 관리상태 | `정상` |
|
||||
| 수행팀 | `IS 3팀` |
|
||||
| PM / 대표 | `-` 또는 실제 PM명 |
|
||||
| 업무수행자 | `문형석 외 2명` |
|
||||
| 협업팀 | `기술개발센터, Baron SSO 연계부서` |
|
||||
| 프로젝트 설명 | `Baron SSO 연계 기반의 TDC114 신규 모바일 앱을 구축하여 직원검색, 전화번호검색, 조직도, 즐겨찾기 등 핵심 기능을 통합 제공하고 Android/iOS 공통 운영 기반과 iOS 대응 구조를 마련한다.` |
|
||||
| 기대 성과 | `사내 직원검색 및 조직도 조회 업무를 모바일에서 일원화하고, Android/iOS 공통 신규앱 기반의 인증 및 운영 체계를 확보하여 사용자 접근성과 유지보수 효율을 높인다.` |
|
||||
| 상시업무 | `미체크 권장` |
|
||||
| 핵심 추진 프로젝트 | `체크 권장` |
|
||||
|
||||
### 0.2 업무 계획 화면
|
||||
|
||||
#### 목표 1
|
||||
|
||||
| 캡처상 입력 항목명 | 넣을 내용 |
|
||||
| --- | --- |
|
||||
| 목표명 | `신규앱 인증/접속 기반 구축` |
|
||||
| 업무성격 | `자료조사` 또는 `기능구현` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-07-02 ~ 2026-07-17` |
|
||||
| 수행기간 | `2026-07-02 ~ 2026-07-17` |
|
||||
| 예상 M/H | `24.0h` |
|
||||
| 실제 M/H | `진행 후 입력` |
|
||||
|
||||
##### 목표 1의 업무 항목
|
||||
|
||||
| 업무명 | 업무성격 | 업무수행자 | 계획기간 | 수행기간 | 비고 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Baron SSO 로그인 연계 설계 | 기능구현 | 문형석 | 2026-07-02 ~ 2026-07-08 | 2026-07-02 ~ 2026-07-08 | Hosted Login, PKCE, Callback 반영 |
|
||||
| 앱 환경설정 및 실행 구조 정비 | 기능구현 | 문형석 | 2026-07-06 ~ 2026-07-13 | 2026-07-06 ~ 2026-07-13 | 환경값, 빌드 설정, 실행 경로 정리 |
|
||||
| 로그인 기본 동작 검증 | 내용정리 | 문형석 | 2026-07-14 ~ 2026-07-17 | 2026-07-14 ~ 2026-07-17 | 실기기/테스트 환경 기준 검증 |
|
||||
|
||||
##### 목표 1의 세부업무 항목
|
||||
|
||||
| 상위 업무명 | 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Baron SSO 로그인 연계 설계 | OIDC/PKCE 인증 흐름 정의 | 2026-07-02 ~ 2026-07-04 | 2026-07-02 ~ 2026-07-04 | 인증 URL, state, code verifier 흐름 정리 |
|
||||
| Baron SSO 로그인 연계 설계 | Callback 처리 정책 정리 | 2026-07-05 ~ 2026-07-08 | 2026-07-05 ~ 2026-07-08 | callback URL, 예외 응답, 세션 연결 기준 정리 |
|
||||
| 앱 환경설정 및 실행 구조 정비 | 환경변수 및 빌드 설정 정리 | 2026-07-06 ~ 2026-07-09 | 2026-07-06 ~ 2026-07-09 | 실행 환경값, 빌드 설정, 앱 실행 조건 정비 |
|
||||
| 앱 환경설정 및 실행 구조 정비 | 개발/테스트 실행 경로 점검 | 2026-07-10 ~ 2026-07-13 | 2026-07-10 ~ 2026-07-13 | 실행 경로, 테스트 기준, 로그 확인 절차 정리 |
|
||||
| 로그인 기본 동작 검증 | 로그인 시나리오 점검 | 2026-07-14 ~ 2026-07-15 | 2026-07-14 ~ 2026-07-15 | 정상 로그인 및 기본 이동 흐름 점검 |
|
||||
| 로그인 기본 동작 검증 | 예외 케이스 확인 | 2026-07-16 ~ 2026-07-17 | 2026-07-16 ~ 2026-07-17 | 실패, 취소, 재시도 케이스 확인 |
|
||||
|
||||
#### 목표 2
|
||||
|
||||
| 캡처상 입력 항목명 | 넣을 내용 |
|
||||
| --- | --- |
|
||||
| 목표명 | `직원검색/조직도 핵심 기능 구현` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석 외 1명` |
|
||||
| 계획기간 | `2026-07-20 ~ 2026-08-14` |
|
||||
| 수행기간 | `2026-07-20 ~ 2026-08-14` |
|
||||
| 예상 M/H | `48.0h` |
|
||||
| 실제 M/H | `진행 후 입력` |
|
||||
|
||||
##### 목표 2의 업무 항목
|
||||
|
||||
| 업무명 | 업무성격 | 업무수행자 | 계획기간 | 수행기간 | 비고 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 직원검색 및 전화번호검색 기능 구현 | 기능구현 | 문형석 | 2026-07-20 ~ 2026-07-29 | 2026-07-20 ~ 2026-07-29 | 검색 조건, 결과 리스트, 상세 연결 |
|
||||
| 가족사 필터 및 조직도 조회 구현 | 기능구현 | 문형석 외 1명 | 2026-07-27 ~ 2026-08-05 | 2026-07-27 ~ 2026-08-05 | 조직 탐색, 부서 목록, 정렬 규칙 반영 |
|
||||
| 직원 상세/전화/문자 연계 구성 | 기능구현 | 문형석 | 2026-08-03 ~ 2026-08-10 | 2026-08-03 ~ 2026-08-10 | 상세정보, 전화걸기, 문자보내기 연계 |
|
||||
| 즐겨찾기 및 화면 UX 보정 | 기능구현 | 문형석 외 1명 | 2026-08-08 ~ 2026-08-14 | 2026-08-08 ~ 2026-08-14 | 로컬 저장, 화면 사용성 개선 |
|
||||
| iOS 대응 구조 및 실행 검토 | 자료조사 | 문형석 | 2026-08-11 ~ 2026-08-14 | 2026-08-11 ~ 2026-08-14 | iOS 실행 조건, 링크 처리, 배포 준비 항목 점검 |
|
||||
|
||||
##### 목표 2의 세부업무 항목
|
||||
|
||||
| 상위 업무명 | 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 직원검색 및 전화번호검색 기능 구현 | 검색 조건 및 입력 규칙 적용 | 2026-07-20 ~ 2026-07-23 | 2026-07-20 ~ 2026-07-23 | 이름/전화번호 검색 조건 및 입력 규칙 반영 |
|
||||
| 직원검색 및 전화번호검색 기능 구현 | 검색 결과 리스트 구성 | 2026-07-24 ~ 2026-07-29 | 2026-07-24 ~ 2026-07-29 | 결과 리스트, 상세 진입, 빈 결과 처리 |
|
||||
| 가족사 필터 및 조직도 조회 구현 | 가족사 필터 구성 | 2026-07-27 ~ 2026-07-30 | 2026-07-27 ~ 2026-07-30 | 회사/조직 필터 선택 구조 반영 |
|
||||
| 가족사 필터 및 조직도 조회 구현 | 조직도 조회 및 정렬 규칙 반영 | 2026-07-31 ~ 2026-08-05 | 2026-07-31 ~ 2026-08-05 | 조직 탐색, 목록 정렬, 하위 이동 처리 |
|
||||
| 직원 상세/전화/문자 연계 구성 | 직원 상세정보 화면 구성 | 2026-08-03 ~ 2026-08-06 | 2026-08-03 ~ 2026-08-06 | 부서/직위/연락처 등 상세 정보 구성 |
|
||||
| 직원 상세/전화/문자 연계 구성 | 전화/문자 실행 연계 | 2026-08-07 ~ 2026-08-10 | 2026-08-07 ~ 2026-08-10 | 전화걸기, 문자보내기 외부 앱 연계 |
|
||||
| 즐겨찾기 및 화면 UX 보정 | 즐겨찾기 저장 기능 반영 | 2026-08-08 ~ 2026-08-11 | 2026-08-08 ~ 2026-08-11 | 로컬 저장 및 목록 반영 |
|
||||
| 즐겨찾기 및 화면 UX 보정 | 주요 화면 UX 보완 | 2026-08-12 ~ 2026-08-14 | 2026-08-12 ~ 2026-08-14 | 화면 동선, 선택 상태, 가독성 보정 |
|
||||
| iOS 대응 구조 및 실행 검토 | iOS 로그인/링크 처리 검토 | 2026-08-11 ~ 2026-08-12 | 2026-08-11 ~ 2026-08-12 | iOS callback 처리, 링크 연결, 정책 차이 점검 |
|
||||
| iOS 대응 구조 및 실행 검토 | iOS 배포 준비 항목 정리 | 2026-08-13 ~ 2026-08-14 | 2026-08-13 ~ 2026-08-14 | 서명, 배포 방식, 테스트 기준 정리 |
|
||||
|
||||
#### 목표 3
|
||||
|
||||
| 캡처상 입력 항목명 | 넣을 내용 |
|
||||
| --- | --- |
|
||||
| 목표명 | `안정화 및 운영 전환 준비` |
|
||||
| 업무성격 | `자료조사` |
|
||||
| 업무수행자 | `문형석 외 2명` |
|
||||
| 계획기간 | `2026-08-17 ~ 2026-08-28` |
|
||||
| 수행기간 | `2026-08-17 ~ 2026-08-28` |
|
||||
| 예상 M/H | `36.0h` |
|
||||
| 실제 M/H | `진행 후 입력` |
|
||||
|
||||
##### 목표 3의 업무 항목
|
||||
|
||||
| 업무명 | 업무성격 | 업무수행자 | 계획기간 | 수행기간 | 비고 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 통합 테스트 및 예외 시나리오 점검 | 기능구현 | 문형석 외 1명 | 2026-08-17 ~ 2026-08-21 | 2026-08-17 ~ 2026-08-21 | 로그인, 검색, 조직도, 상세 기능 검증 |
|
||||
| 배포 환경 및 운영 체크리스트 정리 | 내용정리 | 문형석 | 2026-08-20 ~ 2026-08-25 | 2026-08-20 ~ 2026-08-25 | Android/iOS 배포 기준, 장애 대응, 운영 절차 정리 |
|
||||
| 시범 운영 및 보완사항 반영 | 기능구현 | 문형석 외 2명 | 2026-08-24 ~ 2026-08-28 | 2026-08-24 ~ 2026-08-28 | 피드백 반영 후 1차 마무리 |
|
||||
|
||||
##### 목표 3의 세부업무 항목
|
||||
|
||||
| 상위 업무명 | 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 통합 테스트 및 예외 시나리오 점검 | 핵심 기능 통합 테스트 | 2026-08-17 ~ 2026-08-19 | 2026-08-17 ~ 2026-08-19 | 로그인, 검색, 조직도, 상세 흐름 점검 |
|
||||
| 통합 테스트 및 예외 시나리오 점검 | 예외 시나리오 및 오류 확인 | 2026-08-20 ~ 2026-08-21 | 2026-08-20 ~ 2026-08-21 | 실패 케이스, 오류 메시지, 재시도 확인 |
|
||||
| 배포 환경 및 운영 체크리스트 정리 | Android/iOS 배포 기준 정리 | 2026-08-20 ~ 2026-08-22 | 2026-08-20 ~ 2026-08-22 | 배포 버전, 환경, 점검 항목 정리 |
|
||||
| 배포 환경 및 운영 체크리스트 정리 | 운영 절차 및 장애 대응 정리 | 2026-08-23 ~ 2026-08-25 | 2026-08-23 ~ 2026-08-25 | 운영 절차, 문의 대응, 장애 체크 정리 |
|
||||
| 시범 운영 및 보완사항 반영 | 사용자 피드백 반영 | 2026-08-24 ~ 2026-08-26 | 2026-08-24 ~ 2026-08-26 | 시범 운영 중 확인된 보완사항 반영 |
|
||||
| 시범 운영 및 보완사항 반영 | 1차 완료 정리 | 2026-08-27 ~ 2026-08-28 | 2026-08-27 ~ 2026-08-28 | 완료 보고 및 운영 전환 정리 |
|
||||
|
||||
### 0.3 업무 관리 화면
|
||||
|
||||
| 캡처상 입력 항목명 | 넣을 내용 |
|
||||
| --- | --- |
|
||||
| ROADMAP 전체 업무 > 목표 1 | `신규앱 인증/접속 기반 구축` |
|
||||
| ROADMAP 전체 업무 > 목표 2 | `직원검색/조직도 핵심 기능 구현` |
|
||||
| ROADMAP 전체 업무 > 목표 3 | `안정화 및 운영 전환 준비` |
|
||||
| CHECK 확인사항 1 | `Baron SSO 연계 정보 확정` |
|
||||
| CHECK 확인사항 2 | `조직/직원 데이터 기준 정합성 확인` |
|
||||
| CHECK 확인사항 3 | `Android/iOS 배포 방식 및 운영 기준 협의` |
|
||||
| CHECK 확인사항 4 | `iOS 링크/배포 정책 확인` |
|
||||
|
||||
### 0.4 통합 대시보드 카드 화면
|
||||
|
||||
| 캡처상 표시 항목 | 넣을 내용 |
|
||||
| --- | --- |
|
||||
| 프로젝트명 | `TDC114 신규앱 구축` |
|
||||
| 현재업무 | `Baron SSO 로그인 연계 및 직원검색/조직도 1차 구축` |
|
||||
| 목표일 | `26.08.28 완료 목표` |
|
||||
| 기간 표기 | `26.07 ~ 26.08` |
|
||||
|
||||
## 1. 작성 방향
|
||||
|
||||
- 기존 `바로 로그인v1.0`처럼 짧고 명확한 프로젝트명으로 정리한다.
|
||||
- 현재 저장소와 문서 기준으로 신규어플은 `tdc114plus` 모바일 앱 구축/고도화 성격으로 정리한다.
|
||||
- 날짜는 2026년 3분기 기준으로 자연스럽게 이어지도록 조정했다.
|
||||
- 조직명, 참여자명은 실제 등록 가능한 선택값에 맞춰 마지막 입력 단계에서 미세 조정하면 된다.
|
||||
|
||||
## 2. 기본정보 입력 초안
|
||||
|
||||
### 2.1 권장 프로젝트명
|
||||
|
||||
`TDC114 신규앱 구축`
|
||||
|
||||
대안:
|
||||
|
||||
- `TDC114 신규앱 고도화`
|
||||
- `TDC114 모바일 전화번호부 구축`
|
||||
- `TDC114 신규앱 1차 구축`
|
||||
|
||||
가장 무난한 권장안은 `TDC114 신규앱 구축`이다.
|
||||
|
||||
### 2.2 기본정보 필드별 권장값
|
||||
|
||||
| 항목 | 입력 권장값 |
|
||||
| --- | --- |
|
||||
| 프로젝트명 | `TDC114 신규앱 구축` |
|
||||
| 프로젝트 시작일 | `2026-07-02` |
|
||||
| 프로젝트 종료일 | `2026-08-28` |
|
||||
| 분야 | `시스템화` |
|
||||
| 관리상태 | `정상` |
|
||||
| 수행팀 | `IS 3팀` 또는 실제 담당팀 |
|
||||
| PM / 대표 | `-` 또는 실제 PM |
|
||||
| 업무수행자 | `문형석 외 2명` |
|
||||
| 협업팀 | `기술개발센터, Baron SSO 연계부서` |
|
||||
| 상시업무 여부 | 미체크 권장 |
|
||||
| 핵심 추진 프로젝트 | 체크 권장 |
|
||||
|
||||
### 2.3 프로젝트 설명
|
||||
|
||||
아래 문안 중 하나를 그대로 입력하면 된다.
|
||||
|
||||
#### 설명안 A
|
||||
|
||||
`Baron SSO 연계 기반의 TDC114 신규 모바일 앱을 구축하여 직원검색, 전화번호검색, 조직도, 즐겨찾기 등 핵심 기능을 통합 제공하고 Android/iOS 공통 운영 기반과 iOS 대응 구조를 마련한다.`
|
||||
|
||||
#### 설명안 B
|
||||
|
||||
`기존 전화번호부 업무를 모바일 신규앱으로 전환하기 위한 프로젝트로, Baron SSO 로그인 연계와 조직/직원 정보 조회 기능을 중심으로 1차 서비스를 구축한다.`
|
||||
|
||||
### 2.4 기대 성과
|
||||
|
||||
아래 문안 중 하나를 그대로 입력하면 된다.
|
||||
|
||||
#### 기대성과안 A
|
||||
|
||||
`사내 직원검색 및 조직도 조회 업무를 모바일에서 일원화하고, Android/iOS 공통 신규앱 기반의 인증 및 운영 체계를 확보하여 사용자 접근성과 유지보수 효율을 높인다.`
|
||||
|
||||
#### 기대성과안 B
|
||||
|
||||
`기존 분산된 연락처 조회 업무를 통합하고, Baron SSO 연계 표준 로그인 체계를 Android/iOS 공통으로 적용하여 향후 기능 확장과 서비스 안정화 기반을 확보한다.`
|
||||
|
||||
## 3. 대시보드 카드 노출용 요약 문안
|
||||
|
||||
통합 화면 카드에 보일 수 있도록 짧게 정리한 문안이다.
|
||||
|
||||
### 3.1 프로젝트 표시명
|
||||
|
||||
`TDC114 신규앱 구축`
|
||||
|
||||
### 3.2 현재업무 표시 문안
|
||||
|
||||
`Baron SSO 로그인 연계 및 직원검색/조직도 1차 구축`
|
||||
|
||||
대안:
|
||||
|
||||
- `신규앱 기본 기능 개발 및 인증 연동`
|
||||
- `모바일 전화번호부 앱 1차 기능 구현`
|
||||
|
||||
### 3.3 목표일 표시 기준
|
||||
|
||||
`26.08.28 완료 목표`
|
||||
|
||||
## 4. 업무 계획 입력 초안
|
||||
|
||||
업무 계획 화면에서 `목표 -> 업무 -> 세부업무` 구조로 입력하기 쉽게 정리했다.
|
||||
|
||||
### 4.1 목표 1
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 목표명 | `신규앱 인증/접속 기반 구축` |
|
||||
| 업무성격 | `자료조사` 또는 `기능구현` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-07-02 ~ 2026-07-17` |
|
||||
| 수행기간 | `2026-07-02 ~ 2026-07-17` |
|
||||
| 예상 M/H | `24.0h` |
|
||||
|
||||
#### 업무 1.1
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `Baron SSO 로그인 연계 설계` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-07-02 ~ 2026-07-08` |
|
||||
| 수행기간 | `2026-07-02 ~ 2026-07-08` |
|
||||
| 비고 | `Hosted Login, PKCE, Callback 정책 반영` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `OIDC/PKCE 인증 흐름 정의` | `2026-07-02 ~ 2026-07-04` | `2026-07-02 ~ 2026-07-04` | `인증 URL, state, code verifier 흐름 정리` |
|
||||
| `Callback 처리 정책 정리` | `2026-07-05 ~ 2026-07-08` | `2026-07-05 ~ 2026-07-08` | `callback URL, 예외 응답, 세션 연결 기준 정리` |
|
||||
|
||||
#### 업무 1.2
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `앱 환경설정 및 실행 구조 정비` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-07-06 ~ 2026-07-13` |
|
||||
| 수행기간 | `2026-07-06 ~ 2026-07-13` |
|
||||
| 비고 | `환경값, 빌드 설정, 실행 경로 정리` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `환경변수 및 빌드 설정 정리` | `2026-07-06 ~ 2026-07-09` | `2026-07-06 ~ 2026-07-09` | `실행 환경값, 빌드 설정, 앱 실행 조건 정비` |
|
||||
| `개발/테스트 실행 경로 점검` | `2026-07-10 ~ 2026-07-13` | `2026-07-10 ~ 2026-07-13` | `실행 경로, 테스트 기준, 로그 확인 절차 정리` |
|
||||
|
||||
#### 업무 1.3
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `로그인 기본 동작 검증` |
|
||||
| 업무성격 | `내용정리` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-07-14 ~ 2026-07-17` |
|
||||
| 수행기간 | `2026-07-14 ~ 2026-07-17` |
|
||||
| 비고 | `실기기/테스트 환경 기준 검증` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `로그인 시나리오 점검` | `2026-07-14 ~ 2026-07-15` | `2026-07-14 ~ 2026-07-15` | `정상 로그인 및 기본 이동 흐름 점검` |
|
||||
| `예외 케이스 확인` | `2026-07-16 ~ 2026-07-17` | `2026-07-16 ~ 2026-07-17` | `실패, 취소, 재시도 케이스 확인` |
|
||||
|
||||
### 4.2 목표 2
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 목표명 | `직원검색/조직도 핵심 기능 구현` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석 외 1명` |
|
||||
| 계획기간 | `2026-07-20 ~ 2026-08-14` |
|
||||
| 수행기간 | `2026-07-20 ~ 2026-08-14` |
|
||||
| 예상 M/H | `48.0h` |
|
||||
|
||||
#### 업무 2.1
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `직원검색 및 전화번호검색 기능 구현` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-07-20 ~ 2026-07-29` |
|
||||
| 수행기간 | `2026-07-20 ~ 2026-07-29` |
|
||||
| 비고 | `검색 조건, 결과 리스트, 상세 연결` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `검색 조건 및 입력 규칙 적용` | `2026-07-20 ~ 2026-07-23` | `2026-07-20 ~ 2026-07-23` | `이름/전화번호 검색 조건 및 입력 규칙 반영` |
|
||||
| `검색 결과 리스트 구성` | `2026-07-24 ~ 2026-07-29` | `2026-07-24 ~ 2026-07-29` | `결과 리스트, 상세 진입, 빈 결과 처리` |
|
||||
|
||||
#### 업무 2.2
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `가족사 필터 및 조직도 조회 구현` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석 외 1명` |
|
||||
| 계획기간 | `2026-07-27 ~ 2026-08-05` |
|
||||
| 수행기간 | `2026-07-27 ~ 2026-08-05` |
|
||||
| 비고 | `조직 탐색, 부서 목록, 정렬 규칙 반영` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `가족사 필터 구성` | `2026-07-27 ~ 2026-07-30` | `2026-07-27 ~ 2026-07-30` | `회사/조직 필터 선택 구조 반영` |
|
||||
| `조직도 조회 및 정렬 규칙 반영` | `2026-07-31 ~ 2026-08-05` | `2026-07-31 ~ 2026-08-05` | `조직 탐색, 목록 정렬, 하위 이동 처리` |
|
||||
|
||||
#### 업무 2.3
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `직원 상세/전화/문자 연계 구성` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-08-03 ~ 2026-08-10` |
|
||||
| 수행기간 | `2026-08-03 ~ 2026-08-10` |
|
||||
| 비고 | `상세정보, 전화걸기, 문자보내기 연계` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `직원 상세정보 화면 구성` | `2026-08-03 ~ 2026-08-06` | `2026-08-03 ~ 2026-08-06` | `부서/직위/연락처 등 상세 정보 구성` |
|
||||
| `전화/문자 실행 연계` | `2026-08-07 ~ 2026-08-10` | `2026-08-07 ~ 2026-08-10` | `전화걸기, 문자보내기 외부 앱 연계` |
|
||||
|
||||
#### 업무 2.5
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `iOS 대응 구조 및 실행 검토` |
|
||||
| 업무성격 | `자료조사` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-08-11 ~ 2026-08-14` |
|
||||
| 수행기간 | `2026-08-11 ~ 2026-08-14` |
|
||||
| 비고 | `iOS 실행 조건, 링크 처리, 배포 준비 항목 점검` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `iOS 로그인/링크 처리 검토` | `2026-08-11 ~ 2026-08-12` | `2026-08-11 ~ 2026-08-12` | `iOS callback 처리, 링크 연결, 정책 차이 점검` |
|
||||
| `iOS 배포 준비 항목 정리` | `2026-08-13 ~ 2026-08-14` | `2026-08-13 ~ 2026-08-14` | `서명, 배포 방식, 테스트 기준 정리` |
|
||||
|
||||
#### 업무 2.4
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `즐겨찾기 및 화면 UX 보정` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석 외 1명` |
|
||||
| 계획기간 | `2026-08-08 ~ 2026-08-14` |
|
||||
| 수행기간 | `2026-08-08 ~ 2026-08-14` |
|
||||
| 비고 | `로컬 저장, 화면 사용성 개선` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `즐겨찾기 저장 기능 반영` | `2026-08-08 ~ 2026-08-11` | `2026-08-08 ~ 2026-08-11` | `로컬 저장 및 목록 반영` |
|
||||
| `주요 화면 UX 보완` | `2026-08-12 ~ 2026-08-14` | `2026-08-12 ~ 2026-08-14` | `화면 동선, 선택 상태, 가독성 보정` |
|
||||
|
||||
### 4.3 목표 3
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 목표명 | `안정화 및 운영 전환 준비` |
|
||||
| 업무성격 | `자료조사` |
|
||||
| 업무수행자 | `문형석 외 2명` |
|
||||
| 계획기간 | `2026-08-17 ~ 2026-08-28` |
|
||||
| 수행기간 | `2026-08-17 ~ 2026-08-28` |
|
||||
| 예상 M/H | `36.0h` |
|
||||
|
||||
#### 업무 3.1
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `통합 테스트 및 예외 시나리오 점검` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석 외 1명` |
|
||||
| 계획기간 | `2026-08-17 ~ 2026-08-21` |
|
||||
| 수행기간 | `2026-08-17 ~ 2026-08-21` |
|
||||
| 비고 | `로그인, 검색, 조직도, 상세 기능 검증` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `핵심 기능 통합 테스트` | `2026-08-17 ~ 2026-08-19` | `2026-08-17 ~ 2026-08-19` | `로그인, 검색, 조직도, 상세 흐름 점검` |
|
||||
| `예외 시나리오 및 오류 확인` | `2026-08-20 ~ 2026-08-21` | `2026-08-20 ~ 2026-08-21` | `실패 케이스, 오류 메시지, 재시도 확인` |
|
||||
|
||||
#### 업무 3.2
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `배포 환경 및 운영 체크리스트 정리` |
|
||||
| 업무성격 | `내용정리` |
|
||||
| 업무수행자 | `문형석` |
|
||||
| 계획기간 | `2026-08-20 ~ 2026-08-25` |
|
||||
| 수행기간 | `2026-08-20 ~ 2026-08-25` |
|
||||
| 비고 | `배포 기준, 장애 대응, 운영 절차 정리` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `배포 기준 정리` | `2026-08-20 ~ 2026-08-22` | `2026-08-20 ~ 2026-08-22` | `배포 버전, 환경, 점검 항목 정리` |
|
||||
| `운영 절차 및 장애 대응 정리` | `2026-08-23 ~ 2026-08-25` | `2026-08-23 ~ 2026-08-25` | `운영 절차, 문의 대응, 장애 체크 정리` |
|
||||
|
||||
#### 업무 3.3
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| 업무명 | `시범 운영 및 보완사항 반영` |
|
||||
| 업무성격 | `기능구현` |
|
||||
| 업무수행자 | `문형석 외 2명` |
|
||||
| 계획기간 | `2026-08-24 ~ 2026-08-28` |
|
||||
| 수행기간 | `2026-08-24 ~ 2026-08-28` |
|
||||
| 비고 | `피드백 반영 후 1차 마무리` |
|
||||
|
||||
세부업무:
|
||||
|
||||
| 세부업무명 | 계획기간 | 수행기간 | 설명 |
|
||||
| --- | --- | --- | --- |
|
||||
| `사용자 피드백 반영` | `2026-08-24 ~ 2026-08-26` | `2026-08-24 ~ 2026-08-26` | `시범 운영 중 확인된 보완사항 반영` |
|
||||
| `1차 완료 정리` | `2026-08-27 ~ 2026-08-28` | `2026-08-27 ~ 2026-08-28` | `완료 보고 및 운영 전환 정리` |
|
||||
|
||||
## 5. 업무 관리 입력 초안
|
||||
|
||||
업무 관리 화면의 목표 제목은 아래처럼 넣으면 자연스럽다.
|
||||
|
||||
| 목표 | 입력 문안 |
|
||||
| --- | --- |
|
||||
| 목표 1 | `신규앱 인증/접속 기반 구축` |
|
||||
| 목표 2 | `직원검색/조직도 핵심 기능 구현` |
|
||||
| 목표 3 | `안정화 및 운영 전환 준비` |
|
||||
|
||||
### 5.1 확인사항
|
||||
|
||||
확인사항 카드에는 아래 문안이 적합하다.
|
||||
|
||||
#### 확인사항 1
|
||||
|
||||
- 제목: `Baron SSO 연계 정보 확정`
|
||||
- 구분: `등록`
|
||||
- 내용: `OIDC 연계값, Callback URL, 환경별 접속 경로 확정 필요`
|
||||
|
||||
#### 확인사항 2
|
||||
|
||||
- 제목: `조직/직원 데이터 기준 정합성 확인`
|
||||
- 구분: `확인`
|
||||
- 내용: `신규앱 노출 항목과 실제 조직 데이터 매핑 기준 확인 필요`
|
||||
|
||||
#### 확인사항 3
|
||||
|
||||
- 제목: `Android/iOS 배포 방식 및 운영 기준 협의`
|
||||
- 구분: `공유`
|
||||
- 내용: `Android/iOS 배포 경로와 운영 인수 기준 사전 협의 필요`
|
||||
|
||||
#### 확인사항 4
|
||||
|
||||
- 제목: `iOS 링크/배포 정책 확인`
|
||||
- 구분: `확인`
|
||||
- 내용: `iOS Universal Link, 서명, 배포 절차 적용 가능 여부 확인 필요`
|
||||
|
||||
## 6. 로드맵 요약 문안
|
||||
|
||||
로드맵 또는 상위 보고용으로는 아래 정도면 충분하다.
|
||||
|
||||
### 6.1 7월
|
||||
|
||||
- 인증 연계 구조 확정
|
||||
- 앱 기본 실행 및 로그인 흐름 정비
|
||||
- 개발/테스트 환경 기준 통일
|
||||
|
||||
### 6.2 8월
|
||||
|
||||
- 직원검색, 전화번호검색, 조직도, 상세 기능 집중 구현
|
||||
- 즐겨찾기 및 주요 UX 보완
|
||||
- iOS 로그인/링크 처리 및 배포 준비 항목 검토
|
||||
|
||||
### 6.3 8월 후반
|
||||
|
||||
- 통합 테스트
|
||||
- 시범 운영
|
||||
- 보완사항 반영 및 1차 완료
|
||||
|
||||
## 7. 변경사항 입력 초안
|
||||
|
||||
변경사항 탭에는 아래처럼 기록하면 무난하다.
|
||||
|
||||
| 일자 | 변경내용 |
|
||||
| --- | --- |
|
||||
| 2026-07-02 | 신규어플 프로젝트 등록 및 기본정보 입력 |
|
||||
| 2026-07-10 | 인증 연계 구조 및 환경설정 범위 확정 |
|
||||
| 2026-07-29 | 직원검색/조직도 1차 기능 개발 범위 반영 |
|
||||
| 2026-08-21 | 통합 테스트 결과 및 보완사항 반영 |
|
||||
| 2026-08-28 | 1차 구축 완료 및 운영 전환 기준 정리 |
|
||||
|
||||
## 8. 최종 추천 입력 세트
|
||||
|
||||
시간이 없으면 아래만 우선 입력해도 된다.
|
||||
|
||||
### 기본정보
|
||||
|
||||
- 프로젝트명: `TDC114 신규앱 구축`
|
||||
- 시작일: `2026-07-02`
|
||||
- 종료일: `2026-08-28`
|
||||
- 분야: `시스템화`
|
||||
- 관리상태: `정상`
|
||||
- 수행팀: `IS 3팀`
|
||||
- 업무수행자: `문형석 외 2명`
|
||||
- 협업팀: `기술개발센터, Baron SSO 연계부서`
|
||||
- 프로젝트 설명: `Baron SSO 연계 기반의 TDC114 신규 모바일 앱을 구축하여 직원검색, 전화번호검색, 조직도, 즐겨찾기 등 핵심 기능을 통합 제공하고 Android/iOS 공통 운영 기반과 iOS 대응 구조를 마련한다.`
|
||||
- 기대 성과: `사내 직원검색 및 조직도 조회 업무를 모바일에서 일원화하고, Android/iOS 공통 신규앱 기반의 인증 및 운영 체계를 확보하여 사용자 접근성과 유지보수 효율을 높인다.`
|
||||
|
||||
### 대표 목표
|
||||
|
||||
1. `신규앱 인증/접속 기반 구축`
|
||||
2. `직원검색/조직도 핵심 기능 구현`
|
||||
3. `안정화 및 운영 전환 준비`
|
||||
|
||||
### 카드 표시용
|
||||
|
||||
- 현재업무: `Baron SSO 로그인 연계 및 직원검색/조직도 1차 구축`
|
||||
- 목표일: `26.08.28 완료 목표`
|
||||
|
||||
## 9. 비고
|
||||
|
||||
- `수행팀`, `업무수행자`, `협업팀`은 실제 대시보드 선택값에 맞춰 마지막에만 조정하면 된다.
|
||||
- 프로젝트명을 조금 더 실무형으로 보이게 하려면 `구축`, 조금 더 계속과제 느낌으로 보이게 하려면 `고도화`를 쓰면 된다.
|
||||
- 핵심 추진 프로젝트 체크 여부는 팀 운영 방식에 따라 다르지만, 현재 성격상 체크하는 편이 자연스럽다.
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
| 항목 | 결정 |
|
||||
| --- | --- |
|
||||
| 로그인/가입 | 앱 자체 회원가입은 제공하지 않는다. Baron SSO에 이미 등록된 사용자만 사용 가능하다. |
|
||||
| 앱 실행 로그인 | 사용자는 앱 실행 시 Baron SSO 로그인 방식으로 진입한다. 로그인창에 전화번호 입력 후 로그인 버튼을 누르면 Baron SSO 서버 등록 인원 여부를 확인하고, 등록 인원이면 앱 사용을 허용한다. |
|
||||
| 앱 실행 로그인 | 사용자는 앱 실행 시 앱의 `Baron SSO로 로그인` 버튼으로 Baron SSO Hosted Login 화면에 진입한다. 휴대폰번호 입력과 문자/메일 링크 인증은 Baron SSO 화면에서 처리하고, 인증 성공 후 App Link callback과 PKCE token 교환으로 앱 로그인을 완료한다. |
|
||||
| 데이터 연계 | 신규 앱의 개인 정보와 조직 정보는 Baron SSO의 `orgFront` 데이터와 연계하여 추출한다. |
|
||||
| 1차 제외 기능 | 기존 앱 기능 중 공지사항과 전자결재는 개발 중간 단계까지 구현을 보류한다. |
|
||||
| 플랫폼 특화 제외 | 수신전화식별과 수신팝업은 1차 범위에서 보류한다. iOS에서 동일 방식 지원이 어렵고, 우선 기본 기능에 집중한다. |
|
||||
@@ -0,0 +1,142 @@
|
||||
# tdc114plus 테스트 자동화 스크립트 계획
|
||||
|
||||
작성일: 2026-07-02
|
||||
상태: v1.0 초기 스크립트 기준
|
||||
|
||||
목적: `docs/00_policy_tdc114plus_testing_2026-07-02.md`에 정의한 테스트 정책을 실제 `scripts/` 파일과 연결하고, 즉시 사용 가능한 스크립트와 향후 구현이 필요한 scaffold 스크립트를 구분한다.
|
||||
|
||||
## 1. 즉시 사용 가능한 스크립트
|
||||
|
||||
| 스크립트 | 목적 | 실행 예 |
|
||||
| --- | --- | --- |
|
||||
| `scripts/format-dart.sh` | Docker Flutter 이미지에서 `dart format lib test` 실행 | `./scripts/format-dart.sh` |
|
||||
| `scripts/quality-gate.sh` | `flutter analyze`, `flutter test` 순차 실행 | `./scripts/quality-gate.sh` |
|
||||
| `scripts/api-smoke.sh` | `TDC114_API_BASE` 대상 Baron SSO 연동 API 최소 smoke test 실행. `TDC114_SMOKE_PHONE`이 있으면 `TDC114_SMOKE_AUTH_FLOW`에 따라 legacy `phone-login` 호환 경로 또는 headless 링크 흐름을 확인 | `TDC114_API_BASE=http://127.0.0.1:5000 ./scripts/api-smoke.sh` |
|
||||
| `scripts/smoke.env.example` | authenticated smoke용 로컬 env 예시 파일. `scripts/.env.smoke.local`로 복사해 `TDC114_API_BASE`, `TDC114_SMOKE_PHONE` 값을 넣어 사용 | `cp scripts/smoke.env.example scripts/.env.smoke.local` |
|
||||
| `scripts/smoke.staging.env.example` | staging Baron SSO 검증용 env 예시 파일. `scripts/.env.staging.local`로 복사해 `TDC114_API_BASE`, `TDC114_SMOKE_PHONE`, optional expected label 값을 넣어 사용 | `cp scripts/smoke.staging.env.example scripts/.env.staging.local` |
|
||||
| `scripts/bootstrap-baron-api-env.sh` | Baron SSO API worktree의 `.env.sample`을 바탕으로 로컬 smoke용 `.env`를 생성하고 localhost/알림 비활성 override를 추가 | `./scripts/bootstrap-baron-api-env.sh` |
|
||||
| `scripts/check-baron-api-env.sh` | Baron SSO API worktree의 `.env`, compose, config, Docker runtime 준비 상태를 점검해 API smoke 가능 여부를 빠르게 확인 | `./scripts/check-baron-api-env.sh` |
|
||||
| `scripts/manual-postlogin-run.sh` | Android target에 `dart-define`을 포함한 `flutter run` 경로로 앱을 띄운다. 기본은 Baron SSO Hosted Login + PKCE 진입이며, 예외적으로만 legacy local `phone-login` bootstrap으로 post-login 상태를 seed 한다. 내부 호출은 `flutter-docker.sh run ...` 형태를 사용한다 | `TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local TDC114_FLUTTER_DEVICE_ID=<PHYSICAL_DEVICE_ID> ./scripts/manual-postlogin-run.sh` |
|
||||
| `scripts/generate-release-report.sh` | git 상태와 릴리스 체크리스트 report 생성 | `./scripts/generate-release-report.sh` |
|
||||
| `scripts/perf_smoke.sh` | 현재 앱/테스트 파일 수와 기본 상태 출력 | `./scripts/perf_smoke.sh` |
|
||||
|
||||
## 2. Scaffold 상태의 스크립트
|
||||
|
||||
아래 스크립트는 파일은 존재하지만, 기반 기능이 아직 없으므로 실행 시 scaffold 안내와 함께 종료한다.
|
||||
|
||||
| 스크립트 | 현재 상태 | 완성 조건 |
|
||||
| --- | --- | --- |
|
||||
| `scripts/mock-server.sh` | `status`, `stop`은 가능. `start`는 미구현 안내 | API 계약 기반 mock server 구현 |
|
||||
| `scripts/save-snapshots.sh` | snapshot source가 있으면 report 경로로 복사 | widget/integration screenshot 또는 snapshot 생성 체계 |
|
||||
| `scripts/integration_tests.sh` | `TDC114_API_BASE`를 Dart define으로 주입해 Android 기준 `flutter drive --driver=test_driver/integration_driver.dart --target=integration_test/app_smoke_test.dart`로 실행한다. Android preflight는 실기기 우선 기준이며 emulator는 fallback이다. `TDC114_SMOKE_PHONE`이 있으면 실제 로그인 smoke까지 확장한다. `TDC114_SMOKE_ASSUME_LOGGED_IN=1`일 때 기본 seed는 mock이고, legacy `phone-login` bootstrap은 명시적 예외 모드다 | `TDC114_API_BASE=http://127.0.0.1:5000 ./scripts/integration_tests.sh` |
|
||||
| `scripts/redteam/run_all.sh` | 현재 AI 기능 없음 안내 | LLM/프롬프트 기반 기능이 실제 추가될 때 |
|
||||
|
||||
## 3. Phase별 사용 기준
|
||||
|
||||
### Phase 3: Mock 기반 1차 UI
|
||||
|
||||
필수:
|
||||
|
||||
```bash
|
||||
./scripts/format-dart.sh
|
||||
./scripts/quality-gate.sh
|
||||
```
|
||||
|
||||
선택:
|
||||
|
||||
```bash
|
||||
./scripts/save-snapshots.sh
|
||||
```
|
||||
|
||||
단, snapshot 산출물이 생긴 뒤 사용한다.
|
||||
|
||||
### Phase 4: 실제 API 연동
|
||||
|
||||
필수 후보:
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=https://staging.example.com ./scripts/api-smoke.sh
|
||||
./scripts/check-baron-api-env.sh
|
||||
TDC114_API_BASE=https://staging.example.com ./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
현재 구현 상태:
|
||||
|
||||
- `app/integration_test/app_smoke_test.dart` scaffold 완료
|
||||
- 로그인 화면 표시, 빈 전화번호 validation smoke는 항상 실행 가능
|
||||
- `TDC114_SMOKE_PHONE`이 있으면 실제 로그인 후 직원검색 화면 진입 smoke까지 확장
|
||||
- `scripts/.env.smoke.local`이 있으면 `TDC114_API_BASE`, `TDC114_SMOKE_PHONE`을 자동으로 읽는다
|
||||
- `api-smoke.sh`는 optional `TDC114_SMOKE_AUTH_FLOW=phone-login|link`를 지원한다. staging 신규 승인 로그인 검증은 `link`를 사용한다
|
||||
- staging 검증 시에는 `TDC114_SMOKE_ENV_FILE=scripts/.env.staging.local` 방식으로 별도 env 파일을 지정할 수 있다
|
||||
- `scripts/integration_tests.sh`는 Android 기준 `flutter drive`와 `test_driver/integration_driver.dart`를 사용해 현재 Flutter 버전의 unit/integration 혼합 실행 제한을 피한다
|
||||
- `scripts/integration_tests.sh`는 Android target 정보가 주어지면 `scripts/check-android-device-env.sh`를 먼저 호출해 실기기/에뮬레이터 `offline`/`refused` 상태를 선제 차단한다
|
||||
- `scripts/integration_tests.sh`는 `No supported devices connected.` 실패를 만나면 Android 실기기 우선, emulator fallback 또는 추가 desktop/web runner 필요 안내를 함께 출력
|
||||
- `scripts/integration_tests.sh`는 optional `TDC114_SMOKE_EXPECTED_NAME`, `TDC114_SMOKE_EXPECTED_TENANT_LABEL`을 Dart define으로 전달해 staging 계정 기준 기대 텍스트를 추가 검증할 수 있다
|
||||
|
||||
실환경 연동 완료 조건:
|
||||
|
||||
- Baron SSO backend 또는 staging API endpoint 실행
|
||||
- Baron SSO `.env` 및 `config/` runtime 파일 준비
|
||||
- 실제 로그인까지 확인할 경우 민감정보 없는 `TDC114_SMOKE_PHONE` 테스트 계정 준비
|
||||
- staging 또는 local mock API endpoint 확정
|
||||
- 민감정보 없는 test fixture 사용
|
||||
|
||||
staging 승인 로그인 검증 절차:
|
||||
|
||||
- 상세 시나리오는 `docs/scenario_staging_baron_sso_login_verification_2026-07-06.md`를 따른다.
|
||||
|
||||
### Phase 5: 핵심 액션
|
||||
|
||||
필수 후보:
|
||||
|
||||
```bash
|
||||
./scripts/quality-gate.sh
|
||||
./scripts/perf_smoke.sh
|
||||
```
|
||||
|
||||
추가 예정:
|
||||
|
||||
- 전화걸기/문자보내기 URL 생성 테스트
|
||||
- 즐겨찾기 로컬 저장소 테스트
|
||||
|
||||
### Phase 6: 빌드/배포 준비
|
||||
|
||||
필수 후보:
|
||||
|
||||
```bash
|
||||
./scripts/generate-release-report.sh
|
||||
```
|
||||
|
||||
추가 예정:
|
||||
|
||||
- Android debug APK build wrapper
|
||||
- 수동 검증 체크리스트 자동 생성
|
||||
|
||||
## 4. 운영 원칙
|
||||
|
||||
- 문서에 명령을 추가할 때는 실제 `scripts/` 파일도 함께 추가하거나 scaffold 상태를 명시한다.
|
||||
- scaffold 스크립트는 조용히 성공하지 않고, 미구현이면 non-zero exit code로 종료한다.
|
||||
- 실제 CI gate에 연결할 수 있는 스크립트는 `quality-gate.sh`부터 시작한다.
|
||||
- AI/LLM redteam 자동화는 현재 앱 범위 밖이므로 `redteam/run_all.sh`는 보류 상태로 유지한다.
|
||||
- 자동화 스크립트 실행 결과는 `docs/test-logs/YYYY-MM-test-execution-log.md`에 월별로 누적 기록한다.
|
||||
|
||||
## 5. Playwright MCP 활용 예정
|
||||
|
||||
Playwright MCP는 향후 web/preview 기반 화면 확인이 가능해지는 시점부터 테스트 정책에 활용한다.
|
||||
|
||||
우선 적용 후보:
|
||||
|
||||
- 로그인 화면 smoke test
|
||||
- 직원목록/검색/가족사 필터 화면 회귀 확인
|
||||
- 직원 상세 화면 표시 확인
|
||||
- screenshot 기반 UI 리뷰 자료 생성
|
||||
- 텍스트 overflow, 주요 버튼 표시, 라우팅 이동 확인
|
||||
|
||||
현재는 Flutter web/preview 실행 방식이 확정되지 않았으므로 별도 `scripts/playwright-*` 파일은 만들지 않는다. 실행 방식이 확정되면 Playwright MCP 시나리오 문서와 월별 테스트 로그 기록 형식을 추가한다.
|
||||
|
||||
Playwright MCP 테스트 실행 전 절차:
|
||||
|
||||
1. 실행 가능한 Flutter web/preview 또는 Baron SSO 화면 대상이 준비되면 사용자에게 먼저 알리고 확인을 받는다.
|
||||
2. 사용자 확인 후 `docs/00_policy_tdc114plus_testing_2026-07-02.md`와 본 문서에 테스트 정의, 절차, 성공 기준, 로그 기록 방식을 추가한다.
|
||||
3. 문서 갱신 이후 Playwright MCP 테스트를 실행한다.
|
||||
4. 실행 결과는 `docs/test-logs/YYYY-MM-test-execution-log.md`에 누적 기록한다.
|
||||
@@ -0,0 +1,323 @@
|
||||
# Android 앱 설치/실행 재발 방지 정책
|
||||
|
||||
작성일: 2026-07-06
|
||||
상태: v1.4
|
||||
|
||||
목적: Windows Android Studio emulator + WSL/Docker Flutter 환경과 Android 공기계 USB 연결 환경에서 `tdc114plus` 앱을 테스트할 때, 환경값 누락과 ADB 연결 장애로 같은 문제를 반복하지 않도록 설치/실행 정책을 고정한다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- `docs/policy_android_studio_wsl_adb_2026-07-03.md`
|
||||
- `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
- `scripts/README.md`
|
||||
|
||||
## 1. 이번 장애 요약
|
||||
|
||||
2026-07-06에 아래 문제가 재현되었다.
|
||||
|
||||
- 최신 코드를 빌드한 뒤 `adb install`로 debug APK만 직접 설치했다.
|
||||
- 그러나 이 앱은 `TDC114_API_BASE` 같은 runtime 값을 `--dart-define`으로 받는다.
|
||||
- APK 직접 설치 방식은 이 값을 전달하지 못한다.
|
||||
- 결과적으로 앱은 기본값 `https://sso.example.invalid`를 바라보게 되었고, 직원 목록 API가 실패했다.
|
||||
- 사용자는 코드가 반영되지 않았거나 필터 버그가 남아 있다고 오해할 수 있었다.
|
||||
|
||||
핵심 원인:
|
||||
|
||||
- 문제는 코드 수정 자체가 아니라 `설치 방식이 앱의 runtime config 구조와 맞지 않은 것`이었다.
|
||||
|
||||
## 2. 필수 원칙
|
||||
|
||||
- `tdc114plus` Android 수동 검증 기본 경로는 `flutter run`이다.
|
||||
- `TDC114_API_BASE`가 필요한 앱 실행은 반드시 `dart-define` 포함 경로로 띄운다.
|
||||
- `adb install` 또는 APK 파일 직접 설치는 기본 검증 경로로 사용하지 않는다.
|
||||
- local Baron SSO 검증은 emulator 기준 `http://10.0.2.2:5000`을 사용한다.
|
||||
- 앱/API 버그 판단 전에는 먼저 `./scripts/api-smoke.sh`로 backend 상태를 확인한다.
|
||||
- Windows `adb.exe devices`에서 대상 emulator가 `device` 상태로 안정화되기 전에는 WSL/Docker Android 스크립트를 실행하지 않는다.
|
||||
- 2026-07-08 기준 Windows Android Studio emulator + Docker Flutter 표준 연결 방식은 `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037`이다.
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT>` 직접 연결 방식은 Windows ADB 서버 공유 방식이 실패하거나 integration test의 VM service port forwarding 이슈가 확인된 경우에만 보조 경로로 사용한다.
|
||||
- 2026-07-08 이후 신규 수동 기능점검의 기본 target은 가능하면 Android 공기계 USB 연결 방식으로 전환한다.
|
||||
- emulator 경로는 보조/fallback으로 보존하되, 물리 키보드 한글 입력이나 emulator portproxy 문제를 해결하기 위해 emulator 설정을 반복하지 않는다.
|
||||
- 공기계에서는 `10.0.2.2`를 사용할 수 없으므로 `adb reverse tcp:5000 tcp:5000` + `TDC114_API_BASE=http://127.0.0.1:5000`을 우선 사용한다.
|
||||
- USB 없는 독립형 실기기 검증에서는 `TDC114_API_BASE=https://<staging-or-production-host>`를 사용하고 `TDC114_SKIP_SESSION_BOOTSTRAP=true`로 로컬 bootstrap/mocking을 끈다.
|
||||
- 2026-07-08 이후 로그인과 데이터 소스를 분리해야 하면 `TDC114_AUTH_API_BASE`, `TDC114_DIRECTORY_API_BASE`, `TDC114_ORGANIZATION_API_BASE`를 별도로 지정할 수 있다. 값을 지정하지 않으면 모두 `TDC114_API_BASE`를 사용한다.
|
||||
|
||||
## 3. 허용 경로와 금지 경로
|
||||
|
||||
### 3.1 기본 허용 경로
|
||||
|
||||
공기계 USB 수동 기능점검을 우선한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local \
|
||||
TDC114_FLUTTER_DEVICE_ID=<PHYSICAL_DEVICE_ID> \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
사전 조건:
|
||||
|
||||
- Windows PowerShell `adb.exe devices`에서 공기계가 `device` 상태다.
|
||||
- `adb reverse tcp:5000 tcp:5000`이 적용되어 있다.
|
||||
- `scripts/.env.android-device.local`의 `TDC114_API_BASE`는 `http://127.0.0.1:5000`이다.
|
||||
|
||||
### 3.1-B USB 없는 독립형 실기기 허용 경로
|
||||
|
||||
staging 또는 production 공개 API에 직접 붙는 실기기 검증은 아래 경로를 사용한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.staging.local \
|
||||
TDC114_FLUTTER_DEVICE_ID=<PHYSICAL_DEVICE_ID> \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
사전 조건:
|
||||
|
||||
- `TDC114_API_BASE`는 `https://...` 공개 HTTPS Baron API 주소다.
|
||||
- 필요 시 로그인은 staging, 직원/조직 데이터는 production으로 분리 주입할 수 있다.
|
||||
- `TDC114_SKIP_SESSION_BOOTSTRAP=true`가 설정되어 있다.
|
||||
- 로그인은 앱의 `Baron SSO로 로그인` 버튼에서 Hosted Login을 열고, App Link callback과 PKCE token 교환으로 완료한다.
|
||||
- USB는 최초 설치/실행 후 분리 가능해야 한다.
|
||||
|
||||
### 3.1-A emulator fallback 허용 경로
|
||||
|
||||
emulator를 쓸 경우 아래 경로만 허용한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
용도:
|
||||
|
||||
- post-login 상태 수동 기능 점검
|
||||
- local API base URL 포함 실행
|
||||
- 실제 phone-login bootstrap 또는 mock fallback 포함 실행
|
||||
|
||||
실제 로그인 화면 검증이 필요하면 RP issuer/client/callback 값이 맞는지 확인한 뒤 `Baron SSO로 로그인` 버튼에서 외부 Hosted Login을 연다.
|
||||
|
||||
### 3.2 조건부 허용 경로
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
용도:
|
||||
|
||||
- integration smoke
|
||||
- post-login 가정 자동 검증
|
||||
|
||||
### 3.3 금지 경로
|
||||
|
||||
아래 방식은 정책상 기본 검증 경로로 금지한다.
|
||||
|
||||
```bash
|
||||
adb install app-debug.apk
|
||||
```
|
||||
|
||||
금지 이유:
|
||||
|
||||
- `TDC114_API_BASE`
|
||||
- `TDC114_PREAUTH_*`
|
||||
- `TDC114_SMOKE_USE_MOCK_DIRECTORY`
|
||||
|
||||
같은 runtime define 값이 전달되지 않는다.
|
||||
|
||||
예외:
|
||||
|
||||
- 단순 설치 가능 여부 확인
|
||||
- 패키지명 확인
|
||||
- manifest 수준 점검
|
||||
|
||||
이 경우에도 `기능 검증용 실행`으로 간주하지 않는다.
|
||||
|
||||
## 3-A. 직원검색 초기 기본값 정책
|
||||
|
||||
직원검색 첫 진입 시 기본값은 아래처럼 고정한다.
|
||||
|
||||
- 초기 조회 범위: 로그인 사용자의 회사급 범위
|
||||
- 상단 기본 노출 칩: 회사급 칩 + 본인팀 칩
|
||||
- 금지 동작: 앱 시작 직후 phone/name 재조회로 본인 1명 결과에 맞춰 초기 범위를 다시 팀 또는 개인 단위로 축소하는 로직
|
||||
|
||||
정책 이유:
|
||||
|
||||
- 첫 진입에서 사용자가 자기 자신만 보이면 디렉터리 앱 기본 UX와 맞지 않는다.
|
||||
- 조직/회사 단위 탐색이 시작점이어야 하고, 본인팀은 빠른 재선택용 칩으로 유지하면 충분하다.
|
||||
- `회사급 범위 조회`와 `본인팀 칩 고정 노출`은 서로 다른 정책이므로 둘 다 함께 유지해야 한다.
|
||||
|
||||
## 4. 실행 전 체크 순서
|
||||
|
||||
Android 기능점검 전에는 아래 순서를 고정한다.
|
||||
|
||||
### 4.1 공기계 USB 기본 순서
|
||||
|
||||
1. Windows PowerShell에서 `adb.exe devices` 확인
|
||||
2. 공기계가 `device` 상태인지 확인
|
||||
3. `./scripts/api-smoke.sh` 통과 확인
|
||||
4. `adb reverse tcp:5000 tcp:5000` 적용
|
||||
5. `scripts/check-android-device-env.sh` 통과 확인
|
||||
6. `manual-postlogin-run.sh` 실행
|
||||
|
||||
중단 기준:
|
||||
|
||||
- Windows `adb.exe devices`에서 공기계가 `unauthorized`이면 단말 RSA 승인 전까지 진행하지 않는다.
|
||||
- `adb reverse`가 실패하면 LAN IP 방식으로 바꾸기 전에는 `127.0.0.1:5000` 기준 앱 실행을 하지 않는다.
|
||||
- 앱에서 HTTP API가 차단되면 debug 전용 cleartext 허용 설정을 먼저 검토한다.
|
||||
|
||||
### 4.1-B USB 없는 독립형 실기기 순서
|
||||
|
||||
1. Windows PowerShell에서 `adb.exe devices` 확인
|
||||
2. 공기계 또는 실사용 폰이 `device` 상태인지 확인
|
||||
3. `TDC114_API_BASE=https://<staging-or-production-host>`로 env를 준비
|
||||
4. `TDC114_SKIP_SESSION_BOOTSTRAP=true` 상태로 `manual-postlogin-run.sh` 실행
|
||||
5. 앱 첫 화면에서 `Baron SSO로 로그인` 수행
|
||||
6. 문자 또는 메일의 링크 승인 완료
|
||||
7. `직원검색`, `organization/tenants`, `organization/orgchart` 화면 동작 확인
|
||||
8. 앱이 열린 뒤 USB를 분리하고 같은 동작이 유지되는지 재확인
|
||||
|
||||
중단 기준:
|
||||
|
||||
- 공개 HTTPS base URL이 확정되지 않았으면 진행하지 않는다.
|
||||
- Hosted Login, App Link callback, PKCE token 교환이 staging/production 환경에서 준비되지 않았으면 local mode로 되돌리지 않고 RP 설정과 서버 준비 상태를 먼저 맞춘다.
|
||||
- 승인 링크 수신 채널이 준비되지 않았으면 USB 없는 독립 검증 완료로 간주하지 않는다.
|
||||
|
||||
### 4.2 emulator fallback 순서
|
||||
|
||||
1. Windows PowerShell에서 `adb.exe devices` 확인
|
||||
2. 대상 emulator가 `device` 상태인지 확인
|
||||
3. `./scripts/api-smoke.sh` 통과 확인
|
||||
4. Windows ADB server `5037 -> 127.0.0.1:5037` portproxy와 방화벽 rule 확인
|
||||
5. 그 다음 `manual-postlogin-run.sh` 또는 `integration_tests.sh` 실행
|
||||
|
||||
중단 기준:
|
||||
|
||||
- Windows `adb.exe devices`에서 대상 emulator가 `offline`이면 WSL/Docker 스크립트를 실행하지 않는다.
|
||||
- Windows `adb.exe devices`가 `device`인데 Docker local ADB 직접 연결이 `offline`이면, 직접 emulator port 연결을 반복하지 않고 `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037` 방식으로 전환한다.
|
||||
- Android Studio Device Manager의 표시 이름과 실제 AVD 폴더 이름이 달라도, `C:\Users\user\.android\avd`에 저장된 AVD 수와 Windows `adb.exe devices` 상태를 우선 기준으로 삼는다.
|
||||
- AVD 프로세스가 `terminated`되거나 Android Studio가 `failed to connect within 5 minutes`를 표시하면 WSL/Docker 확인으로 넘어가지 않고 Windows 단독 emulator 부팅 안정화부터 처리한다.
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 앱이 local API 기준으로 실행된다
|
||||
- 직원검색 또는 로그인 화면이 기대한 경로로 열린다
|
||||
|
||||
## 5. 포트가 왜 바뀌는가
|
||||
|
||||
질문: 코드 수정이 생길 때마다 포트가 바뀌는가?
|
||||
|
||||
답: 아니다. `코드 수정 때문에 포트가 바뀌는 것이 아니다.`
|
||||
|
||||
포트가 바뀌는 이유는 보통 아래 중 하나다.
|
||||
|
||||
- 새 emulator 인스턴스를 띄웠다
|
||||
- 기존 emulator를 끄고 다른 emulator 번호로 다시 띄웠다
|
||||
- `emulator-5554`, `5556`, `5558`처럼 여러 인스턴스가 섞였다
|
||||
- Windows `portproxy`가 그 emulator의 adbd port와 맞지 않았다
|
||||
|
||||
즉:
|
||||
|
||||
- 코드 변경
|
||||
- Flutter rebuild
|
||||
- hot reload
|
||||
|
||||
이 자체는 emulator port를 바꾸지 않는다.
|
||||
|
||||
## 6. 반복 절차를 줄이는 고정 운영안
|
||||
|
||||
반복을 줄이기 위해 아래 운영안을 기본값으로 사용한다.
|
||||
|
||||
### 6.1 1대 고정 원칙
|
||||
|
||||
- 수동 검증용 emulator는 한 번에 1대만 켠다.
|
||||
- 기본 장비는 당일 Windows `adb.exe devices`에서 `device`로 확인된 emulator 1대다.
|
||||
- 다른 emulator가 `offline`으로 남아 있거나 여러 인스턴스가 섞이면 Android Studio/ADB 상태를 먼저 정리한다.
|
||||
|
||||
효과:
|
||||
|
||||
- 어떤 emulator가 현재 대상인지 혼선이 줄어든다.
|
||||
- `offline`/`refused` 원인 추적이 쉬워진다.
|
||||
|
||||
### 6.2 Windows ADB 서버 공유 원칙
|
||||
|
||||
- Docker/WSL Flutter는 기본적으로 Windows ADB server를 공유한다.
|
||||
- 표준 환경변수는 `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037`이다.
|
||||
- Windows 관리자 PowerShell에서 `0.0.0.0:5037 -> 127.0.0.1:5037` portproxy와 방화벽 rule을 유지한다.
|
||||
- Windows `adb.exe devices`에서 `emulator-5562 device`처럼 정상으로 보이면, Docker Flutter도 같은 Windows ADB server를 통해 장치를 인식해야 한다.
|
||||
- 직접 emulator adbd port 연결이 `offline`으로 반복되면 해당 방식은 중단하고 Windows ADB server 공유 방식만 사용한다.
|
||||
|
||||
효과:
|
||||
|
||||
- Docker container 내부 ADB key 불일치로 인한 `offline`/`unauthorized` 반복을 줄인다.
|
||||
- Windows에서 이미 정상 승인된 ADB 세션을 그대로 사용한다.
|
||||
|
||||
### 6.3 명시 emulator portproxy 원칙
|
||||
|
||||
- 수동 검증 포트는 Windows `adb.exe devices`에서 확인한 emulator port에 맞춘다.
|
||||
- 예: Windows 대상이 `emulator-5562`이면 `5562 -> 127.0.0.1:5562` portproxy와 방화벽 규칙을 확인한다.
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT>`는 보조 경로로만 명시한다.
|
||||
- shutdown/startup 스크립트는 과거 고정 포트를 임의로 disconnect하지 않는다.
|
||||
|
||||
효과:
|
||||
|
||||
- 실제 대상 포트와 스크립트 포트가 어긋나는 일을 줄인다.
|
||||
|
||||
### 6.4 APK 직접 설치 금지
|
||||
|
||||
- 코드 수정 후 수동 검증은 항상 `flutter run` 또는 `manual-postlogin-run.sh`
|
||||
- APK 직접 설치는 설치 확인용 보조 수단으로만 사용
|
||||
|
||||
효과:
|
||||
|
||||
- runtime define 누락 사고를 막는다.
|
||||
|
||||
### 6.5 같은 세션 재사용
|
||||
|
||||
- emulator를 켠 뒤 가능한 한 끄지 않는다.
|
||||
- `flutter run` 세션이 살아 있을 때는 hot reload/hot restart를 우선한다.
|
||||
- 큰 설정 변경이 아닐 때는 재설치보다 같은 세션 재사용을 우선한다.
|
||||
|
||||
효과:
|
||||
|
||||
- rebuild/install 시간과 ADB 재연결 횟수가 줄어든다.
|
||||
|
||||
## 7. 표준 명령
|
||||
|
||||
### 7.1 post-login 수동 기능점검
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
### 7.2 integration smoke
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
### 7.3 backend 상태 확인
|
||||
|
||||
```bash
|
||||
./scripts/api-smoke.sh
|
||||
```
|
||||
|
||||
## 8. 내일부터의 운영 기준
|
||||
|
||||
- Android 수동 검증 기본 target은 USB 연결 공기계다.
|
||||
- Android emulator는 fallback target으로 보존한다.
|
||||
- Docker/WSL 기본 연결은 `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037`로 명시한다.
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT>`는 직접 emulator port 연결이 필요한 예외 상황에만 사용
|
||||
- 실행 스크립트 기본값은 `manual-postlogin-run.sh`
|
||||
- `adb install`은 기능검증용 실행으로 인정하지 않음
|
||||
|
||||
이 기준을 어기면 다시 아래 오판이 발생할 수 있다.
|
||||
|
||||
- 코드 미반영으로 오해
|
||||
- API 장애로 오해
|
||||
- 필터 버그 미수정으로 오해
|
||||
@@ -0,0 +1,303 @@
|
||||
# Android Studio / WSL ADB 연동 재발 방지 정책
|
||||
|
||||
작성일: 2026-07-03
|
||||
상태: v1.3 Windows Android Studio emulator + WSL/Docker Flutter 기준
|
||||
|
||||
목적: Windows Android Studio emulator를 WSL 및 Docker 기반 Flutter CLI에서 사용할 때 발생한 ADB 연동 지연을 반복하지 않도록, 지연 원인과 동일 상황 발생 시 우선 처리 방식을 정책으로 고정한다.
|
||||
|
||||
관련 문서:
|
||||
|
||||
- `docs/troubleshooting/android-studio-wsl-adb-timetable-260703.md`
|
||||
- `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
- `docs/dev_env_tdc114plus_setup_plan_2026-07-02.md`
|
||||
|
||||
## 1. 적용 범위
|
||||
|
||||
본 정책은 아래 상황에 적용한다.
|
||||
|
||||
- Windows Android Studio에서 Android emulator를 실행한다.
|
||||
- Flutter CLI는 WSL 또는 Docker container 내부에서 실행한다.
|
||||
- WSL/Docker Flutter에서 Windows emulator 또는 Android device를 인식해야 한다.
|
||||
- `scripts/flutter-docker.sh devices` 또는 `scripts/integration_tests.sh`가 Android target을 필요로 한다.
|
||||
|
||||
아래 상황은 본 정책의 직접 적용 대상이 아니다.
|
||||
|
||||
- macOS 기반 iOS simulator
|
||||
- WSL 내부 Android emulator 직접 설치
|
||||
- 실기기만 사용하고 Windows ADB server를 거치지 않는 구성
|
||||
|
||||
## 2. 기본 원칙
|
||||
|
||||
- Windows Android Studio emulator를 사용할 때는 Windows `adb.exe` 기준으로 먼저 device 상태를 확인한다.
|
||||
- WSL에 Android SDK/ADB가 없다고 판단되면 WSL 내부 emulator 설치로 바로 우회하지 않는다.
|
||||
- `adb -a -P 5037 nodaemon server` 방식은 1차 시도만 허용한다.
|
||||
- `10048` bind 실패가 1회라도 재현되면 즉시 Windows `portproxy` 방식으로 전환한다.
|
||||
- Docker Flutter에는 `ADB_SERVER_SOCKET`을 명시적으로 전달한다.
|
||||
- 2026-07-08 확인 결과, Windows `adb.exe devices`가 `device`인데 Docker local ADB 직접 연결이 `offline`으로 반복될 수 있으므로 기본 연결은 `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037` 방식으로 한다.
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT>` 기반 Docker local ADB server 방식은 `ADB_SERVER_SOCKET` 방식으로 integration test가 실제로 막힐 때만 보조 경로로 사용한다.
|
||||
- Docker Flutter는 ADB key, Gradle, pub cache, Android SDK 하위 cache를 로컬 디렉터리에 유지한다.
|
||||
- Android emulator에서 host API에 접근할 때는 `127.0.0.1`이 아니라 `10.0.2.2`를 우선 사용한다.
|
||||
- Baron SSO backend, gateway, userfront, Ory runtime이 모두 살아 있는지 확인하기 전에는 Android 관련 테스트를 시작하지 않는다.
|
||||
- integration test 실행 전에는 host 기준 `./scripts/api-smoke.sh`를 먼저 통과시킨다.
|
||||
- 실행 결과와 장애 내용은 `docs/test-logs/YYYY-MM-test-execution-log.md`에 누적 기록한다.
|
||||
|
||||
## 3. 지연 원인
|
||||
|
||||
2026-07-03 작업에서 확인한 주요 지연 원인은 아래와 같다.
|
||||
|
||||
| 원인 | 영향 | 다음 대응 |
|
||||
| --- | --- | --- |
|
||||
| Windows ADB server가 `127.0.0.1:5037`에 먼저 바인딩됨 | WSL/Docker에서 직접 접근 불가 | `portproxy`로 `0.0.0.0:5037 -> 127.0.0.1:5037` 노출 |
|
||||
| Android Studio, Device Manager, emulator, ADB client가 ADB server를 자동 재기동 | 기존 PID 종료 후에도 `adb -a` 재시도 실패 반복 | `adb -a` 반복 시도 금지 |
|
||||
| `adb -a -P 5037 nodaemon server`가 `10048` 오류로 실패 | 외부 바인딩 방식 지연 | 1회 실패 후 `portproxy` 전환 |
|
||||
| WSL 내부에 `adb`, `java`, `sdkmanager`, `emulator`가 없음 | WSL 단독 Android 환경 전환 불가 | Windows Android Studio emulator 사용 유지 |
|
||||
| Docker container와 Windows ADB server의 localhost 의미가 다름 | integration test VM service dynamic port 연결 실패 가능 | 필요 시 당일 emulator adbd port를 노출 후 Docker local ADB server 방식 검증 |
|
||||
| Docker local ADB server가 새 ADB key를 생성 | emulator가 `unauthorized` 상태로 표시 | Windows 승인 ADB key를 git ignored `.android-adb/`에 재사용 |
|
||||
| Docker Flutter container가 매번 새로 생성됨 | NDK/CMake/Gradle/pub cache 재다운로드로 반복 지연 | `.docker-cache/flutter` 아래 cache volume 유지 |
|
||||
| `scripts/integration_tests.sh` 출력이 종료 후 표시되는 구조였음 | Android 첫 빌드 진행 상태 확인 어려움 | 실시간 출력 방식 유지 |
|
||||
|
||||
## 4. 동일 상황 발생 시 처리 순서
|
||||
|
||||
### 4.1 Windows emulator 준비
|
||||
|
||||
1. Windows Android Studio를 실행한다.
|
||||
2. Device Manager에서 emulator를 시작한다.
|
||||
3. Windows PowerShell에서 `adb.exe devices`를 확인한다.
|
||||
|
||||
```powershell
|
||||
& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" devices
|
||||
```
|
||||
|
||||
완료 기준:
|
||||
|
||||
- `emulator-5554 device` 또는 동일한 Android target이 `device` 상태로 표시된다.
|
||||
|
||||
### 4.2 `adb -a` 1차 시도
|
||||
|
||||
필요 시 아래 방식을 1회만 시도한다.
|
||||
|
||||
```powershell
|
||||
& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" -a -P 5037 nodaemon server
|
||||
```
|
||||
|
||||
아래 결과가 나오면 더 반복하지 않는다.
|
||||
|
||||
- `10048`
|
||||
- `0.0.0.0:5037` bind 실패
|
||||
- 기존 ADB PID 종료 후에도 동일 실패 반복
|
||||
|
||||
### 4.3 `portproxy` 전환
|
||||
|
||||
관리자 PowerShell에서 아래 명령을 적용한다.
|
||||
|
||||
```powershell
|
||||
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=5037 connectaddress=127.0.0.1 connectport=5037
|
||||
netsh advfirewall firewall add rule name="ADB 5037 for WSL" dir=in action=allow protocol=TCP localport=5037
|
||||
netsh interface portproxy show v4tov4
|
||||
```
|
||||
|
||||
WSL에서 Windows host IP를 확인한다.
|
||||
|
||||
```bash
|
||||
awk '/nameserver/ {print $2; exit}' /etc/resolv.conf
|
||||
```
|
||||
|
||||
이번 환경의 예시는 아래와 같다.
|
||||
|
||||
```bash
|
||||
172.21.128.1
|
||||
```
|
||||
|
||||
### 4.4 WSL/Docker 연결 확인
|
||||
|
||||
WSL에서 TCP 연결을 먼저 확인한다.
|
||||
|
||||
```bash
|
||||
nc -vz <WINDOWS_HOST_IP> 5037
|
||||
```
|
||||
|
||||
Docker Flutter에서 device 인식을 확인한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 ./scripts/flutter-docker.sh devices
|
||||
```
|
||||
|
||||
완료 기준:
|
||||
|
||||
- Android emulator가 Flutter devices 목록에 표시된다.
|
||||
- Linux desktop만 보이면 Android target 준비가 완료되지 않은 상태로 판단한다.
|
||||
|
||||
### 4.4-A Flutter/Docker 표준 연결 방식
|
||||
|
||||
기본 device 인식, 앱 실행, APK 설치 확인은 아래 방식을 표준으로 사용한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 ./scripts/flutter-docker.sh devices
|
||||
```
|
||||
|
||||
정책 기준:
|
||||
|
||||
- `5037 remote Windows ADB server` 방식은 현재 Windows emulator 연동의 기본 경로다.
|
||||
- Windows에서 이미 `device`로 승인된 ADB 세션을 Docker Flutter가 공유한다.
|
||||
- Docker local ADB가 직접 emulator port에 붙었을 때 `offline`이 반복되면 더 반복하지 않는다.
|
||||
- 직접 emulator port 연결은 아래 보조 경로로만 둔다.
|
||||
|
||||
보조 경로:
|
||||
|
||||
```bash
|
||||
TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT> ./scripts/flutter-docker.sh devices
|
||||
```
|
||||
|
||||
### 4.5 Android emulator API 주소
|
||||
|
||||
Android emulator에서 host machine API를 호출할 때는 아래 주소를 사용한다.
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=http://10.0.2.2:5000
|
||||
```
|
||||
|
||||
emulator용 local env 파일 예시는 아래와 같다.
|
||||
|
||||
```text
|
||||
scripts/.env.android-emulator.local
|
||||
```
|
||||
|
||||
민감정보가 포함될 수 있으므로 해당 파일은 git tracked 파일로 추가하지 않는다.
|
||||
|
||||
## 5. Integration test 추가 분기
|
||||
|
||||
`ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037` 방식은 device 목록 확인과 APK 설치까지는 가능할 수 있다. 다만 Flutter integration test loading 단계에서 VM service dynamic port 연결이 실패할 수 있다.
|
||||
|
||||
대표 증상:
|
||||
|
||||
```text
|
||||
WebSocketChannelException
|
||||
127.0.0.1:<dynamic port> connection refused
|
||||
```
|
||||
|
||||
이 경우 원인은 remote Windows ADB server가 만든 port forward의 `127.0.0.1`이 Docker container 내부 localhost와 일치하지 않는 구조일 가능성이 높다.
|
||||
|
||||
동일 증상이 실제로 발생한 경우에만 아래 순서로 보조 경로 전환을 검토한다.
|
||||
|
||||
1. Windows 관리자 PowerShell에서 emulator adbd port를 노출한다.
|
||||
|
||||
```powershell
|
||||
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=<EMULATOR_PORT> connectaddress=127.0.0.1 connectport=<EMULATOR_PORT>
|
||||
netsh advfirewall firewall add rule name="ADB emulator <EMULATOR_PORT> for WSL" dir=in action=allow protocol=TCP localport=<EMULATOR_PORT>
|
||||
netsh interface portproxy show v4tov4
|
||||
```
|
||||
|
||||
2. WSL에서 `<EMULATOR_PORT>` 연결을 확인한다.
|
||||
|
||||
```bash
|
||||
nc -vz <WINDOWS_HOST_IP> <EMULATOR_PORT>
|
||||
```
|
||||
|
||||
3. Docker container 내부 local ADB server가 emulator adbd에 직접 붙는지 확인한다.
|
||||
|
||||
```bash
|
||||
docker run --rm ghcr.io/cirruslabs/flutter:stable sh -lc 'adb connect <WINDOWS_HOST_IP>:<EMULATOR_PORT> && adb devices'
|
||||
```
|
||||
|
||||
4. 이 방식이 성공하면 `scripts/flutter-docker.sh` 또는 `scripts/integration_tests.sh`에 선택 환경변수를 추가한다.
|
||||
|
||||
예상 환경변수:
|
||||
|
||||
```bash
|
||||
TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT>
|
||||
```
|
||||
|
||||
5. Docker local ADB가 `unauthorized`이면 Windows에서 이미 승인된 ADB key를 재사용한다.
|
||||
|
||||
```bash
|
||||
mkdir -p .android-adb
|
||||
cp /mnt/c/Users/user/.android/adbkey .android-adb/adbkey.new
|
||||
cp /mnt/c/Users/user/.android/adbkey.pub .android-adb/adbkey.pub.new
|
||||
mv -f .android-adb/adbkey.new .android-adb/adbkey
|
||||
mv -f .android-adb/adbkey.pub.new .android-adb/adbkey.pub
|
||||
chmod 600 .android-adb/adbkey
|
||||
```
|
||||
|
||||
6. 위 방식이 `device` 상태를 만들면 integration test는 아래 명령을 기본값으로 사용한다.
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT> \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
## 5-A. API smoke 선행 원칙
|
||||
|
||||
Android integration test 전에 아래 명령을 먼저 실행한다.
|
||||
|
||||
```bash
|
||||
./scripts/check-baron-api-env.sh
|
||||
./scripts/api-smoke.sh
|
||||
```
|
||||
|
||||
판정 기준:
|
||||
|
||||
- `./scripts/check-baron-api-env.sh`가 failure 0, warning 0 상태여야 한다.
|
||||
- 최소한 아래 runtime이 running 또는 healthy 상태여야 한다.
|
||||
- `baron_backend`
|
||||
- `baron_gateway`
|
||||
- `baron_userfront`
|
||||
- `ory_kratos`
|
||||
- `ory_hydra`
|
||||
- `ory_keto`
|
||||
- `ory_oathkeeper`
|
||||
- `ory_postgres`
|
||||
- phone-login, employee list, tenant list, orgchart가 모두 HTTP 200이어야 한다.
|
||||
- unauthorized directory guard는 HTTP 401 또는 403이어야 한다.
|
||||
|
||||
실패 시 처리:
|
||||
|
||||
- `./scripts/check-baron-api-env.sh`에서 warning이 나오면 Android test보다 runtime 복구를 우선한다.
|
||||
- `502 Bad Gateway`가 나오면 Baron/Ory runtime 중단 가능성을 먼저 의심한다.
|
||||
- `./scripts/check-baron-api-env.sh`로 상태를 본다.
|
||||
- `baron_backend`, `baron_userfront`, `ory_*` 컨테이너를 복구한 뒤 integration test를 재시도한다.
|
||||
- `orgFront` 관련 API 확인이 필요한 경우에도 같은 원칙을 적용해 backend/gateway/userfront를 모두 확인한 뒤 진행한다.
|
||||
|
||||
## 5-B. Docker cache 유지 원칙
|
||||
|
||||
반복 실행 시 NDK/CMake/Gradle/pub cache 재설치를 막기 위해 `scripts/flutter-docker.sh`는 아래 로컬 cache 디렉터리를 유지한다.
|
||||
|
||||
- `.docker-cache/flutter/gradle`
|
||||
- `.docker-cache/flutter/pub`
|
||||
- `.docker-cache/flutter/android-sdk/licenses`
|
||||
- `.docker-cache/flutter/android-sdk/ndk`
|
||||
- `.docker-cache/flutter/android-sdk/cmake`
|
||||
|
||||
운영 원칙:
|
||||
|
||||
- 위 cache 디렉터리는 git tracked 파일로 추가하지 않는다.
|
||||
- cache가 손상되지 않는 한 수동 삭제하지 않는다.
|
||||
- Flutter Docker image를 바꾸더라도 우선 기존 cache와 호환되는지 확인한다.
|
||||
- cache가 꼬여 비정상 빌드가 반복되면 해당 하위 디렉터리만 선별 삭제한다.
|
||||
|
||||
## 6. 금지 또는 제한 사항
|
||||
|
||||
- `adb -a -P 5037 nodaemon server` 실패 후 동일 명령을 여러 번 반복하지 않는다.
|
||||
- Windows ADB PID를 계속 종료하면서 원인 확인 없이 시간을 쓰지 않는다.
|
||||
- WSL에 `adb`, Java, Android SDK, `/dev/kvm` 조건이 없는데 WSL 내부 emulator 설치로 즉시 전환하지 않는다.
|
||||
- 민감정보가 포함된 `.env.*.local` 파일을 git tracked 파일로 추가하지 않는다.
|
||||
- `.android-adb/`, `.docker-cache/`를 git tracked 파일로 추가하지 않는다.
|
||||
- Android emulator API base에 `http://127.0.0.1:5000`을 기본값으로 쓰지 않는다.
|
||||
- `5037 remote ADB server` 방식에서 integration test VM service 실패가 재현됐는데 같은 방식만 반복하지 않는다.
|
||||
|
||||
## 7. 완료 체크리스트
|
||||
|
||||
다음 항목을 모두 만족하면 Android Studio / WSL ADB 연동 준비가 완료된 것으로 본다.
|
||||
|
||||
- Windows `adb.exe devices`에서 emulator가 `device` 상태다.
|
||||
- `netsh interface portproxy show v4tov4`에 `5037` mapping이 존재한다.
|
||||
- integration test에서 직접 연결 보조 경로가 필요하면 `netsh interface portproxy show v4tov4`에 당일 `<EMULATOR_PORT>` mapping도 존재한다.
|
||||
- WSL에서 `<WINDOWS_HOST_IP>:5037` TCP 연결이 성공한다.
|
||||
- `ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 ./scripts/flutter-docker.sh devices`에서 Android target이 표시된다.
|
||||
- 보조 경로 사용 시 `TDC114_ADB_CONNECT_ADDRESS=<WINDOWS_HOST_IP>:<EMULATOR_PORT> ./scripts/flutter-docker.sh devices`에서 Android target이 `device` 상태로 표시된다.
|
||||
- emulator용 API base가 `http://10.0.2.2:5000`으로 설정되어 있다.
|
||||
- `./scripts/check-baron-api-env.sh`가 warning 없이 통과한다.
|
||||
- host 기준 `./scripts/api-smoke.sh`가 통과한다.
|
||||
- integration test에서 VM service dynamic port 실패가 발생하면 당일 `<EMULATOR_PORT>` local ADB server 방식으로 분기한다.
|
||||
- `.android-adb/`, `.docker-cache/`가 로컬에 유지되고 git tracked 상태가 아니다.
|
||||
- 결과를 `docs/test-logs/YYYY-MM-test-execution-log.md`에 기록한다.
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"relation": [
|
||||
"delegate_permission/common.handle_all_urls"
|
||||
],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "kr.co.baron.tdc114plus",
|
||||
"sha256_cert_fingerprints": [
|
||||
"3A:2D:60:48:6F:E5:3A:84:0C:41:14:DC:3A:17:A4:3B:64:E7:DE:A5:10:4A:09:26:0E:DC:5F:49:88:44:71:76"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"relation": [
|
||||
"delegate_permission/common.handle_all_urls"
|
||||
],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "kr.co.baron.tdc114plus",
|
||||
"sha256_cert_fingerprints": [
|
||||
"3A:2D:60:48:6F:E5:3A:84:0C:41:14:DC:3A:17:A4:3B:64:E7:DE:A5:10:4A:09:26:0E:DC:5F:49:88:44:71:76"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1863
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
삼안 직접 소속 판정 요약 (2026-07-16)
|
||||
selected_tenant_name=삼안
|
||||
selected_tenant_slug=saman
|
||||
selected_tenant_memberCount_raw=0
|
||||
selected_tenant_totalMemberCount_raw=None
|
||||
current_app_direct_employee_count=1862
|
||||
|
||||
[현재 앱 직접 소속 판정식]
|
||||
employee.tenantSlug == selectedTenant.slug
|
||||
AND (employee.department is empty OR employee.department == selectedTenant.name)
|
||||
|
||||
[이번 삼안 데이터에서 걸린 이유]
|
||||
- department_empty: 1862
|
||||
|
||||
[직급 상위 20]
|
||||
- <empty>: 1845
|
||||
- 부사장: 14
|
||||
- 사장: 1
|
||||
- 이사: 1
|
||||
- 회장: 1
|
||||
|
||||
[직위 상위 20]
|
||||
- <empty>: 1861
|
||||
- 대표이사: 1
|
||||
|
||||
[판단 메모]
|
||||
- 1862명 전원이 source_tenant_slug=saman에서 내려온 members다.
|
||||
- 1862명 전원의 employee_department_raw가 빈 문자열이다.
|
||||
- 따라서 현재 앱 로직에서는 1862명 전원이 직접 소속으로 분류된다.
|
||||
- 이 집합에서 직위가 확인되는 값은 대표이사 1건뿐이며, 나머지 1861건은 직위가 비어 있다.
|
||||
|
||||
|
||||
[대안별 예상 인원 수]
|
||||
- 현재 앱 직접 소속 규칙 유지: 1862명
|
||||
- 다른 하위조직 membership이 없는 루트 전용 인원만 사용: 17명
|
||||
- 임원/대표이사급만 사용: 17명
|
||||
- 이번 삼안 데이터에서는 `루트 전용 17명`과 `임원/대표이사급 17명`이 동일 집합이다.
|
||||
@@ -0,0 +1,18 @@
|
||||
employee_id,employee_name,employee_email,membership_count_across_tenants,has_non_saman_membership,non_saman_memberships
|
||||
ba92e160-684c-4705-8b65-ff6087979b24,공병승,bskong@samaneng.com,1,N,
|
||||
e8ce81d7-f682-4f7b-8ea8-75de62eac7ea,곽병구,bgkwak1@samaneng.com,1,N,
|
||||
f3469d30-5c83-4171-b71e-93509feb5873,권현진,hjkwon2@samaneng.com,1,N,
|
||||
26bc52b9-8e06-4a6d-935d-e857500dfaf3,김대수,dskim@samaneng.com,1,N,
|
||||
3bf6cd28-480a-414e-8aae-62fddc6215ab,김봉식,bskim5@samaneng.com,1,N,
|
||||
d6283634-9159-4ecd-b121-930b952b3ca5,김정만,jmkim1@samaneng.com,1,N,
|
||||
995a96bc-ec0b-45a0-a780-d0a8198af86c,박승양,sypark@samaneng.com,1,N,
|
||||
a1b4a6ea-d783-43f2-8ded-dd9400c9dd73,박호식,hspark3@samaneng.com,1,N,
|
||||
63e8ad9f-2b6f-4faa-b8ae-3d47875748f5,서동석,dsseo1@samaneng.com,1,N,
|
||||
bfefd442-f625-4537-8e72-56f919764ea1,서정택,jtseo@samaneng.com,1,N,
|
||||
a5226e20-64a6-4882-8650-b1bd021fd925,신정하,jhshin2@samaneng.com,1,N,
|
||||
fdbe4d03-221c-4966-b37e-fb4f8557420e,여형구,hgyeo@samaneng.com,1,N,
|
||||
59aa19b6-3223-48e8-825c-ec0b8ab342df,정갑균,ggjeong@samaneng.com,1,N,
|
||||
56ee2c75-0a33-440e-9852-7cb02d62d482,정홍섭,hsjeong2@samaneng.com,1,N,
|
||||
c54a8119-e1b2-4767-90ca-d45b2eac65f8,조호연,hycho@samaneng.com,1,N,
|
||||
fa3d0d72-e1cc-4101-8e95-dbe13a561a4f,최대선,dschoi@samaneng.com,1,N,
|
||||
d0209fc9-dfbe-4411-ada2-3d02929f6b99,최동식,dschoi16@samaneng.com,1,N,
|
||||
|
@@ -0,0 +1,204 @@
|
||||
# Android 공기계 로컬 USB 테스트 전환 검토
|
||||
|
||||
작성일: 2026-07-08
|
||||
상태: 검토 완료
|
||||
|
||||
## 1. 목적
|
||||
|
||||
기존 Windows Android Studio emulator + WSL/Docker Flutter 기반 테스트는 유지하되, 앞으로의 기본 수동/통합 테스트 경로를 "집에서 가져온 Android 공기계 + 로컬 PC USB 연결" 방식으로 전환할 수 있는지 검토한다.
|
||||
|
||||
이번 검토의 범위는 아래와 같다.
|
||||
|
||||
- 현재 저장소에서 emulator 전용 가정이 어디에 있는지 확인
|
||||
- 공기계 연결 방식으로 바꿀 때 유지 가능한 코드와 추가 필요한 보강점을 구분
|
||||
- 실제 전환 시 가장 작은 변경 경로를 제안
|
||||
|
||||
## 2. 결론 요약
|
||||
|
||||
- 앱 코드 자체는 공기계 테스트로 전환 가능한 구조다. 실행 시점에 `TDC114_API_BASE`를 `--dart-define`으로 주입하는 방식이라 target만 안정적으로 잡히면 emulator와 device를 공용으로 사용할 수 있다.
|
||||
- 현재 가장 강하게 emulator에 묶여 있는 부분은 앱 로직이 아니라 운영 스크립트와 문서다.
|
||||
- 공기계 전환의 핵심 이점은 Windows emulator portproxy, Docker local ADB, remote ADB server, VM service dynamic port 문제를 대부분 피할 수 있다는 점이다.
|
||||
- 다만 실기기에서는 emulator 전용 주소 `10.0.2.2`를 쓸 수 없고, 로컬 HTTP 접근은 Android cleartext 정책에 막힐 가능성이 높다.
|
||||
- 따라서 "기존 emulator 코드는 유지"하면서도, 앞으로는 실기기용 env/체크 스크립트/실행 절차를 별도로 추가하는 방식이 가장 안전하다.
|
||||
|
||||
## 3. 현재 코드/스크립트 구조에서 확인한 사항
|
||||
|
||||
### 3.1 target 선택 자체는 이미 공용화되어 있음
|
||||
|
||||
- `scripts/integration_tests.sh`
|
||||
- `TDC114_FLUTTER_DEVICE_ID` 또는 `TDC114_ADB_CONNECT_ADDRESS`가 있으면 해당 target으로 실행한다.
|
||||
- 즉, Flutter가 실기기를 인식하기만 하면 integration test 명령 자체는 재사용 가능하다.
|
||||
- `scripts/manual-postlogin-run.sh`
|
||||
- `TDC114_FLUTTER_DEVICE_ID` 또는 `TDC114_ADB_CONNECT_ADDRESS` 기반으로 `flutter run -d <device>`를 실행한다.
|
||||
- 수동 점검 경로도 공기계 전환에 재사용 가능하다.
|
||||
- `scripts/flutter-docker.sh`
|
||||
- `ADB_SERVER_SOCKET`, `TDC114_ADB_CONNECT_ADDRESS`를 Docker에 전달한다.
|
||||
- 구조상 device 연결 경로도 수용할 수 있다.
|
||||
|
||||
### 3.2 실제로는 preflight와 운영 정책이 emulator 기준임
|
||||
|
||||
- `scripts/check-android-emulator-env.sh`
|
||||
- 이름부터 emulator 전용이다.
|
||||
- Windows Android Studio, Device Manager, portproxy, emulator GUI 복구 절차를 전제로 한다.
|
||||
- `scripts/startup.sh`
|
||||
- 기본 Android precheck 스크립트가 `check-android-emulator-env.sh`로 고정돼 있다.
|
||||
- 문서 다수
|
||||
- `docs/checklist_morning_startup_runtime_2026-07-03.md`
|
||||
- `docs/policy_android_studio_wsl_adb_2026-07-03.md`
|
||||
- `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
- 위 문서들은 현재 운영 중심축이 emulator임을 보여준다.
|
||||
|
||||
### 3.3 emulator 전용 API 주소 가정이 남아 있음
|
||||
|
||||
- `scripts/integration_tests.sh`
|
||||
- bootstrap용 base URL에서 `10.0.2.2 -> 127.0.0.1` 치환을 수행한다.
|
||||
- `scripts/manual-postlogin-run.sh`
|
||||
- 동일하게 `10.0.2.2 -> 127.0.0.1` 치환을 수행한다.
|
||||
- 문서 전반
|
||||
- emulator env는 `TDC114_API_BASE=http://10.0.2.2:5000`을 표준으로 본다.
|
||||
|
||||
이 부분은 "실기기에서 무엇을 쓸지"만 정하면 큰 문제는 아니다. 실기기는 아래 둘 중 하나면 된다.
|
||||
|
||||
- `adb reverse tcp:5000 tcp:5000` 후 `http://127.0.0.1:5000`
|
||||
- 같은 LAN에서 `http://<PC_LAN_IP>:5000`
|
||||
|
||||
## 4. 공기계 전환 시 기대 효과
|
||||
|
||||
### 4.1 사라지거나 크게 줄어드는 문제
|
||||
|
||||
- Windows emulator GUI 상태 의존
|
||||
- `5037` ADB server 공유 문제
|
||||
- `5555`/`5557`/`5559` 같은 emulator adbd portproxy 관리
|
||||
- Docker 내부 local ADB key와 Windows ADB key 불일치
|
||||
- remote Windows ADB server가 만든 VM service dynamic port가 Docker localhost와 어긋나는 문제
|
||||
|
||||
즉, 지금까지 반복된 문제의 상당수는 "앱" 문제가 아니라 "Windows emulator를 WSL/Docker Flutter에서 원격으로 다루는 구조"에서 생겼다. USB 실기기는 이 복잡도를 상당히 낮춘다.
|
||||
|
||||
### 4.2 새로 관리해야 하는 문제
|
||||
|
||||
- 공기계의 USB 디버깅/RSA 승인 상태
|
||||
- `adb reverse` 재설정 필요 여부
|
||||
- 단말과 PC가 같은 네트워크인지 여부(LAN IP 방식일 때)
|
||||
- Android의 cleartext HTTP 허용 여부
|
||||
|
||||
## 5. 가장 중요한 기술 리스크
|
||||
|
||||
### 5.1 Android cleartext HTTP 차단 가능성
|
||||
|
||||
현재 `app/android/app/src/main/AndroidManifest.xml`에는 아래가 없다.
|
||||
|
||||
- `android:usesCleartextTraffic="true"`
|
||||
- debug용 `network_security_config`
|
||||
|
||||
로컬 Baron API는 현재 문서와 스크립트 기준으로 주로 `http://127.0.0.1:5000`, `http://10.0.2.2:5000`, `http://<PC_LAN_IP>:5000`를 사용한다. 실기기에서 debug APK를 띄웠을 때 Android 버전에 따라 cleartext가 차단될 수 있다.
|
||||
|
||||
따라서 공기계 전환 전에 가장 먼저 확인할 항목은 이것이다.
|
||||
|
||||
1. 공기계에서 `flutter run --dart-define=TDC114_API_BASE=http://127.0.0.1:5000` 또는 LAN IP로 실행
|
||||
2. 로그인/디렉토리 API 호출이 실제로 되는지 확인
|
||||
3. 차단되면 debug 전용 cleartext 허용 설정 추가
|
||||
|
||||
### 5.2 `adb reverse`와 Docker 컨테이너 내부 ADB의 관계
|
||||
|
||||
실기기에서 가장 단순한 API 접근 방식은 `adb reverse tcp:5000 tcp:5000`이다. 다만 현재 테스트 명령은 `scripts/flutter-docker.sh`를 통해 Docker 컨테이너 안에서 실행되는 경우가 많다.
|
||||
|
||||
검토 시점 기준으로 확인된 점:
|
||||
|
||||
- `flutter drive`/`flutter run`은 Docker 내부에서 수행된다.
|
||||
- `adb reverse`를 누가 실행하느냐에 따라 적용 대상이 달라질 수 있다.
|
||||
|
||||
따라서 실무상 가장 안전한 기준은 아래 순서다.
|
||||
|
||||
1. 먼저 Windows 또는 WSL host에서 `adb devices`로 공기계가 `device` 상태인지 확인
|
||||
2. 같은 ADB 경로에서 `adb reverse tcp:5000 tcp:5000` 실행
|
||||
3. 이후 Docker Flutter가 동일 device를 보는지 확인
|
||||
|
||||
만약 Docker 내부 ADB와 host ADB가 서로 다른 서버/세션을 쓰면 `adb reverse`가 예상대로 먹지 않을 수 있다. 그 경우에는 LAN IP 방식을 백업 경로로 잡는 것이 안전하다.
|
||||
|
||||
## 6. 변경 영향 검토
|
||||
|
||||
### 6.1 그대로 재사용 가능한 것
|
||||
|
||||
- `app/` 내부 Dart 앱 코드 대부분
|
||||
- `app/integration_test/app_smoke_test.dart`
|
||||
- `app/test_driver/integration_driver.dart`
|
||||
- `scripts/api-smoke.sh`
|
||||
- `scripts/check-baron-api-env.sh`
|
||||
- `scripts/integration_tests.sh`의 기본 실행 구조
|
||||
- `scripts/manual-postlogin-run.sh`의 post-login seed 구조
|
||||
|
||||
### 6.2 공기계 기준으로 별도 추가하는 편이 좋은 것
|
||||
|
||||
- 실기기 전용 env 예시
|
||||
- `scripts/.env.android-device.local`는 이미 문서상 가정만 있고 tracked example은 부족하다.
|
||||
- 실기기 preflight 스크립트
|
||||
- 예: `scripts/check-android-device-env.sh`
|
||||
- 실기기 실행 가이드 문서
|
||||
- USB 디버깅, RSA 승인, `adb reverse`, LAN IP fallback 포함
|
||||
|
||||
### 6.3 나중에 일반화하면 좋은 것
|
||||
|
||||
- `check-android-emulator-env.sh`를 유지한 채, 상위 래퍼 `check-android-target-env.sh`를 만들어
|
||||
- `TDC114_ANDROID_TARGET_KIND=emulator|device`
|
||||
- 또는 env 유무 기준으로 분기
|
||||
- `startup.sh`에서 precheck script를 교체 가능하게 유지하되, 기본 정책 문구를 "Android target" 기준으로 일반화
|
||||
|
||||
## 7. 권장 전환 방식
|
||||
|
||||
기존 emulator 코드는 그대로 두고 아래 순서로 가는 것을 권장한다.
|
||||
|
||||
1. 이번 테스트까지만 기존 emulator 경로 사용
|
||||
2. 그 다음부터는 공기계를 기본 target으로 사용
|
||||
3. 초기에는 `manual-postlogin-run.sh` 중심으로 수동 기능점검부터 안정화
|
||||
4. 그 다음 `integration_tests.sh`를 공기계 target으로 재사용
|
||||
5. 충분히 안정화된 뒤에만 `startup.sh` 기본 Android precheck를 실기기 기준으로 확장
|
||||
|
||||
## 8. 최소 실행 초안
|
||||
|
||||
### 8.1 공기계 수동 점검
|
||||
|
||||
```bash
|
||||
# 1) 공기계 USB 연결 후 host에서 device 확인
|
||||
adb devices
|
||||
|
||||
# 2) reverse 방식 선택 시
|
||||
adb reverse tcp:5000 tcp:5000
|
||||
|
||||
# 3) 실기기용 env 준비
|
||||
# scripts/.env.android-device.local
|
||||
TDC114_API_BASE=http://127.0.0.1:5000
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
|
||||
# 4) 앱 실행
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local \
|
||||
TDC114_FLUTTER_DEVICE_ID=<physical_device_id> \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
### 8.2 공기계 integration test
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local \
|
||||
TDC114_FLUTTER_DEVICE_ID=<physical_device_id> \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
LAN IP 방식을 쓰는 경우 env의 `TDC114_API_BASE`만 `http://<PC_LAN_IP>:5000`로 바꾼다.
|
||||
|
||||
## 9. 최종 판단
|
||||
|
||||
공기계 전환은 타당하다. 현재 막힌 문제의 대부분은 emulator 자체보다도 "Windows emulator + WSL/Docker Flutter + 원격 ADB/portproxy" 조합에서 발생했다.
|
||||
|
||||
따라서 다음 기본 방침은 합리적이다.
|
||||
|
||||
- emulator 경로는 보존
|
||||
- 앞으로의 기본 테스트는 공기계 USB 연결 방식으로 전환
|
||||
- 초기 목표는 "수동 post-login 점검 안정화"
|
||||
- 그 다음 "integration_tests.sh 공기계 재사용"
|
||||
|
||||
단, 실전 전환 전에 반드시 먼저 확인할 항목은 아래 2개다.
|
||||
|
||||
1. 공기계에서 local HTTP API가 cleartext 차단 없이 실제 호출되는가
|
||||
2. `adb reverse`가 Docker Flutter 실행 경로에서도 안정적으로 유지되는가
|
||||
|
||||
이 2개가 통과하면 emulator 대비 운영 복잡도는 확실히 낮아질 가능성이 높다.
|
||||
@@ -0,0 +1,159 @@
|
||||
# Baron SSO 레포/커밋 운영 검토
|
||||
|
||||
작성일: 2026-07-15
|
||||
상태: review
|
||||
|
||||
목적: `tdc114plus` 앱 저장소와 Baron SSO 관련 소스코드의 저장소 분리 여부, 커밋 정책, 로컬 빌드 부담 완화 방안을 함께 검토한다.
|
||||
|
||||
## 1. 현재 상태 요약
|
||||
|
||||
- `tdc114plus`는 현재 별도 Gitea 저장소(`https://gitea.hmac.kr/kevin/tdc114plus.git`)에서 관리 중이다.
|
||||
- 앱 저장소의 정책 문서에는 이미 `Baron SSO backend/orgFront 변경과 tdc114plus Flutter 앱 변경은 저장소와 커밋을 분리한다`는 원칙이 들어 있다.
|
||||
- Baron SSO 참조 기준 문서에는 공식 Baron SSO 저장소 `origin/dev`를 기준으로 보고, 실제 수정이 필요하면 `/home/ubuntu/workspace/baron-sso-tdc114plus-api` worktree의 `feature/tdc114plus-api` 브랜치에서 작업하도록 정리돼 있다.
|
||||
- 즉, 방향성 자체는 이미 “분리 관리” 쪽으로 잡혀 있으나, Gitea 상의 장기 운영 단위와 커밋 연결 규칙은 아직 명문화가 약하다.
|
||||
|
||||
## 2. 검토 결론
|
||||
|
||||
### 2.1 Baron SSO 관련 별도 Gitea 저장소 생성 필요 여부
|
||||
|
||||
결론:
|
||||
|
||||
- "완전히 새로운 독립 저장소"를 지금 즉시 만들어야 하는 수준의 필수 사항은 아니다.
|
||||
- 다만 `tdc114plus` 대응용 Baron SSO 변경을 장기간 추적할 계획이라면, Gitea 상에서 팀이 명확히 보이는 관리 단위는 꼭 두는 편이 좋다.
|
||||
|
||||
권장안:
|
||||
|
||||
1. 최우선 권장: 기존 Baron SSO 공식 저장소를 기준으로 하고, 팀/개인 fork에서 `feature/tdc114plus-*` 브랜치 규칙으로 관리한다.
|
||||
2. 차선 권장: Baron SSO 수정이 계속 누적되고 담당자/릴리스 이력이 분리되어야 하면, Gitea에 `baron-sso-tdc114plus` 성격의 전용 fork 또는 전용 미러 저장소를 둔다.
|
||||
3. 비권장: Baron SSO 코드를 `tdc114plus` 앱 저장소 안으로 복사하거나 subtree/submodule처럼 강결합해 같이 버전 관리한다.
|
||||
|
||||
판단 이유:
|
||||
|
||||
- 현재 문서와 스크립트는 이미 Baron SSO를 외부 worktree로 전제하고 있다.
|
||||
- 앱 저장소와 Baron SSO 저장소를 섞으면 커밋 단위, 리뷰 단위, 배포 책임이 흐려진다.
|
||||
- 반대로 완전 별도 저장소를 새로 만들더라도 upstream 동기화 책임이 생기므로, 운영 이점이 분명할 때만 택하는 것이 좋다.
|
||||
|
||||
### 2.2 커밋 정책 수립 필요 여부
|
||||
|
||||
결론:
|
||||
|
||||
- 필요하다.
|
||||
- 특히 앱 저장소와 Baron SSO 저장소를 동시에 건드리는 작업이 이미 발생할 수 있으므로, "무엇을 한 커밋으로 묶고 무엇을 분리할지"를 바로 정해야 한다.
|
||||
|
||||
## 3. 권장 운영 정책
|
||||
|
||||
### 3.1 저장소 경계 정책
|
||||
|
||||
- `tdc114plus` 저장소:
|
||||
- Flutter 앱 코드
|
||||
- 앱 문서
|
||||
- 앱 테스트/빌드 스크립트
|
||||
- 앱에서만 사용하는 mock/contract 코드
|
||||
- Baron SSO 저장소 또는 fork:
|
||||
- backend
|
||||
- orgFront
|
||||
- userFront
|
||||
- 신규 앱 지원용 API endpoint, DTO, auth 연동 코드
|
||||
|
||||
금지:
|
||||
|
||||
- Baron SSO 소스 파일을 `tdc114plus` 저장소로 복사 반입
|
||||
- APK, 로그 덤프, 대용량 캐시 산출물을 tracked 파일로 커밋
|
||||
- 한 커밋에 앱 코드와 Baron SSO 서버 코드를 동시에 포함
|
||||
|
||||
### 3.2 브랜치 정책
|
||||
|
||||
- `tdc114plus`:
|
||||
- `main`: 항상 analyze/test 통과 상태만 반영
|
||||
- 기능 작업: `feature/<scope>-<topic>`
|
||||
- 문서/운영 작업: `docs/<topic>`, `ops/<topic>`
|
||||
- Baron SSO:
|
||||
- 기준 브랜치: `origin/dev`
|
||||
- tdc114plus 전용 작업: `feature/tdc114plus-api`, `feature/tdc114plus-auth`, `fix/tdc114plus-org-context`
|
||||
|
||||
### 3.3 커밋 단위 정책
|
||||
|
||||
한 커밋에는 아래 중 한 가지 성격만 담는다.
|
||||
|
||||
1. 앱 기능 변경
|
||||
2. 앱 리팩터링
|
||||
3. 테스트 추가/수정
|
||||
4. 문서/운영 스크립트 변경
|
||||
5. Baron SSO API 변경
|
||||
|
||||
권장 규칙:
|
||||
|
||||
- 기능 변경과 포맷 변경을 섞지 않는다.
|
||||
- 리네임/이동 커밋과 로직 변경 커밋을 가능하면 분리한다.
|
||||
- APK 빌드 결과물, 캡처 이미지, 임시 로그는 별도 보관하고 git tracked 대상에서 제외한다.
|
||||
- 앱과 서버를 함께 바꿔야 하면 저장소별로 각각 커밋하고, 커밋 메시지 본문에 상대 저장소 커밋 해시를 남긴다.
|
||||
|
||||
커밋 메시지 예시:
|
||||
|
||||
```text
|
||||
feat(auth): add hosted login callback handling
|
||||
```
|
||||
|
||||
```text
|
||||
fix(directory): align org-context subtree parsing with swagger
|
||||
```
|
||||
|
||||
```text
|
||||
docs(ops): add Android device startup checklist
|
||||
```
|
||||
|
||||
```text
|
||||
feat(baron-api): add tdc114plus org-context support endpoint
|
||||
```
|
||||
|
||||
교차 저장소 작업 시 본문 예시:
|
||||
|
||||
```text
|
||||
Related-Baron-Commit: abc1234
|
||||
Related-App-Commit: def5678
|
||||
```
|
||||
|
||||
### 3.4 main 반영 게이트
|
||||
|
||||
`tdc114plus` 저장소는 `main` 반영 전에 최소 아래를 권장한다.
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh analyze
|
||||
./scripts/flutter-docker.sh test
|
||||
```
|
||||
|
||||
Baron SSO 저장소는 팀 표준 게이트를 따르되, 최소한 아래 둘 중 하나는 남기는 편이 좋다.
|
||||
|
||||
- API smoke 결과
|
||||
- 변경 endpoint 수동 검증 로그 또는 문서 링크
|
||||
|
||||
## 4. 로컬 PC 성능 저하 및 네트워크 끊김 이슈 대응
|
||||
|
||||
현재 문제:
|
||||
|
||||
- APK 빌드나 대형 파일 변경 작업 중 로컬 PC 자원이 크게 소모되면서 네트워크 접속이 끊긴다.
|
||||
- 이 경우 원격 작업 세션, 빌드 검증, 로그 수집이 함께 불안정해질 수 있다.
|
||||
|
||||
권장 대응:
|
||||
|
||||
1. APK 빌드와 통합 검증은 로컬 PC보다 현재처럼 Docker/WSL/원격 작업공간 기준으로 우선 수행한다.
|
||||
2. 로컬 PC는 편집/간단 확인 위주로 쓰고, 무거운 빌드/테스트는 스크립트로 표준화된 원격 환경에서 수행한다.
|
||||
3. 빌드 결과물은 git에 올리지 말고, 필요 시 릴리스 산출물 저장 위치를 별도로 둔다.
|
||||
4. `main` 반영 기준을 "로컬에서 한번 실행"이 아니라 "표준 스크립트 실행 결과 확인"으로 바꾼다.
|
||||
5. 장기적으로는 Gitea 연동 CI 또는 별도 빌드 머신을 두어 APK 생성과 smoke test를 오프로드하는 것이 가장 효과적이다.
|
||||
|
||||
## 5. 바로 실행할 추천안
|
||||
|
||||
우선순위 순서:
|
||||
|
||||
1. Baron SSO는 새 독립 저장소를 바로 만들기보다, 현재 공식 저장소 + fork/worktree 체계를 팀 표준으로 먼저 확정한다.
|
||||
2. `tdc114plus`와 Baron SSO 각각에 브랜치 접두사와 커밋 메시지 규칙을 정한다.
|
||||
3. 교차 저장소 작업 시 서로의 커밋 해시를 본문에 남기는 규칙을 추가한다.
|
||||
4. `main` 반영 전 검증 명령을 문서상 필수 게이트로 고정한다.
|
||||
5. APK 빌드는 로컬 PC가 아닌 원격/Docker 기준으로 수행하는 운영 정책을 확정한다.
|
||||
|
||||
## 6. 최종 판단
|
||||
|
||||
- Baron SSO 관련 코드는 분리 관리가 맞다.
|
||||
- 다만 "신규 독립 레포 생성"은 필수라기보다 운영 선택지이며, 먼저 fork/worktree + 브랜치 정책만 명확히 해도 상당수 문제가 해결된다.
|
||||
- 지금 가장 시급한 것은 저장소 추가보다 커밋 경계, 교차 저장소 연결 방식, 빌드 오프로드 정책을 확정하는 일이다.
|
||||
@@ -0,0 +1,51 @@
|
||||
# tdc114plus docs 바로 하위 주요 문서 전수 검토 기록
|
||||
|
||||
작성일: 2026-07-10
|
||||
상태: 검토 완료
|
||||
|
||||
목적: `docs/` 바로 하위 `.md` 문서를 신규 개발 기준에 맞춰 전수 검토하고, 코드 수정 전 적용해야 할 정책/가이드 보정 사항을 기록한다.
|
||||
|
||||
## 1. 검토 기준
|
||||
|
||||
- 신규 앱은 Baron SSO에 등록되는 별도 모바일 RP다.
|
||||
- 로그인 기본 방식은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`다.
|
||||
- Flutter 앱은 headless API를 직접 호출하지 않는다.
|
||||
- 조직/직원 데이터 기준 원본은 `GET https://sadmin.hmac.kr/api/v1/integrations/org-context`다.
|
||||
- 조직 drilldown은 `자식 조직이 있으면 하위조직 목록`, `leaf 조직이면 직원 목록`을 따른다.
|
||||
- 하위조직 카드 인원 수는 직접 소속 수가 아니라 subtree 합산 인원 수를 표시한다.
|
||||
|
||||
## 2. 검토 범위
|
||||
|
||||
`docs/` 바로 하위 `.md` 31개를 기준으로 검토했다.
|
||||
|
||||
- `00_` 계약/정책/가이드 문서 전체
|
||||
- Android/ADB/실기기 운영 체크리스트
|
||||
- Baron org-context 참고 문서
|
||||
- staging 로그인 시나리오
|
||||
- 기존 정책 검토/전환 리뷰 문서
|
||||
|
||||
하위 폴더(`docs/references`, `docs/test-logs`, `docs/troubleshooting`, `docs/daily-issues`)는 이번 범위에서 제외했다.
|
||||
|
||||
## 3. 확인 결과
|
||||
|
||||
- 핵심 계약 문서(`00_contract_tdc114plus_api_2026-07-02.md`)는 Hosted Login + PKCE 기준과 일치한다.
|
||||
- 화면 정책 문서(`00_policy_tdc114plus_screen_feature_2026-07-07.md`)는 leaf/비-leaf 조직 표시 규칙과 subtree 인원 수 정책을 포함하도록 정리되어 있다.
|
||||
- 외부 API 사용 문서(`00_guide_tdc114plus_external_api_usage_2026-07-03.md`)는 운영 Key를 앱에 넣지 않는다는 원칙과 일치한다.
|
||||
- org-context 매핑 문서에는 `memberCount`와 `totalMemberCount` 차이를 더 명확히 보강했다.
|
||||
- 쉬운 설명 문서에는 headless 직접 호출 중심 설명이 남아 있어 Hosted Login + PKCE 기준으로 개정했다.
|
||||
- staging 검증 시나리오에는 headless API 배포 전제가 남아 있어 Hosted Login + PKCE 검증 기준으로 개정했다.
|
||||
- Android/ADB/실기기 문서는 현재 USB 실기기 + Windows ADB 서버 공유 운영 기준과 충돌하지 않는다.
|
||||
|
||||
## 4. 이번에 개정한 문서
|
||||
|
||||
- `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md`
|
||||
- `docs/00_guide_tdc114plus_org_context_mapping_2026-07-08.md`
|
||||
- `docs/guide_baron_org_context_api_reference_2026-07-03.md`
|
||||
- `docs/guide_new_app_baron_sso_easy_explanation_2026-07-08.md`
|
||||
- `docs/scenario_staging_baron_sso_login_verification_2026-07-06.md`
|
||||
|
||||
## 5. 코드 수정 판단
|
||||
|
||||
현재 화면 정책상 `CM본부 -> CM사업부 -> 호남지역총괄본부` 흐름에서 `호남지역총괄본부 0명`은 API 데이터가 leaf 직접 소속 0명이라면 정상일 수 있다.
|
||||
|
||||
다만 코드상 선택 조직의 직원 검색 범위가 선택 조직 자신만 보고 descendant tenant를 포함하지 않는 문제가 있다. 따라서 다음 코드 수정은 `현재 선택 scope의 subtree 전체를 직원 검색 범위로 사용`하도록 보완한다.
|
||||
@@ -0,0 +1,87 @@
|
||||
# tdc114plus 정책 문서 개편 검토
|
||||
|
||||
작성일: 2026-07-07
|
||||
상태: review v1.0
|
||||
|
||||
목적: `docs/` 아래 기존 정책/계약/절차 문서가 새로 수립한 `분리형 API 전환 정책` 기준으로 수정 가능한지 검토하고, 문서별 후속 조치 방향을 정리한다.
|
||||
|
||||
관련 기준 문서:
|
||||
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
|
||||
백업 위치:
|
||||
|
||||
- `/home/ubuntu/workspace/tdc114plus/temp/docs-policy-backup/`
|
||||
|
||||
## 1. 결론
|
||||
|
||||
- 기존 문서들은 대부분 `수정 가능`하다.
|
||||
- 다만 전부를 새로 쓰는 것은 아니고, 문서 성격에 따라 `전면 개정`, `부분 개정`, `유지`, `기록 보존`으로 나눠야 한다.
|
||||
- 특히 `개발 정책`, `API 계약`, `테스트 정책`, `작업 타임테이블`, `외부 API 사용 가이드`는 새 정책 기준으로 반드시 재정렬하는 것이 맞다.
|
||||
- 반대로 Android 설치/ADB/체크리스트류 문서는 분리형 API 정책과 직접 충돌하지 않으므로 기본 유지가 맞다.
|
||||
|
||||
## 2. 문서별 판정
|
||||
|
||||
| 문서 | 판정 | 이유 | 권장 조치 |
|
||||
| --- | --- | --- | --- |
|
||||
| `docs/00_policy_tdc114plus_development_2026-07-02.md` | 전면 개정 권장 | Baron SSO API 생성 중심 문구가 강하고 Swagger 중심 인터페이스 개발 원칙이 상위 기준으로 드러나지 않음 | 새 정책을 반영해 상위 실행 원칙 문구 재작성 |
|
||||
| `docs/00_contract_tdc114plus_api_2026-07-02.md` | 전면 개정 권장 | 현재 계약이 Baron SSO 전용 설계와 내부 추정 구조에 많이 기대고 있음 | Swagger 기준 endpoint/DTO 문서로 재작성 |
|
||||
| `docs/00_policy_tdc114plus_testing_2026-07-02.md` | 부분 개정 권장 | 테스트 구조는 유효하지만 실제 API 연동 기준이 Baron SSO runtime 중심임 | mock 우선, Swagger 계약 검증, remote/mock 전환 테스트 기준 추가 |
|
||||
| `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md` | 부분 개정 권장 | 기존 진행 이력은 보존 가치가 있으나 실행 Phase가 이전 방식 중심으로 적혀 있음 | 새 정책 Phase 기준으로 다음 작업 구간만 재정렬 |
|
||||
| `docs/00_guide_tdc114plus_external_api_usage_2026-07-03.md` | 부분 개정 권장 | 외부 API 활용 방식 문서이므로 새 정책과 잘 결합 가능 | Swagger 우선 사용 원칙과 data source 분리 기준 추가 |
|
||||
| `docs/guide_baron_sso_reference_source_2026-07-02.md` | 부분 개정 권장 | 완전 삭제할 문서는 아니지만, 이제는 Baron SSO 코드 참조 문서이지 앱 개발 상위 기준 문서는 아님 | 제목/목적을 `참조용 문서` 성격으로 낮추고 우선순위 하향 |
|
||||
| `docs/00_policy_tdc114plus_screen_feature_2026-07-07.md` | 부분 개정 가능 | 화면 정책 자체는 유효하지만 일부 용어가 Baron SSO 전제에 묶여 있음 | 화면 규칙은 유지하고 API/세션 관련 표현만 일반화 |
|
||||
| `docs/dev_env_tdc114plus_setup_plan_2026-07-02.md` | 기록 보존 중심 | 초기 환경 구축 기록 성격이 강하고 현재는 실행 정책 문서라기보다 이력 문서에 가까움 | 원본 유지, 필요 시 현재 환경 기준 별도 문서 신설 |
|
||||
| `docs/guide_tdc114plus_development_decision_brief_2026-07-01.md` | 기록 보존 중심 | 초기 판단 근거 문서라 현재 정책으로 덮어쓰는 대상이 아님 | 원본 유지 |
|
||||
| `docs/guide_tdc114plus_script_automation_plan_2026-07-02.md` | 부분 개정 가능 | 자동화 계획은 계속 유효하나 검증 대상을 Swagger 계약 기준으로 보강할 필요가 있음 | smoke/test 분리를 명확히 보강 |
|
||||
| `docs/policy_android_app_install_execution_2026-07-06.md` | 유지 | API 분리 정책과 직접 충돌 없음 | 유지 |
|
||||
| `docs/policy_android_studio_wsl_adb_2026-07-03.md` | 유지 | 개발 장비/실행 정책 문서라 독립적임 | 유지 |
|
||||
| `docs/scenario_android_emulator_device_integration_test_2026-07-03.md` | 부분 개정 가능 | 시나리오는 유효하나 API 대상 URL/테스트 전제가 바뀔 수 있음 | 실제 API 대상 설명만 갱신 |
|
||||
| `docs/checklist_pre_staging_manual_2026-07-06.md` | 부분 개정 가능 | staging 체크리스트는 유지 가능하나 기준 API가 Swagger 중심으로 바뀌어야 함 | 체크 항목 갱신 |
|
||||
| `docs/scenario_staging_baron_sso_login_verification_2026-07-06.md` | 부분 개정 가능 | 로그인 검증 흐름은 유효하지만 Baron SSO 내부 구현 전제가 강함 | 인터페이스 계약 기준으로 표현 수정 |
|
||||
| `docs/checklist_morning_startup_runtime_2026-07-03.md` | 유지 | 운영성 체크리스트라 정책 변경 영향이 낮음 | 유지 |
|
||||
| `docs/checklist_evening_shutdown_runtime_2026-07-06.md` | 유지 | 운영성 체크리스트라 정책 변경 영향이 낮음 | 유지 |
|
||||
| `docs/guide_baron_org_context_api_reference_2026-07-03.md` | 참조용 유지 | 특정 외부 연동 참고자료로 쓸 수 있음 | 정책 문서가 아닌 reference로 유지 |
|
||||
| `docs/guide_baron_sso_org_context_mirror_recovery_request_2026-07-03.md` | 기록 보존 | 이슈 대응 기록 문서임 | 유지 |
|
||||
|
||||
## 3. 우선 개편 대상
|
||||
|
||||
가장 먼저 손대야 할 문서는 아래 다섯 개다.
|
||||
|
||||
1. `docs/00_policy_tdc114plus_development_2026-07-02.md`
|
||||
2. `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
3. `docs/00_policy_tdc114plus_testing_2026-07-02.md`
|
||||
4. `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
5. `docs/00_guide_tdc114plus_external_api_usage_2026-07-03.md`
|
||||
|
||||
이유:
|
||||
|
||||
- 새 정책의 실행력은 위 다섯 문서가 실제로 같은 방향을 보느냐에 달려 있다.
|
||||
- 특히 `개발 정책`과 `API 계약`이 이전 기준에 남아 있으면 이후 코드 작업도 다시 Baron SSO 종속 방식으로 흔들릴 수 있다.
|
||||
|
||||
## 4. 수정 방식 제안
|
||||
|
||||
권장 순서:
|
||||
|
||||
1. `tdc114plus-development-policy`를 먼저 고친다.
|
||||
2. 그 다음 `tdc114plus-api-contract`를 Swagger 기준으로 재작성한다.
|
||||
3. 이후 `tdc114plus-testing-policy`를 mock/contract/real API 3단계 구조로 맞춘다.
|
||||
4. `tdc114plus-work-progress-timetable`의 다음 작업 구간을 새 Phase 기준으로 정리한다.
|
||||
5. 마지막으로 `external-api-usage-guide`, `screen-feature-policy`, staging 체크리스트 문서를 정렬한다.
|
||||
|
||||
## 5. 해석 원칙
|
||||
|
||||
- 기존 문서에 적힌 과거 진행 이력은 가능한 보존한다.
|
||||
- 다만 앞으로의 실행 기준은 `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`를 상위 기준으로 둔다.
|
||||
- Baron SSO 관련 문구가 있어도 `참조`, `연동 대상`, `과거 구현 근거` 수준이면 유지 가능하다.
|
||||
- Baron SSO 소스 수정 또는 Baron SSO 전용 endpoint 추가를 기본 개발 방식처럼 서술한 부분은 새 정책에 맞춰 수정해야 한다.
|
||||
|
||||
## 6. 다음 문서 작업 제안
|
||||
|
||||
다음 실제 수정 작업은 아래 순서가 가장 적절하다.
|
||||
|
||||
1. `docs/00_policy_tdc114plus_development_2026-07-02.md` 개정
|
||||
2. `docs/00_contract_tdc114plus_api_2026-07-02.md` 개정
|
||||
3. `docs/00_policy_tdc114plus_testing_2026-07-02.md` 개정
|
||||
|
||||
이 세 문서가 먼저 정리되면, 이후 코드 구조 개편도 문서 기준으로 일관되게 진행할 수 있다.
|
||||
@@ -0,0 +1,267 @@
|
||||
# Android target 통합테스트 진행 시나리오
|
||||
|
||||
작성일: 2026-07-03
|
||||
상태: v0.1 진행 중
|
||||
|
||||
목적: `tdc114plus` Flutter 앱의 실제 Baron SSO API 로그인, 직원목록 진입, 플랫폼 액션 수동 검증을 Android 실기기 우선, emulator fallback 기준으로 단계적으로 확인한다.
|
||||
|
||||
## 1. 적용 범위
|
||||
|
||||
이 시나리오는 아래 작업에 적용한다.
|
||||
|
||||
- Android 실기기 준비
|
||||
- Android emulator fallback 준비
|
||||
- Android 런타임에서 Baron SSO local API 접근 확인
|
||||
- `app/integration_test/` + `app/test_driver/` 기반 Flutter integration test 실행
|
||||
- 실제 기기 수동 smoke: 로그인, 직원목록, 전화/문자 버튼, 즐겨찾기 유지
|
||||
|
||||
Playwright MCP는 이 시나리오의 실행 대상이 아니다. Playwright MCP가 필요한 단계가 오면 테스트 정책에 따라 사용자 확인과 정책 문서 갱신을 먼저 진행한다.
|
||||
|
||||
## 2. 사전 원칙
|
||||
|
||||
- 전화번호와 token은 명령 출력, 문서, git tracked 파일에 남기지 않는다.
|
||||
- `scripts/.env.smoke.local`, `scripts/.env.android-emulator.local`, `scripts/.env.android-device.local`은 `.gitignore` 대상이다.
|
||||
- 기본 테스트 타깃은 Android 실기기다.
|
||||
- Android emulator에서는 host `127.0.0.1`이 아니라 보통 `10.0.2.2`로 host machine에 접근한다.
|
||||
- Android 실기기는 `adb reverse` 또는 PC LAN IP 중 하나를 선택한다.
|
||||
- Flutter 앱 변경 후에는 `./scripts/format-dart.sh`, `./scripts/quality-gate.sh`를 실행한다.
|
||||
- 테스트 실행 결과는 `docs/test-logs/2026-07-test-execution-log.md`에 누적 기록한다.
|
||||
|
||||
## 3. 진행 체크리스트
|
||||
|
||||
| 단계 | 상태 | 목적 | 명령/확인 | 완료 기준 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 0 | 완료 | 시나리오 문서 생성 | 본 문서 작성 | 문서가 `docs/`에 존재 |
|
||||
| 1 | 완료 | Baron SSO local runtime 준비 확인 | `./scripts/check-baron-api-env.sh` | failure/warning 없이 통과 |
|
||||
| 1-A | 완료 | `baron_backend` 미실행 시 복구 | Baron SSO API worktree에서 `docker compose up -d backend` | `baron_backend` running/healthy |
|
||||
| 1-B | 완료 | Ory/UserFront runtime 확인 및 복구 | `docker ps -a`, 필요 시 Ory/UserFront 컨테이너 시작 | `ory_kratos`, `ory_hydra`, `ory_keto`, `ory_oathkeeper`, `ory_postgres`, `baron_userfront` running |
|
||||
| 2 | 완료 | host 기준 authenticated API smoke 확인 | `./scripts/api-smoke.sh` | phone-login/직원목록/조직도 HTTP 200 |
|
||||
| 3 | 완료 | Flutter/Docker가 인식하는 device 확인 | `./scripts/flutter-docker.sh devices` | Android target이 표시되거나 부재 원인 확인 |
|
||||
| 3-A | 완료 | host/WSL ADB 상태 확인 | `adb devices` 또는 `which adb` | ADB 설치/연결 상태 확인 |
|
||||
| 3-B | 완료 | Android target 준비 | Windows Android Studio emulator 실행 + WSL/Docker에서 ADB 접근 구성 | Flutter devices에 Android target 표시 |
|
||||
| 4 | 대기 | 실기기용 API 주소 결정 | `scripts/.env.android-device.local` | 실기기에서 접근 가능한 `TDC114_API_BASE` 확정 |
|
||||
| 4-A | 완료 | Android target Docker ADB 인식 확인 | `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices` | 실기기 또는 fallback emulator 표시 |
|
||||
| 5 | 완료 | emulator integration test 실행 | `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/integration_tests.sh` | `+3: All tests passed!` |
|
||||
| 5-B | 완료 | 로그인 완료 가정 기능점검 | `TDC114_SMOKE_ASSUME_LOGGED_IN=1` 기반 세션 bootstrap 후 emulator integration test 실행 | 앱이 post-login 상태에서 직원검색/즐겨찾기/상세 액션 smoke를 통과 |
|
||||
| 5-A | 완료 | Docker local ADB 방식 검증 | Windows `5555` portproxy + Docker 내부 `adb connect` | integration test runner가 VM service에 연결 |
|
||||
| 6 | 대기 | 실기기 연결 확인 | `adb devices` 또는 Flutter devices | device 상태 표시 |
|
||||
| 7 | 대기 | 실기기 API 접근 방식 결정 | `adb reverse tcp:5000 tcp:5000` 또는 PC LAN IP | 실기기 브라우저/API 접근 가능 |
|
||||
| 8 | 대기 | 실기기 integration test 실행 | `TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.local ./scripts/integration_tests.sh` | 로그인 후 직원목록 진입 |
|
||||
| 9 | 대기 | 플랫폼 액션 수동 smoke | 실제 앱에서 전화/문자 버튼 확인 | 전화/문자 intent가 정상 호출 |
|
||||
| 10 | 대기 | 즐겨찾기 유지 수동 smoke | 즐겨찾기 토글 후 앱 재실행 | 즐겨찾기 상태 유지 |
|
||||
| 11 | 대기 | 결과 기록 | 테스트 로그 업데이트 | 성공/실패와 후속 조치 기록 |
|
||||
|
||||
## 4. 환경 파일 예시
|
||||
|
||||
### 4.1 Host smoke
|
||||
|
||||
기본 파일:
|
||||
|
||||
```text
|
||||
scripts/.env.smoke.local
|
||||
```
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=http://127.0.0.1:5000
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
```
|
||||
|
||||
### 4.2 Android emulator fallback
|
||||
|
||||
기본 파일:
|
||||
|
||||
```text
|
||||
scripts/.env.android-emulator.local
|
||||
```
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=http://10.0.2.2:5000
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
```
|
||||
|
||||
### 4.3 Android 실기기
|
||||
|
||||
`adb reverse`를 쓰는 경우:
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=http://127.0.0.1:5000
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
```
|
||||
|
||||
PC LAN IP를 쓰는 경우:
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=http://<PC_LAN_IP>:5000
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
```
|
||||
|
||||
## 5. 실패별 분기
|
||||
|
||||
| 증상 | 의미 | 다음 조치 |
|
||||
| --- | --- | --- |
|
||||
| `No supported devices connected.` | Flutter가 실행 가능한 Android target을 못 봄 | USB 디버깅 실기기 확인, 필요 시 Android Studio emulator fallback 실행, Docker/ADB 접근 방식 확인 |
|
||||
| `Integration tests and unit tests cannot be run in a single invocation.` | 현재 Flutter 버전에서 Android integration을 `flutter test`로 호출함 | `flutter drive --driver=test_driver/integration_driver.dart --target=integration_test/...` 경로로 전환 |
|
||||
| Linux desktop만 표시됨 | WSL/Docker Flutter는 보이지만 앱에 Linux runner가 없음 | Android target 연결 또는 별도 desktop runner 추가 검토 |
|
||||
| `adb: command not found` | WSL에 Android platform-tools가 없음 | Windows Android Studio platform-tools를 PATH로 연결하거나 WSL에 Android SDK platform-tools 설치 |
|
||||
| Windows `adb -a -P 5037 nodaemon server`에서 10048 | 기존 ADB server 또는 다른 프로세스가 5037 포트를 이미 사용 중 | `Get-Process adb`/`Stop-Process`, `netstat -ano | findstr :5037`, `taskkill /PID ... /F` 후 재시도 |
|
||||
| `WebSocketChannelException`, `127.0.0.1:<dynamic port>` connection refused | remote Windows ADB server가 만든 VM service forward가 Docker container localhost와 맞지 않음 | Windows emulator adbd `5555`를 portproxy로 노출하고 Docker 내부 local ADB server에서 `adb connect` 방식 검증 |
|
||||
| Docker local ADB가 `unauthorized` | Docker container의 ADB key가 emulator에서 승인된 Windows ADB key와 다름 | Windows 사용자 ADB key를 git ignored `.android-adb/`에 복사하고 Docker `/root/.android`로 마운트 |
|
||||
| integration test 로그인 화면/validation은 통과하지만 real API login test 실패 | 앱/API 문제 또는 backend runtime 중단 가능 | 먼저 `./scripts/api-smoke.sh`로 host authenticated smoke 재확인, 502면 Baron/Ory runtime 복구 |
|
||||
| API smoke는 통과하지만 integration test login 실패 | Android 런타임에서 API base URL 접근 실패 가능 | emulator는 `10.0.2.2`, 실기기는 `adb reverse` 또는 PC LAN IP 확인 |
|
||||
| HTTP cleartext 차단 | Android 앱이 `http://` 접근을 막을 수 있음 | Android network security config 또는 manifest 확인 |
|
||||
| phone-login 401 | 테스트 전화번호가 Baron SSO 등록자와 불일치 | env 파일의 전화번호와 Baron SSO 등록 상태 확인 |
|
||||
| phone-login 503 | Baron SSO/Ory/Kratos 세션 발급 문제 | backend 로그 확인, 인증 민감 영역으로 별도 검토 |
|
||||
| backend는 running인데 `kratos`, `keto`, `hydra` DNS 실패 | Ory runtime 컨테이너가 중지됨 | Ory/UserFront 컨테이너 시작 후 runtime 점검 재실행 |
|
||||
| employee/orgchart 401/403 | token/session/권한 문제 | 앱 세션 저장/전달, backend auth middleware 확인 |
|
||||
|
||||
## 6. 현재 실행 메모
|
||||
|
||||
- 2026-07-03: 문서 생성. 다음 단계는 1단계 `check-baron-api-env.sh` 실행이다.
|
||||
- 2026-07-03: 1단계 실행 결과 `baron_backend`가 running 상태가 아니어서 1-A 복구 단계를 추가했다.
|
||||
- 2026-07-03: 1-A에서 `docker compose up -d backend` 실행 후 1단계 재검증 통과. `baron_backend`, `baron_gateway` running 확인.
|
||||
- 2026-07-03: 2단계 API smoke에서 phone-login 503 발생. backend 로그에서 `kratos`, `keto`, `hydra`, `oathkeeper` DNS 실패 확인. 1-B Ory/UserFront 복구 단계를 추가했다.
|
||||
- 2026-07-03: 1-B에서 Ory/UserFront 컨테이너를 시작했다. `baron_backend`, `baron_userfront`, `baron_gateway`, Ory 핵심 컨테이너 running 확인.
|
||||
- 2026-07-03: 2단계 API smoke 재실행 통과. phone-login, employee list, tenant list, orgchart 모두 HTTP 200.
|
||||
- 2026-07-03: 3단계 `./scripts/flutter-docker.sh devices` 실행 결과 Docker Flutter는 `Linux desktop`만 인식하고 Android emulator/device는 인식하지 못했다. 3-A ADB 상태 확인 단계를 추가했다.
|
||||
- 2026-07-03 08:11 KST: 3-A 확인 결과 WSL에 `adb`가 설치되어 있지 않다. `./scripts/integration_tests.sh`는 Linux desktop만 발견했지만 앱에 Linux runner가 없어 `No supported devices connected.`로 종료했다. 3-B Android target 준비 단계가 필요하다.
|
||||
- 2026-07-03 오전: Windows Android Studio에서 `Medium Phone` Android 15 API 35 emulator를 생성하고 Windows `adb.exe devices`에서 `emulator-5554 device`를 확인했다.
|
||||
- 2026-07-03 오전: Windows `adb -a -P 5037 nodaemon server`는 기존 ADB server 자동 재기동으로 `10048` 오류가 반복되어 `netsh interface portproxy` 방식으로 전환했다.
|
||||
- 2026-07-03 오전: 관리자 PowerShell에서 `0.0.0.0:5037 -> 127.0.0.1:5037` portproxy와 방화벽 rule을 추가했다. WSL에서 `172.21.128.1:5037` 연결 성공, Docker Flutter 내부 `adb devices`에서 `emulator-5554 device` 확인.
|
||||
- 2026-07-03 10:22 KST: `scripts/integration_tests.sh`를 실시간 출력 방식으로 개선한 뒤 emulator integration test를 재실행했다. APK 빌드/설치는 성공했지만 test loading 단계에서 `WebSocketChannelException`, `127.0.0.1:<dynamic port>` connection refused로 실패했다. remote Windows ADB server의 VM service port forward가 Docker container localhost와 맞지 않는 구조로 판단하고 5-A를 추가했다.
|
||||
- 2026-07-03 11:06 KST: Windows 관리자 PowerShell에서 `0.0.0.0:5555 -> 127.0.0.1:5555` portproxy와 방화벽 rule을 추가했다. Docker local ADB 방식에서 최초 `unauthorized`가 발생했으나 Windows 사용자 ADB key를 git ignored `.android-adb/`에 복사하고 Docker `/root/.android`로 마운트해 `172.21.128.1:5555 device` 상태를 확보했다.
|
||||
- 2026-07-03 11:06 KST: Docker local ADB 방식으로 integration test를 재실행했다. 최초 real API login test 실패는 Baron/Ory runtime 중단에 따른 `api-smoke.sh` 502와 연관됨을 확인했고, Ory/UserFront 및 backend 재시작 후 authenticated API smoke 통과, 최종 integration test `+3: All tests passed!`를 확인했다.
|
||||
- 2026-07-06: 신규 링크 로그인 전환 이후에는 local 승인 완료 E2E가 막힐 수 있으므로, Android target 기능점검은 `TDC114_SMOKE_ASSUME_LOGGED_IN=1`을 이용한 post-login 세션 seed 경로를 함께 사용한다.
|
||||
- 2026-07-06: local Baron SSO runtime에 테스트 번호 `010-9136-5338`용 identity와 local user를 맞춘 뒤 legacy `phone-login` HTTP 200, headless 로그인 시작 응답, `link/poll` pending 상태까지 확인했다.
|
||||
- 2026-07-06: 로그인 완료 가정 기능점검 재시도에서는 host `api-smoke.sh`는 다시 통과했지만, `172.21.128.1:5555`는 `offline`, `172.21.128.1:5037` 경로는 `protocol fault`라 Android target 연결이 실패했다. 현재 blocker는 앱/API가 아니라 Windows emulator 또는 ADB/portproxy 상태다.
|
||||
|
||||
## 7. 3-B Android target 준비 상세 절차
|
||||
|
||||
아래 중 하나를 선택한다.
|
||||
|
||||
### 7.0 현재 WSL 확인 결과
|
||||
|
||||
2026-07-03 현재 확인한 내용:
|
||||
|
||||
- WSL 내부 `adb` 명령은 없다.
|
||||
- WSL 내부 `java` 명령은 없다.
|
||||
- WSL 내부 `sdkmanager`, `emulator` 명령은 없다.
|
||||
- `ANDROID_HOME`, `ANDROID_SDK_ROOT` 환경 변수는 설정되어 있지 않다.
|
||||
- `/dev/kvm` 장치가 확인되지 않아 WSL 내부 Android emulator 가속 실행 가능성이 낮다.
|
||||
- 일반적인 Windows Android SDK 경로(`/mnt/c/Users/*/AppData/Local/Android/Sdk/platform-tools`)가 WSL에서 바로 발견되지 않았다.
|
||||
- WSL에서 `powershell.exe`를 호출해 Windows 경로를 자동 탐색하려 했으나 현재 세션에서는 `UtilBindVsockAnyPort` 오류로 실행되지 않았다.
|
||||
|
||||
따라서 캡쳐처럼 Ubuntu/WSL 내부에 Android SDK, emulator, AVD를 직접 설치하는 경로는 현재 즉시 진행 가능하지 않다. 진행하려면 Java, Android command-line tools, platform-tools, emulator, system image, KVM/GUI 조건을 새로 맞춰야 한다. 더 안정적인 다음 단계는 Windows에서 Android Studio/SDK 설치 여부와 `adb.exe` 위치를 직접 확인하는 것이다.
|
||||
|
||||
### 7.0-A Ubuntu/WSL 내부 emulator 경로 판단
|
||||
|
||||
캡쳐의 Ubuntu 설치 방식은 아래 조건이 모두 충족될 때만 추천한다.
|
||||
|
||||
1. WSL에서 `/dev/kvm`이 보인다.
|
||||
2. WSLg 또는 별도 X server로 emulator GUI 표시가 가능하다.
|
||||
3. Java 11 이상과 Android command-line tools 설치가 가능하다.
|
||||
4. `sdkmanager`, `avdmanager`, `emulator`, `adb`가 WSL 내부 PATH에 잡힌다.
|
||||
5. Docker Flutter 컨테이너에서도 해당 emulator/ADB에 접근할 수 있다.
|
||||
|
||||
현재 환경은 1, 3, 4가 충족되지 않는다. 그래서 우선순위는 `Windows Android Studio emulator 또는 실기기 + WSL/ADB 연결` 방식으로 둔다.
|
||||
|
||||
### 7.1 Android emulator 사용
|
||||
|
||||
1. Windows Android Studio를 연다.
|
||||
2. Device Manager에서 Pixel 계열 emulator를 생성하거나 기존 emulator를 시작한다.
|
||||
3. Windows 터미널에서 `adb devices`로 emulator가 보이는지 확인한다.
|
||||
4. WSL에서 Android platform-tools를 사용할 수 있게 한다.
|
||||
- 방법 A: Windows Android SDK `platform-tools` 경로를 WSL `PATH`에 연결한다.
|
||||
- 방법 B: WSL에 Android SDK platform-tools를 별도로 설치한다.
|
||||
5. WSL에서 `adb devices`가 emulator를 표시하는지 확인한다.
|
||||
6. Docker Flutter가 Android device를 볼 수 있도록 `flutter-docker.sh`의 ADB socket/device mount 필요 여부를 확인한다.
|
||||
|
||||
### 7.2 Android 실기기 사용
|
||||
|
||||
1. 휴대폰에서 개발자 옵션을 활성화한다.
|
||||
2. USB 디버깅을 켠다.
|
||||
3. USB로 PC에 연결하고 RSA 디버깅 허용 팝업을 승인한다.
|
||||
4. Windows 또는 WSL에서 `adb devices`가 `device` 상태로 표시되는지 확인한다.
|
||||
5. 실기기에서 local API 접근은 `adb reverse tcp:5000 tcp:5000` 또는 PC LAN IP 방식 중 하나를 선택한다.
|
||||
|
||||
### 7.3 Windows emulator + Docker local ADB server 방식
|
||||
|
||||
`ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037` 방식은 Flutter device 목록 확인과 APK 설치까지 가능했지만, integration test loading 단계에서 VM service dynamic port가 Docker container의 `127.0.0.1`로 연결되지 않는 문제가 발생했다.
|
||||
|
||||
다음 검증은 Docker container 내부의 local ADB server가 Windows emulator adbd에 직접 붙는 방식으로 진행한다.
|
||||
|
||||
1. Windows 관리자 PowerShell에서 emulator adbd port를 노출한다.
|
||||
|
||||
```powershell
|
||||
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=5555 connectaddress=127.0.0.1 connectport=5555
|
||||
netsh advfirewall firewall add rule name="ADB emulator 5555 for WSL" dir=in action=allow protocol=TCP localport=5555
|
||||
netsh interface portproxy show v4tov4
|
||||
```
|
||||
|
||||
2. WSL에서 `5555` 연결을 확인한다.
|
||||
|
||||
```bash
|
||||
nc -vz 172.21.128.1 5555
|
||||
```
|
||||
|
||||
3. Docker Flutter container 내부에서 local ADB server로 emulator에 직접 연결한다.
|
||||
|
||||
```bash
|
||||
docker run --rm ghcr.io/cirruslabs/flutter:stable sh -lc 'adb connect 172.21.128.1:5555 && adb devices'
|
||||
```
|
||||
|
||||
4. 이 방식에서 device가 표시되면 `scripts/flutter-docker.sh`에 `TDC114_ADB_CONNECT_ADDRESS` 같은 optional env를 추가해 테스트 실행 전 `adb connect`를 수행하도록 보강한다.
|
||||
|
||||
5. Docker ADB가 `unauthorized`로 표시되면 Windows에서 이미 승인된 ADB key를 local ignored directory에 복사한다.
|
||||
|
||||
```bash
|
||||
mkdir -p .android-adb
|
||||
cp /mnt/c/Users/user/.android/adbkey .android-adb/adbkey.new
|
||||
cp /mnt/c/Users/user/.android/adbkey.pub .android-adb/adbkey.pub.new
|
||||
mv -f .android-adb/adbkey.new .android-adb/adbkey
|
||||
mv -f .android-adb/adbkey.pub.new .android-adb/adbkey.pub
|
||||
chmod 600 .android-adb/adbkey
|
||||
```
|
||||
|
||||
6. 최종 실행 명령:
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
현재 환경의 통과 기준 출력:
|
||||
|
||||
```text
|
||||
+3: All tests passed!
|
||||
```
|
||||
|
||||
### 7.4 로그인 완료 가정 기능점검
|
||||
|
||||
신규 링크 로그인 흐름에서는 local runtime에서 실제 승인 완료까지 항상 검증할 수 있는 것이 아니므로, Android target 기능점검은 아래 보조 경로를 사용한다.
|
||||
|
||||
1. 기본은 mock 세션 seed를 사용한다.
|
||||
2. legacy 호환 점검이 꼭 필요할 때만 host 기준 `phone-login` API로 유효 세션을 1회 발급받는다.
|
||||
3. 해당 세션 또는 mock user 정보를 Flutter app 시작 전에 `SharedPreferences`에 seed 한다.
|
||||
4. 앱이 `AuthGate`에서 로그인 화면 대신 `직원검색`으로 바로 진입하는지 확인한다.
|
||||
5. 직원 목록, 즐겨찾기, 직원 상세, 전화/문자 버튼 노출을 integration test로 점검한다.
|
||||
6. local runtime이 유효 세션을 발급하지 못하면 mock directory 모드로 fallback 하여 post-login UI 기능만 별도로 점검한다.
|
||||
|
||||
실행 예시:
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
TDC114_SMOKE_ASSUME_LOGGED_IN=1 \
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
주의:
|
||||
|
||||
- 이 경로는 "로그인 완료 이후 앱 기능" 점검용이다.
|
||||
- 실제 `headless phone-login -> 승인 -> link/poll 성공` 자체를 대체하지는 않는다.
|
||||
- local `phone-login` bootstrap이 `401 login_failed`이면 자동으로 mock directory fallback을 사용한다.
|
||||
@@ -0,0 +1,354 @@
|
||||
# staging Baron SSO 승인 로그인 검증 시나리오
|
||||
|
||||
작성일: 2026-07-06
|
||||
상태: v0.2 진행 중
|
||||
|
||||
목적: `tdc114plus` 신규 전화번호 승인 로그인 흐름을 local Baron SSO runtime 대신 staging Baron SSO 환경에서 우선 검증하기 위한 절차를 정리한다. 공식 기준은 `Baron SSO Hosted Login + OIDC Authorization Code + PKCE`이며, headless 직접 호출은 레거시/참고 검증으로만 본다.
|
||||
|
||||
## 1. 왜 staging 경로를 우선 쓰는가
|
||||
|
||||
- 현재 local Baron SSO runtime에는 테스트 대상 전화번호의 identity/user mirror가 없을 수 있다.
|
||||
- 이 경우 local에서는 `Hosted Login -> 문자/메일 링크 인증 -> App Link callback -> PKCE token 교환`을 끝까지 확인하기 어렵다.
|
||||
- staging Baron SSO에 테스트 번호, RP 등록, redirect URI, 실제 링크 발송 경로가 준비되어 있다면 실제 승인 완료 end-to-end 검증을 더 빠르게 진행할 수 있다.
|
||||
|
||||
## 2. 적용 범위
|
||||
|
||||
이 시나리오는 아래 검증에 적용한다.
|
||||
|
||||
- staging Baron API smoke
|
||||
- Android target 기준 staging API integration test
|
||||
- 실제 승인 완료 로그인 1회 검증
|
||||
- staging 반영 검토 전환 판단
|
||||
|
||||
## 3. 필요한 값
|
||||
|
||||
아래 값이 준비되어야 한다.
|
||||
|
||||
- `TDC114_API_BASE`
|
||||
- staging Baron API base URL
|
||||
- `TDC114_SMOKE_PHONE`
|
||||
- staging Baron SSO에 등록된 테스트 전화번호
|
||||
- 선택값 `TDC114_SMOKE_EXPECTED_NAME`
|
||||
- 로그인 후 화면에서 확인할 사용자명
|
||||
- 선택값 `TDC114_SMOKE_EXPECTED_TENANT_LABEL`
|
||||
- 로그인 후 화면에서 확인할 조직 또는 테넌트 라벨
|
||||
|
||||
권장 env 파일:
|
||||
|
||||
```text
|
||||
scripts/.env.staging.local
|
||||
```
|
||||
|
||||
기본 예시는 아래 파일을 복사해서 사용한다.
|
||||
|
||||
```text
|
||||
scripts/smoke.staging.env.example
|
||||
```
|
||||
|
||||
## 4. 선행 조건
|
||||
|
||||
아래 조건이 먼저 만족되어야 한다.
|
||||
|
||||
- Flutter auth/model/widget test 통과
|
||||
- backend handler/server test 통과
|
||||
- staging 대상 Baron SSO Hosted Login, authorization endpoint, token endpoint가 사용 가능함
|
||||
- 테스트 번호 수신 단말에서 링크 승인 가능
|
||||
- 테스트 결과를 `docs/test-logs/2026-07-test-execution-log.md`에 기록할 준비가 되어 있음
|
||||
|
||||
배포 전 내부 준비 기준은 아래 순서를 따른다.
|
||||
|
||||
1. 로컬 구현 완료 고정
|
||||
2. 자동화 테스트 고정
|
||||
3. 로컬 API 계약 검증
|
||||
4. Android target UI 기능 확인
|
||||
5. Android target 실사용 흐름 점검
|
||||
6. 수동 점검 체크리스트 정리
|
||||
7. staging 반영 직전 검토
|
||||
|
||||
## 5. 권장 진행 순서
|
||||
|
||||
### 5.1 1단계: env 준비
|
||||
|
||||
예시:
|
||||
|
||||
```bash
|
||||
cp scripts/smoke.staging.env.example scripts/.env.staging.local
|
||||
```
|
||||
|
||||
값을 채운다.
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=https://staging.example.com
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
TDC114_SMOKE_AUTH_FLOW=link
|
||||
TDC114_SMOKE_EXPECTED_NAME=홍길동
|
||||
TDC114_SMOKE_EXPECTED_TENANT_LABEL=IS3
|
||||
```
|
||||
|
||||
사용자명과 조직 라벨은 optional이다. 값이 자주 바뀌거나 확실하지 않으면 비워둔다.
|
||||
|
||||
### 5.2 2단계: staging API smoke
|
||||
|
||||
먼저 host 기준 smoke를 확인한다.
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.staging.local ./scripts/api-smoke.sh
|
||||
```
|
||||
|
||||
확인 포인트:
|
||||
|
||||
- Hosted Login authorization URL 생성 가능
|
||||
- RP `client_id`, `redirect_uri`, PKCE `code_challenge` 조합이 Baron SSO에서 거부되지 않음
|
||||
- App Link callback과 token 교환에 필요한 endpoint가 확인됨
|
||||
- 레거시 headless smoke는 필요 시 참고로만 수행
|
||||
|
||||
주의:
|
||||
|
||||
- staging의 공식 성공 기준은 앱 직접 headless 호출이 아니라 Hosted Login 진입과 PKCE callback 완료다.
|
||||
- 실제 승인 완료는 integration test 또는 수동 검증으로 이어서 확인한다.
|
||||
|
||||
### 5.3 3단계: Android target 준비
|
||||
|
||||
기존 Android runtime 절차를 따른다.
|
||||
|
||||
- emulator는 `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
- ADB 정책은 `docs/policy_android_studio_wsl_adb_2026-07-03.md`
|
||||
|
||||
핵심은 `TDC114_API_BASE`를 staging 값으로 바꾸고, 독립형 실기기 테스트에서는 `TDC114_SKIP_SESSION_BOOTSTRAP=true`로 로컬 legacy bootstrap을 끄는 것이다.
|
||||
|
||||
공기계 독립 실행 권장 env:
|
||||
|
||||
```text
|
||||
scripts/.env.android-device.staging.local
|
||||
```
|
||||
|
||||
예시:
|
||||
|
||||
```text
|
||||
TDC114_API_BASE=https://staging.example.com
|
||||
TDC114_SKIP_SESSION_BOOTSTRAP=true
|
||||
TDC114_SMOKE_AUTH_FLOW=link
|
||||
TDC114_SMOKE_PHONE=010xxxxxxxx
|
||||
```
|
||||
|
||||
로그인만 staging, 직원/조직 데이터만 production으로 분리해야 하면 아래 override를 추가한다.
|
||||
|
||||
```text
|
||||
TDC114_AUTH_API_BASE=https://staging.example.com
|
||||
TDC114_DIRECTORY_API_BASE=https://production.example.com
|
||||
TDC114_ORGANIZATION_API_BASE=https://production.example.com
|
||||
```
|
||||
|
||||
### 5.4 4단계: staging integration test 실행
|
||||
|
||||
emulator fallback 예시:
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.staging.local \
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
이미 승인된 prefix 경로를 쓰는 경우에는 기존 Android emulator 실행 방식과 동일하게 적용한다.
|
||||
|
||||
integration test의 현재 검증 기준:
|
||||
|
||||
- 로그인 화면 표시
|
||||
- 빈 전화번호 validation
|
||||
- `TDC114_SMOKE_PHONE`가 있으면 실제 번호 입력 후 로그인 시도
|
||||
- 로그인 성공 시 `직원검색`, `검색 결과` 확인
|
||||
- optional expected 값이 있으면 사용자명/조직 라벨까지 추가 확인
|
||||
|
||||
### 5.4-A 4-A단계: 공기계 독립 로그인 실행
|
||||
|
||||
공기계 또는 실사용 폰에 staging 직접 로그인 화면을 띄우려면 아래 경로를 사용한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037 \
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-device.staging.local \
|
||||
TDC114_FLUTTER_DEVICE_ID=<PHYSICAL_DEVICE_ID> \
|
||||
./scripts/manual-postlogin-run.sh
|
||||
```
|
||||
|
||||
이 모드에서는:
|
||||
|
||||
- 앱이 local legacy `phone-login` bootstrap을 시도하지 않는다.
|
||||
- 앱이 staging Baron API를 직접 사용한다.
|
||||
- 로그인은 앱의 `Baron SSO로 로그인` 버튼으로 Hosted Login을 열고, 인증 완료 후 App Link callback과 PKCE token 교환으로 완료한다.
|
||||
|
||||
### 5.5 5단계: 실제 승인 완료 수동 확인
|
||||
|
||||
테스트 단말에서 아래를 수행한다.
|
||||
|
||||
1. 앱에서 `Baron SSO로 로그인` 탭
|
||||
2. 열린 Baron SSO Hosted Login 화면에서 휴대폰번호 입력
|
||||
3. 수신된 문자 또는 메일의 링크 열기
|
||||
4. `https://114.hmac.kr/auth/callback` App Link로 앱 복귀 확인
|
||||
5. PKCE token 교환 후 `직원검색` 진입 확인
|
||||
|
||||
성공 기준:
|
||||
|
||||
- Baron SSO authorization endpoint 진입 성공
|
||||
- 사용자가 수신 링크를 열 수 있음
|
||||
- App Link callback 수신 및 `state` 검증 성공
|
||||
- 앱 세션 저장 후 `직원검색` 화면 진입
|
||||
|
||||
## 5-A. staging 배포 전 수동 점검 체크리스트
|
||||
|
||||
아래 항목은 staging 반영 요청 전에 미리 채워두는 것을 권장한다.
|
||||
|
||||
### 5-A.1 에뮬레이터 기준 확인
|
||||
|
||||
- 로그인 화면이 정상 표시되는가
|
||||
- 빈 전화번호 validation이 정상 동작하는가
|
||||
- `Baron SSO로 로그인` 버튼이 Hosted Login 화면을 여는가
|
||||
- 인증 대기 중 문구와 로딩 상태가 정상 표시되는가
|
||||
- 오류 발생 시 내부 시스템 정보 없이 일반화된 안내 문구가 보이는가
|
||||
- 로그인 성공 후 `직원검색` 첫 화면으로 진입하는가
|
||||
- 첫 화면에서 기본 검색 결과가 표시되는가
|
||||
- 직원 상세, 즐겨찾기, 전화/문자 버튼이 기존처럼 동작하는가
|
||||
|
||||
### 5-A.2 예외 시나리오 확인
|
||||
|
||||
- 미등록 번호 입력 시 generic 실패 안내가 보이는가
|
||||
- 레거시 headless fallback을 켠 경우에만 만료된 `pendingRef`/poll 종료 처리가 자연스러운가
|
||||
- poll 간격이 짧을 때 제한 응답 또는 재시도 대기 처리가 되는가
|
||||
- 앱 재실행 후 세션 복원이 되는가
|
||||
- 인증 만료 시 세션 정리 후 재로그인 흐름으로 복귀하는가
|
||||
|
||||
### 5-A.3 staging 반영 직전 확인
|
||||
|
||||
- 정확한 staging `TDC114_API_BASE`를 확보했는가
|
||||
- 해당 base에서 Hosted Login authorization endpoint와 token endpoint를 사용할 수 있는가
|
||||
- 테스트 번호로 문자 또는 메일 수신이 가능한가
|
||||
- staging 로그 확인 담당자와 확인 위치를 알고 있는가
|
||||
- 실패 시 되돌릴 범위와 회귀 확인 방법을 문서로 정리했는가
|
||||
|
||||
## 6. 예외 케이스 점검
|
||||
|
||||
실제 승인 완료 1회가 끝나면 아래를 추가 확인한다.
|
||||
|
||||
- 미등록 번호 입력 시 generic 실패 메시지
|
||||
- 레거시 headless fallback을 켠 경우에만 만료된 `pendingRef` 처리
|
||||
- polling 간격이 너무 짧을 때 `slow_down` 또는 유사 제한 동작
|
||||
- 로그인 성공 후 directory API 401 없이 첫 화면 진입 가능한지
|
||||
|
||||
## 7. 성공 시 다음 판단
|
||||
|
||||
아래가 충족되면 staging 반영 검토 시작 가능 단계로 본다.
|
||||
|
||||
- 실제 승인 완료 end-to-end 1회 이상 통과
|
||||
- 예외 케이스 점검 완료
|
||||
- 테스트 번호, 로그 확인 포인트, 롤백 경로 정리
|
||||
|
||||
## 8. 현재 메모
|
||||
|
||||
- 2026-07-06 현재 local runtime에는 테스트 대상 전화번호 identity/user mirror가 없어 local 승인 완료 검증이 막혀 있다.
|
||||
- 따라서 다음 실질 작업은 staging 번호와 staging API base를 확보해 위 절차로 1회 end-to-end를 끝까지 확인하는 것이다.
|
||||
|
||||
## 9. 팀장 공유용 문서 버전
|
||||
|
||||
이번 신규앱 로그인은 기존의 선인증 전화번호 로그인과 다르게, `전화번호 입력 -> 링크 발송 -> 사용자 승인 -> 승인 상태 polling -> 세션 저장`의 비동기 승인 절차를 거친다. 따라서 단순히 앱 소스 구현만 완료되었다고 해서 staging 반영 가능 상태라고 보기는 어렵고, staging Baron SSO 쪽에도 신규 로그인 흐름을 실제로 수용할 준비가 필요하다.
|
||||
|
||||
기존 로그인은 Baron SSO가 전화번호 확인 후 바로 세션을 발급하는 구조여서, 로컬 또는 기존 테스트 계정만으로도 비교적 빠르게 검증이 가능했다. 반면 이번 로그인은 사용자의 승인 링크 발송과 승인 완료 상태 변경이 중간에 개입하므로, staging 환경에서는 앱 코드 외에도 API 라우트 배포, 테스트 사용자 데이터, 링크 발송 경로, 승인 후 상태 조회가 모두 함께 맞아야 실제 end-to-end 검증이 가능하다.
|
||||
|
||||
따라서 이번 건은 "앱 구현 완료 후 즉시 staging 반영"이 아니라, "앱 구현과 backend 구현을 고정한 뒤 staging 준비 항목을 맞추고, 실제 승인 완료를 1회 이상 확인한 후 반영 검토" 순서로 접근하는 것이 안전하다.
|
||||
|
||||
## 10. staging 단계에서 준비가 필요한 항목
|
||||
|
||||
아래 항목은 로컬 준비가 아니라 staging 환경에서 선행되어야 하는 준비 사항이다.
|
||||
|
||||
### 10.1 staging 신규앱 API 배포 필요 여부
|
||||
|
||||
현재 기준으로는 필요 가능성이 매우 높다.
|
||||
|
||||
- 신규앱은 legacy 즉시 로그인이나 앱 직접 headless 호출보다 Baron SSO Hosted Login + PKCE 계약을 기본으로 사용한다.
|
||||
- 따라서 staging 대상 Baron SSO/RP 설정에 아래 OIDC endpoint와 설정이 실제 사용 가능해야 한다.
|
||||
- Authorization endpoint
|
||||
- Token endpoint
|
||||
- TDC114PLUS RP `client_id`
|
||||
- `https://114.hmac.kr/auth/callback` redirect URI
|
||||
- 추가로 로그인 이후 첫 화면 진입까지 확인하려면 아래 데이터 API도 확인되어야 한다.
|
||||
- `GET /api/v1/integrations/org-context`
|
||||
- 필요 시 `GET /api/v1/public/orgchart`
|
||||
|
||||
정리:
|
||||
|
||||
- staging에 TDC114PLUS RP 설정과 Hosted Login 흐름이 아직 반영되지 않았다면, 실제 승인 로그인 검증 전에 RP 등록/설정 반영이 선행되어야 한다.
|
||||
- 단순 Baron SSO 대표 URL만 알고 있는 상태로는 부족하고, 실제 OIDC discovery/authorization/token endpoint와 redirect URI 허용 여부가 필요하다.
|
||||
|
||||
### 10.2 staging API base URL 확정
|
||||
|
||||
아래가 명확해야 한다.
|
||||
|
||||
- 신규앱이 호출해야 하는 정확한 staging `TDC114_API_BASE`
|
||||
- 해당 base가 실제로 Swagger 공개 route를 제공하는지
|
||||
- gateway, reverse proxy, auth middleware가 신규 route를 정상 통과시키는지
|
||||
|
||||
현재 확인상 `https://sso.hmac.kr`는 Baron SSO 대표 주소일 수는 있으나, 앱 데이터 API base로 확정할 근거는 부족했다.
|
||||
|
||||
### 10.3 staging 테스트 사용자 준비
|
||||
|
||||
staging Baron SSO에는 아래 조건을 만족하는 테스트 사용자가 준비되어야 한다.
|
||||
|
||||
- 테스트 전화번호가 staging Baron SSO 인증 대상 사용자로 존재
|
||||
- 해당 사용자가 링크 발송 대상 lookup에서 조회 가능
|
||||
- 승인 완료 후 앱 세션 발급 대상 사용자로 연결 가능
|
||||
- 직원검색/조직도 API에서 앱 사용자로도 정상 조회 가능
|
||||
|
||||
쉽게 말하면 staging에서는 "전화번호를 아는 인증 사용자"와 "앱이 직원으로 인식하는 사용자 정보"가 둘 다 준비되어 있어야 한다.
|
||||
|
||||
### 10.4 staging 링크 발송 경로 준비
|
||||
|
||||
이번 로그인은 사용자가 실제 링크를 수신해야 하므로 아래가 staging에서 준비되어야 한다.
|
||||
|
||||
- 문자 또는 메일 발송 provider가 staging에서 활성화되어 있는지
|
||||
- 테스트 번호에서 실제 링크를 수신 가능한지
|
||||
- 링크 클릭 후 staging Baron SSO가 인증 완료 상태로 전환되고 redirect URI로 authorization code를 돌려주는지
|
||||
|
||||
이 항목이 안 맞으면 Hosted Login 진입은 성공해도 실제 승인 완료 검증은 끝까지 진행되지 않는다.
|
||||
|
||||
### 10.5 staging callback/token 교환 경로 준비
|
||||
|
||||
신규앱은 승인 후 App Link callback으로 authorization code를 받고, token endpoint에서 PKCE token 교환을 수행한다. 따라서 staging에서는 아래가 준비되어야 한다.
|
||||
|
||||
- `https://114.hmac.kr/auth/callback` redirect URI 허용
|
||||
- callback에 `code`, `state` 전달
|
||||
- token endpoint에서 `authorization_code + code_verifier` 교환 허용
|
||||
- Client Secret 없이 PKCE 공개 앱으로 token 교환 가능
|
||||
|
||||
이 부분은 단순 route 존재 여부만으로는 부족하고, 실제 링크 승인과 callback/token 교환이 연결되어 있어야 한다.
|
||||
|
||||
### 10.6 staging 로그 확인 포인트 확보
|
||||
|
||||
실제 승인 로그인 검증 중에는 실패 원인 분리가 중요하므로 아래를 알아야 한다.
|
||||
|
||||
- staging backend 로그 확인 위치
|
||||
- 필요 시 gateway 또는 auth 로그 확인 위치
|
||||
- Hosted Login 진입, 링크 발송, callback redirect, token 교환 실패 로그를 누가 확인할 수 있는지
|
||||
|
||||
이 정보가 없으면 staging에서 실패가 나도 앱 문제인지, API 미배포인지, 사용자 데이터 문제인지 구분이 늦어진다.
|
||||
|
||||
### 10.7 staging 반영 실패 대비 경로
|
||||
|
||||
아래도 staging 단계에서 미리 정리되어야 한다.
|
||||
|
||||
- 신규앱 API가 미반영 상태로 남을 경우의 원복 또는 비활성 경로
|
||||
- 기존 로그인 방식과 신규 로그인 방식의 분리 여부
|
||||
- 문제가 생겼을 때 local 회귀 검증을 어떤 기준으로 다시 확인할지
|
||||
|
||||
이번 변경은 신규 로그인 플로우가 추가된 형태이므로, staging에서도 route 단위로 반영 범위와 되돌림 범위를 설명할 수 있어야 한다.
|
||||
|
||||
## 11. staging 준비 완료 판단 기준
|
||||
|
||||
아래가 충족되어야 staging에서 실제 승인 로그인 검증을 진행할 수 있다고 본다.
|
||||
|
||||
1. staging `TDC114_API_BASE`가 확정되었다.
|
||||
2. staging Baron SSO에 TDC114PLUS RP와 Hosted Login + PKCE 설정이 반영되었다.
|
||||
3. staging Baron SSO에 테스트 전화번호 사용자가 준비되었다.
|
||||
4. 테스트 번호에서 실제 링크 수신이 가능하다.
|
||||
5. 승인 후 App Link callback과 PKCE token 교환이 session 발급까지 이어진다.
|
||||
6. 로그인 후 `직원검색` 첫 화면 진입이 가능하다.
|
||||
7. 실패 시 확인할 로그 위치와 담당자 경로가 정리되었다.
|
||||
|
||||
위 기준이 충족되기 전에는 "staging 반영 가능"이라고 단정하지 않고, "staging 반영 검토 준비 단계"로 표현하는 것이 정확하다.
|
||||
@@ -1,436 +0,0 @@
|
||||
# tdc114plus API 계약
|
||||
|
||||
작성일: 2026-07-02
|
||||
상태: v1.0 1차 구현 기준 확정
|
||||
|
||||
목적: `tdc114plus` Flutter 앱이 Baron SSO backend 및 orgFront 데이터와 연동하기 위해 필요한 API 계약을 정의한다. 본 문서는 구현 전 계약 기준이며, 실제 Baron SSO backend 구현은 `/home/ubuntu/workspace/baron-sso-tdc114plus-api`의 `feature/tdc114plus-api` 브랜치에서 진행한다.
|
||||
|
||||
## 1. 설계 기준
|
||||
|
||||
확인한 기준 문서:
|
||||
|
||||
- `docs/tdc114plus-development-decision-brief-2026-07-01.md`
|
||||
- `docs/tdc114plus-development-policy-2026-07-02.md`
|
||||
- `docs/baron-sso-reference-source-policy-2026-07-02.md`
|
||||
- `docs/references/baron-safe-policies/api-contract.md`
|
||||
- Baron SSO `docs/API_DESIGN_POLICY.md`
|
||||
- Baron SSO `docs/identity-redis-mirror-policy-2026-06-09.md`
|
||||
- Baron SSO `docs/references/baron-safe-policies/nonstandard-phone-only-login-technical-review-2026-06-23.md`
|
||||
|
||||
확인한 기존 Baron SSO 코드:
|
||||
|
||||
- `backend/cmd/server/main.go`
|
||||
- `backend/internal/handler/auth_handler.go`
|
||||
- `backend/internal/handler/tenant_handler.go`
|
||||
- `backend/internal/handler/user_handler.go`
|
||||
- `backend/internal/domain/user.go`
|
||||
- `backend/internal/domain/tenant.go`
|
||||
- `orgfront/src/lib/adminApi.ts`
|
||||
|
||||
## 2. 핵심 원칙
|
||||
|
||||
- 기존 Baron SSO API 응답을 `tdc114plus` 요구사항에 맞게 직접 변경하지 않는다.
|
||||
- `tdc114plus` 전용 endpoint와 response DTO를 둔다.
|
||||
- JSON field는 camelCase를 사용한다.
|
||||
- 목록 응답은 `items`, `limit`, `offset`, `total`, `nextCursor` 형식을 따른다.
|
||||
- 직원/조직 데이터는 Baron SSO `orgFront` 및 backend read model을 기준으로 제공한다.
|
||||
- 앱 자체 회원가입은 제공하지 않는다.
|
||||
- 미등록 사용자는 앱 사용을 허용하지 않는다.
|
||||
- 공지사항, 전자결재, 수신전화식별, 수신팝업은 1차 API 범위에서 제외한다.
|
||||
|
||||
## 3. 1차 구현 확정사항
|
||||
|
||||
| 항목 | 1차 구현 기준 | 후속 검토 |
|
||||
| --- | --- | --- |
|
||||
| 전화번호 로그인 보안 수준 | Baron SSO 등록 사용자 확인, rate limit, 감사 로그, generic error message 적용 | SMS OTP, 기기 등록, 내부망 제한, 추가 인증 |
|
||||
| token 종류 | 기존 Baron SSO session token 재사용 | 앱 전용 access token 또는 refresh token 분리 |
|
||||
| 개인정보 마스킹 범위 | Baron SSO 등록 사용자에게 직원 검색/조직도 기본 필드 노출 | 권한별 전화번호/이메일/직급 마스킹 정책 |
|
||||
| 즐겨찾기 동기화 | 1차는 앱 로컬 저장 | 서버 동기화 API 추가 |
|
||||
|
||||
본 확정사항은 1차 개발 범위를 빠르게 구현하기 위한 기준이다. 운영 배포 전 보안 리뷰에서 전화번호 로그인, token 저장, 개인정보 노출 범위는 재검토한다.
|
||||
|
||||
## 4. API namespace
|
||||
|
||||
권장 namespace:
|
||||
|
||||
```text
|
||||
/api/v1/tdc114plus
|
||||
```
|
||||
|
||||
이유:
|
||||
|
||||
- 기존 `/api/v1/admin/users`, `/api/v1/admin/orgchart/snapshot`은 관리자/orgFront 성격이 강하다.
|
||||
- 앱은 일반 등록 사용자용 직원검색/조직도 기능이므로 별도 namespace가 필요하다.
|
||||
- 향후 감사 로그, 마스킹, 앱별 권한 정책을 독립적으로 적용하기 쉽다.
|
||||
|
||||
## 5. 인증 API
|
||||
|
||||
### 5.1 전화번호 로그인
|
||||
|
||||
```http
|
||||
POST /api/v1/tdc114plus/auth/phone-login
|
||||
```
|
||||
|
||||
설명:
|
||||
|
||||
- 사용자가 앱 로그인창에 전화번호를 입력하면 Baron SSO 등록 사용자 여부를 확인한다.
|
||||
- 등록 사용자이면 앱 사용에 필요한 Baron SSO session token을 반환한다.
|
||||
- 기존 Baron SSO의 `/api/v1/auth/phone-login` 흐름을 참고하되, `tdc114plus` 전용 DTO와 오류 정책을 둔다.
|
||||
|
||||
요청:
|
||||
|
||||
```json
|
||||
{
|
||||
"phoneNumber": "01012345678",
|
||||
"device": {
|
||||
"platform": "android",
|
||||
"appVersion": "0.1.0",
|
||||
"deviceName": "Pixel 8"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"token": "baron-sso-session-token",
|
||||
"expiresAt": "2026-07-02T12:00:00Z",
|
||||
"user": {
|
||||
"id": "user-uuid",
|
||||
"name": "홍길동",
|
||||
"phoneNumber": "+821012345678",
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantName": "한맥",
|
||||
"tenantSlug": "hanmac",
|
||||
"department": "기술연구소",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
오류:
|
||||
|
||||
| HTTP | code | 설명 |
|
||||
| --- | --- | --- |
|
||||
| 400 | `invalid_phone_number` | 전화번호 형식 오류 |
|
||||
| 401 | `login_failed` | 등록 사용자 확인 실패. 사용자 존재 여부를 과도하게 드러내지 않는다. |
|
||||
| 429 | `rate_limited` | 반복 시도 제한 |
|
||||
| 503 | `identity_provider_unavailable` | Kratos/SSO 조회 실패 |
|
||||
|
||||
보안 메모:
|
||||
|
||||
- 전화번호 단독 로그인은 표준 인증으로 보기 어렵다.
|
||||
- 1차 정책상 Baron SSO 등록 인원 확인용으로 사용하되, rate limit, 감사 로그, generic error message를 적용한다.
|
||||
- 운영 전에는 SMS OTP, 기기 등록, 내부망 제한, 추가 인증 중 하나 이상을 후속 검토한다.
|
||||
|
||||
### 5.2 내 프로필
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/me
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"name": "홍길동",
|
||||
"phoneNumber": "+821012345678",
|
||||
"email": "user@example.com",
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantName": "한맥",
|
||||
"tenantSlug": "hanmac",
|
||||
"department": "기술연구소",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발",
|
||||
"permissions": {
|
||||
"directory": true,
|
||||
"organization": true,
|
||||
"favoritesSync": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 직원검색/전화번호검색 API
|
||||
|
||||
### 6.1 직원 목록 및 검색
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/directory/employees
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
Query:
|
||||
|
||||
| 이름 | 필수 | 설명 |
|
||||
| --- | --- | --- |
|
||||
| `q` | N | 이름, 전화번호, 부서, 직위, 직무 검색어 |
|
||||
| `tenantId` | N | 가족사/회사/조직 필터 |
|
||||
| `tenantSlug` | N | 가족사 slug 필터 |
|
||||
| `department` | N | 부서명 필터 |
|
||||
| `limit` | N | 기본 50 |
|
||||
| `offset` | N | 기본 0 |
|
||||
| `cursor` | N | cursor pagination 사용 시 |
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"name": "홍길동",
|
||||
"phoneNumber": "+821012345678",
|
||||
"phoneDisplay": "010-1234-5678",
|
||||
"email": "user@example.com",
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantName": "한맥",
|
||||
"tenantSlug": "hanmac",
|
||||
"department": "기술연구소",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발",
|
||||
"status": "active",
|
||||
"profileImageUrl": null,
|
||||
"sortOrder": 100
|
||||
}
|
||||
],
|
||||
"limit": 50,
|
||||
"offset": 0,
|
||||
"total": 1,
|
||||
"nextCursor": ""
|
||||
}
|
||||
```
|
||||
|
||||
검색 규칙:
|
||||
|
||||
- `q`는 이름, 전화번호, 부서, 직위, 직책, 직무, 이메일 일부를 대상으로 한다.
|
||||
- 전화번호 검색은 숫자만 입력해도 매칭되도록 서버에서 정규화한다.
|
||||
- 기본 노출 대상은 조직도 표시 가능한 사용자 상태로 제한한다.
|
||||
- Baron SSO 기준 `active`, `temporary_leave`, `suspended`는 조직도 노출 후보로 볼 수 있다.
|
||||
- `baron_guest`, `extended_leave`, `archived`는 기본 제외한다.
|
||||
|
||||
### 6.2 직원 상세
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/directory/employees/{employeeId}
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"name": "홍길동",
|
||||
"phoneNumber": "+821012345678",
|
||||
"phoneDisplay": "010-1234-5678",
|
||||
"email": "user@example.com",
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantName": "한맥",
|
||||
"tenantSlug": "hanmac",
|
||||
"joinedTenants": [
|
||||
{
|
||||
"id": "tenant-uuid",
|
||||
"name": "한맥",
|
||||
"slug": "hanmac",
|
||||
"type": "COMPANY",
|
||||
"parentId": "parent-tenant-uuid"
|
||||
}
|
||||
],
|
||||
"department": "기술연구소",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발",
|
||||
"status": "active",
|
||||
"profileImageUrl": null,
|
||||
"actions": {
|
||||
"call": true,
|
||||
"sms": true,
|
||||
"email": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. 가족사 필터/조직도 API
|
||||
|
||||
### 7.1 가족사/조직 필터 목록
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/organization/tenants
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "tenant-uuid",
|
||||
"name": "한맥",
|
||||
"slug": "hanmac",
|
||||
"type": "COMPANY",
|
||||
"parentId": "hanmac-family-root",
|
||||
"memberCount": 120,
|
||||
"totalMemberCount": 350
|
||||
}
|
||||
],
|
||||
"generatedAt": "2026-07-02T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 조직도 snapshot
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/organization/orgchart
|
||||
Authorization: Bearer {token}
|
||||
```
|
||||
|
||||
Query:
|
||||
|
||||
| 이름 | 필수 | 설명 |
|
||||
| --- | --- | --- |
|
||||
| `tenantId` | N | 특정 가족사/조직 하위만 조회 |
|
||||
| `refresh` | N | 서버 캐시 refresh 요청. 기본 `false` |
|
||||
|
||||
응답:
|
||||
|
||||
```json
|
||||
{
|
||||
"tenants": [
|
||||
{
|
||||
"id": "tenant-uuid",
|
||||
"name": "기술연구소",
|
||||
"slug": "rnd",
|
||||
"type": "ORGANIZATION",
|
||||
"parentId": "company-tenant-uuid",
|
||||
"memberCount": 12,
|
||||
"totalMemberCount": 38
|
||||
}
|
||||
],
|
||||
"employees": [
|
||||
{
|
||||
"id": "user-uuid",
|
||||
"name": "홍길동",
|
||||
"phoneNumber": "+821012345678",
|
||||
"phoneDisplay": "010-1234-5678",
|
||||
"tenantId": "tenant-uuid",
|
||||
"tenantName": "기술연구소",
|
||||
"tenantSlug": "rnd",
|
||||
"department": "기술연구소",
|
||||
"grade": "책임",
|
||||
"position": "팀장",
|
||||
"jobTitle": "개발",
|
||||
"status": "active"
|
||||
}
|
||||
],
|
||||
"generatedAt": "2026-07-02T12:00:00Z",
|
||||
"cache": {
|
||||
"source": "redis",
|
||||
"hit": true,
|
||||
"ttlSeconds": 300
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
구현 참고:
|
||||
|
||||
- 기존 `GET /api/v1/admin/orgchart/snapshot`은 `tenants`, `users`, `generatedAt`, `cache` 구조를 가진다.
|
||||
- `tdc114plus` 응답은 앱 의미에 맞춰 `users` 대신 `employees`를 사용한다.
|
||||
- 기존 admin/orgFront API를 직접 변경하지 않고 별도 DTO에서 변환한다.
|
||||
|
||||
## 8. 즐겨찾기 API
|
||||
|
||||
1차 구현은 앱 로컬 저장을 기본으로 한다.
|
||||
|
||||
서버 동기화는 후속 단계에서 검토한다.
|
||||
|
||||
후속 후보:
|
||||
|
||||
```http
|
||||
GET /api/v1/tdc114plus/favorites
|
||||
PUT /api/v1/tdc114plus/favorites
|
||||
```
|
||||
|
||||
## 9. 오류 응답 공통 형식
|
||||
|
||||
Baron SSO API 설계 정책에 맞춰 신규 API는 `code`를 기본 포함한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "사람이 읽을 수 있는 메시지",
|
||||
"code": "machine_readable_code",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
공통 오류:
|
||||
|
||||
| HTTP | code | 설명 |
|
||||
| --- | --- | --- |
|
||||
| 400 | `invalid_request` | 요청 형식 오류 |
|
||||
| 401 | `unauthorized` | 토큰 없음/만료 |
|
||||
| 403 | `forbidden` | tdc114plus 사용 권한 없음 |
|
||||
| 404 | `not_found` | 직원/조직 없음 |
|
||||
| 429 | `rate_limited` | 과도한 요청 |
|
||||
| 503 | `dependency_unavailable` | Kratos, Redis, DB 등 의존성 장애 |
|
||||
|
||||
## 10. 개인정보/보안 정책
|
||||
|
||||
- 전화번호 원문은 로그에 남기지 않고 마스킹 또는 정규화 값 일부만 기록한다.
|
||||
- 직원 검색/상세 조회는 감사 로그 대상으로 둔다.
|
||||
- 대량 조회, 짧은 시간 내 반복 조회는 이상 조회 탐지 후보로 기록한다.
|
||||
- 1차 구현에서는 Baron SSO 등록 사용자에게 직원 검색/조직도 기본 필드를 노출한다.
|
||||
- 권한별 민감정보 마스킹은 후속 정책에서 확정한다.
|
||||
- 1차 앱에서는 `call`, `sms` 액션을 제공하되, 앱 내부에서 수신전화식별/수신팝업 기능은 구현하지 않는다.
|
||||
|
||||
## 11. Baron SSO 구현 후보
|
||||
|
||||
신규 패키지/파일 후보:
|
||||
|
||||
```text
|
||||
backend/internal/domain/tdc114plus_models.go
|
||||
backend/internal/handler/tdc114plus_handler.go
|
||||
backend/internal/service/tdc114plus_service.go
|
||||
backend/internal/service/tdc114plus_service_test.go
|
||||
backend/internal/handler/tdc114plus_handler_test.go
|
||||
```
|
||||
|
||||
라우트 후보:
|
||||
|
||||
```go
|
||||
tdc114plus := api.Group("/tdc114plus")
|
||||
tdc114plus.Post("/auth/phone-login", tdc114plusHandler.PhoneLogin)
|
||||
tdc114plus.Get("/me", requireAnyUser, tdc114plusHandler.GetMe)
|
||||
tdc114plus.Get("/directory/employees", requireAnyUser, tdc114plusHandler.ListEmployees)
|
||||
tdc114plus.Get("/directory/employees/:id", requireAnyUser, tdc114plusHandler.GetEmployee)
|
||||
tdc114plus.Get("/organization/tenants", requireAnyUser, tdc114plusHandler.ListTenants)
|
||||
tdc114plus.Get("/organization/orgchart", requireAnyUser, tdc114plusHandler.GetOrgChart)
|
||||
```
|
||||
|
||||
## 12. 구현 전 확인사항
|
||||
|
||||
확정되어 바로 진행 가능한 항목:
|
||||
|
||||
- 전용 namespace `/api/v1/tdc114plus`
|
||||
- 전용 DTO
|
||||
- 기존 admin/user/orgchart API는 변경하지 않음
|
||||
- 직원/조직 데이터는 기존 orgchart snapshot 및 identity mirror/read model 기반으로 변환
|
||||
- 전화번호 로그인은 1차에서 등록자 확인 + rate limit + audit + generic error message 기준으로 구현
|
||||
- token은 1차에서 기존 Baron SSO session token 재사용
|
||||
- 개인정보는 1차에서 Baron SSO 등록 사용자에게 기본 필드 노출
|
||||
- 즐겨찾기는 1차에서 앱 로컬 저장
|
||||
|
||||
운영 배포 전 재검토 항목:
|
||||
|
||||
- SMS OTP, 기기 등록, 내부망 제한, 추가 인증 중 하나 이상 도입 여부
|
||||
- 앱 전용 access token 또는 refresh token 분리 여부
|
||||
- 권한별 개인정보 마스킹 범위
|
||||
- 즐겨찾기 서버 동기화 API 추가 여부
|
||||
@@ -1,112 +0,0 @@
|
||||
# tdc114plus 개발 정책
|
||||
|
||||
작성일: 2026-07-02
|
||||
|
||||
목적: `tdc114plus` 개발 중 Baron SSO 연동 방식, 개발 도구, AI coding assistant 활용 기준, Flutter/플랫폼 구현 원칙을 정리한다.
|
||||
|
||||
## 1. Baron SSO 연동 원칙
|
||||
|
||||
`tdc114plus` 개발 중 Baron SSO 소스코드와 연동이 필요한 부분은 기존 Baron SSO 소스코드를 임의로 변경해서 맞추지 않는다.
|
||||
|
||||
기본 원칙은 다음과 같다.
|
||||
|
||||
- `tdc114plus`에 필요한 데이터 요청, 인증 확인, 조직/직원 데이터 제공은 Baron SSO 쪽에 필요한 API를 생성하여 진행한다.
|
||||
- 기존 Baron SSO의 로그인, 세션, consent, userfront, orgFront 동작을 직접 변형하지 않는다.
|
||||
- 기존 API 응답 구조를 `tdc114plus` 요구사항에 맞춰 임의로 변경하지 않는다.
|
||||
- `tdc114plus` 전용 응답 형식이 필요하면 별도 API endpoint 또는 별도 response DTO를 둔다.
|
||||
- Baron SSO 소스 수정이 필요한 경우 `/home/ubuntu/workspace/baron-sso-tdc114plus-api`의 `feature/tdc114plus-api` 브랜치에서 진행한다.
|
||||
- `tdc114plus` 앱 저장소에는 Flutter 앱 코드, API client, model, provider, test를 둔다.
|
||||
- Baron SSO backend/orgFront 변경과 `tdc114plus` Flutter 앱 변경은 저장소와 커밋을 분리한다.
|
||||
|
||||
## 2. VS Code 기반 AI 개발 방식
|
||||
|
||||
앱 개발은 VS Code를 기본 IDE로 두고, AI coding assistant를 활용한 개발 방식을 권장한다.
|
||||
|
||||
목표:
|
||||
|
||||
- 반복적인 Flutter 화면/상태관리 코드 작성 속도를 높인다.
|
||||
- API 계약 변경 시 model, service, provider, test 코드를 일관되게 갱신한다.
|
||||
- 문서와 코드의 불일치를 줄인다.
|
||||
- 보안 민감 영역은 AI가 제안하더라도 사람이 반드시 리뷰한다.
|
||||
|
||||
권장 VS Code 구성:
|
||||
|
||||
| 항목 | 내용 |
|
||||
| --- | --- |
|
||||
| Flutter/Dart extension | Flutter 개발, debug, format, test 실행 |
|
||||
| REST Client 또는 Thunder Client | API 계약 검증 |
|
||||
| Docker extension | mock/preview 서버 실행 |
|
||||
| Git/Gitea 연동 | branch, commit, PR 확인 |
|
||||
| AI coding assistant | 코드 생성, 리팩터링, 테스트 초안, 문서화 보조 |
|
||||
|
||||
AI 활용 절차:
|
||||
|
||||
1. 작업 전 정책 문서와 API 계약을 먼저 확인한다.
|
||||
2. AI에게 변경 범위를 명확히 지시한다.
|
||||
3. 생성된 코드는 반드시 `flutter analyze`와 테스트를 통과시킨다.
|
||||
4. API 계약 변경이 있으면 문서, model, service, provider, test를 함께 갱신한다.
|
||||
5. 보안 민감 코드, 인증 코드, 개인정보 처리 코드는 사람이 직접 리뷰한다.
|
||||
|
||||
## 3. Flutter 공통 구현 원칙
|
||||
|
||||
- 공통 Flutter 코드는 처음부터 Android/iOS 모두를 고려해 작성한다.
|
||||
- 화면, 상태관리, API client, repository, model은 플랫폼 공통 코드로 우선 설계한다.
|
||||
- 플랫폼별 차이가 있는 기능은 공통 interface를 먼저 만들고 Android/iOS 구현체를 분리한다.
|
||||
- 공지사항, 전자결재, 수신전화식별, 수신팝업은 1차 범위에서 보류한다.
|
||||
- 1차 범위는 직원검색, 전화번호검색, 가족사 필터, 조직도, 직원목록, 전화걸기, 문자보내기, 즐겨찾기에 집중한다.
|
||||
|
||||
## 4. 플랫폼별 구현 원칙
|
||||
|
||||
- 플랫폼별 네이티브 기능은 Android에서 먼저 PoC를 완성한 뒤 iOS로 확장한다.
|
||||
- iOS를 너무 늦게 검증하지 않는다.
|
||||
- PoC 중에도 최소한 WebView, 로그인 세션, APNs 준비 가능 여부는 확인한다.
|
||||
- 푸시, 생체 인증, 보안 저장소, bridge는 플랫폼별 차이가 크므로 공통 인터페이스와 플랫폼 구현체를 분리한다.
|
||||
- 운영 배포 전에는 Android/iOS 모두 동일한 보안 기준을 통과해야 한다.
|
||||
|
||||
## 5. 검증 원칙
|
||||
|
||||
Flutter 앱 변경 시 최소 검증:
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh analyze
|
||||
./scripts/flutter-docker.sh test
|
||||
```
|
||||
|
||||
상세 테스트 기준은 아래 정식 정책을 따른다.
|
||||
|
||||
- `docs/tdc114plus-testing-policy-2026-07-02.md`
|
||||
|
||||
Baron SSO API 변경 시 최소 검증:
|
||||
|
||||
- 변경한 backend/orgFront 영역의 기존 테스트 확인
|
||||
- 신규 API handler/service/model 테스트 추가
|
||||
- 기존 로그인, 세션, userfront, orgFront 주요 흐름 회귀 확인
|
||||
- API 계약 문서와 구현 응답 형식 일치 확인
|
||||
|
||||
## 6. 질문 및 확인 원칙
|
||||
|
||||
작업 진행 중 확인사항이나 질문이 발생하면, 먼저 관련 정책/결정/참고 md 파일을 확인한다.
|
||||
|
||||
진행 순서:
|
||||
|
||||
1. 현재 작업과 관련된 정책 문서를 먼저 확인한다.
|
||||
2. 정책 문서에서 판단 가능한 내용은 문서 기준으로 진행한다.
|
||||
3. 정책 간 충돌, 해석 불명확, 보안 영향, 기존 Baron SSO 동작 변경, 배포 영향이 있는 경우에만 사용자에게 질문한다.
|
||||
4. 사용자에게 질문할 때는 확인한 문서, 판단이 필요한 지점, 가능한 선택지, 권장안을 함께 제시한다.
|
||||
5. 새로운 결정이 내려지면 관련 md 문서와 작업진행 타임테이블을 갱신한다.
|
||||
|
||||
즉, 작업 중 매 판단마다 바로 질문하지 않는다. 먼저 문서를 확인하고, 문서 기준으로 처리 가능한 작업은 진행한다. 문서 확인 후에도 결정이 필요한 경우에만 질문한다.
|
||||
|
||||
## 7. 문서 우선순위
|
||||
|
||||
개발 중 판단 기준은 아래 순서로 적용한다.
|
||||
|
||||
1. `docs/tdc114plus-development-decision-brief-2026-07-01.md`
|
||||
2. `docs/tdc114plus-work-progress-timetable-2026-07-02.md`
|
||||
3. `docs/tdc114plus-development-policy-2026-07-02.md`
|
||||
4. `docs/tdc114plus-testing-policy-2026-07-02.md`
|
||||
5. `docs/tdc114plus-api-contract-2026-07-02.md`
|
||||
6. `docs/baron-sso-reference-source-policy-2026-07-02.md`
|
||||
7. `docs/references/baron-safe-policies/`
|
||||
|
||||
Baron Safe 참고 문서는 참고 자료이며, `tdc114plus`의 직접 정책보다 우선하지 않는다.
|
||||
@@ -1,108 +0,0 @@
|
||||
# tdc114plus 테스트 자동화 스크립트 계획
|
||||
|
||||
작성일: 2026-07-02
|
||||
상태: v1.0 초기 스크립트 기준
|
||||
|
||||
목적: `docs/tdc114plus-testing-policy-2026-07-02.md`에 정의한 테스트 정책을 실제 `scripts/` 파일과 연결하고, 즉시 사용 가능한 스크립트와 향후 구현이 필요한 scaffold 스크립트를 구분한다.
|
||||
|
||||
## 1. 즉시 사용 가능한 스크립트
|
||||
|
||||
| 스크립트 | 목적 | 실행 예 |
|
||||
| --- | --- | --- |
|
||||
| `scripts/format-dart.sh` | Docker Flutter 이미지에서 `dart format lib test` 실행 | `./scripts/format-dart.sh` |
|
||||
| `scripts/quality-gate.sh` | `flutter analyze`, `flutter test` 순차 실행 | `./scripts/quality-gate.sh` |
|
||||
| `scripts/generate-release-report.sh` | git 상태와 릴리스 체크리스트 report 생성 | `./scripts/generate-release-report.sh` |
|
||||
| `scripts/perf_smoke.sh` | 현재 앱/테스트 파일 수와 기본 상태 출력 | `./scripts/perf_smoke.sh` |
|
||||
|
||||
## 2. Scaffold 상태의 스크립트
|
||||
|
||||
아래 스크립트는 파일은 존재하지만, 기반 기능이 아직 없으므로 실행 시 scaffold 안내와 함께 종료한다.
|
||||
|
||||
| 스크립트 | 현재 상태 | 완성 조건 |
|
||||
| --- | --- | --- |
|
||||
| `scripts/mock-server.sh` | `status`, `stop`은 가능. `start`는 미구현 안내 | API 계약 기반 mock server 구현 |
|
||||
| `scripts/save-snapshots.sh` | snapshot source가 있으면 report 경로로 복사 | widget/integration screenshot 또는 snapshot 생성 체계 |
|
||||
| `scripts/integration_tests.sh` | `TDC114_API_BASE`와 `integration_test/` 필요 | staging API 또는 mock server 기반 integration test |
|
||||
| `scripts/redteam/run_all.sh` | 현재 AI 기능 없음 안내 | LLM/프롬프트 기반 기능이 실제 추가될 때 |
|
||||
|
||||
## 3. Phase별 사용 기준
|
||||
|
||||
### Phase 3: Mock 기반 1차 UI
|
||||
|
||||
필수:
|
||||
|
||||
```bash
|
||||
./scripts/format-dart.sh
|
||||
./scripts/quality-gate.sh
|
||||
```
|
||||
|
||||
선택:
|
||||
|
||||
```bash
|
||||
./scripts/save-snapshots.sh
|
||||
```
|
||||
|
||||
단, snapshot 산출물이 생긴 뒤 사용한다.
|
||||
|
||||
### Phase 4: 실제 API 연동
|
||||
|
||||
필수 후보:
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=https://staging.example.com ./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
완성 조건:
|
||||
|
||||
- `app/integration_test/` 테스트 추가
|
||||
- staging 또는 local mock API endpoint 확정
|
||||
- 민감정보 없는 test fixture 사용
|
||||
|
||||
### Phase 5: 핵심 액션
|
||||
|
||||
필수 후보:
|
||||
|
||||
```bash
|
||||
./scripts/quality-gate.sh
|
||||
./scripts/perf_smoke.sh
|
||||
```
|
||||
|
||||
추가 예정:
|
||||
|
||||
- 전화걸기/문자보내기 URL 생성 테스트
|
||||
- 즐겨찾기 로컬 저장소 테스트
|
||||
|
||||
### Phase 6: 빌드/배포 준비
|
||||
|
||||
필수 후보:
|
||||
|
||||
```bash
|
||||
./scripts/generate-release-report.sh
|
||||
```
|
||||
|
||||
추가 예정:
|
||||
|
||||
- Android debug APK build wrapper
|
||||
- 수동 검증 체크리스트 자동 생성
|
||||
|
||||
## 4. 운영 원칙
|
||||
|
||||
- 문서에 명령을 추가할 때는 실제 `scripts/` 파일도 함께 추가하거나 scaffold 상태를 명시한다.
|
||||
- scaffold 스크립트는 조용히 성공하지 않고, 미구현이면 non-zero exit code로 종료한다.
|
||||
- 실제 CI gate에 연결할 수 있는 스크립트는 `quality-gate.sh`부터 시작한다.
|
||||
- AI/LLM redteam 자동화는 현재 앱 범위 밖이므로 `redteam/run_all.sh`는 보류 상태로 유지한다.
|
||||
- 자동화 스크립트 실행 결과는 `docs/test-logs/YYYY-MM-test-execution-log.md`에 월별로 누적 기록한다.
|
||||
|
||||
## 5. Playwright MCP 활용 예정
|
||||
|
||||
Playwright MCP는 향후 web/preview 기반 화면 확인이 가능해지는 시점부터 테스트 정책에 활용한다.
|
||||
|
||||
우선 적용 후보:
|
||||
|
||||
- 로그인 화면 smoke test
|
||||
- 직원목록/검색/가족사 필터 화면 회귀 확인
|
||||
- 직원 상세 화면 표시 확인
|
||||
- screenshot 기반 UI 리뷰 자료 생성
|
||||
- 텍스트 overflow, 주요 버튼 표시, 라우팅 이동 확인
|
||||
|
||||
현재는 Flutter web/preview 실행 방식이 확정되지 않았으므로 별도 `scripts/playwright-*` 파일은 만들지 않는다. 실행 방식이 확정되면 Playwright MCP 시나리오 문서와 월별 테스트 로그 기록 형식을 추가한다.
|
||||
@@ -1,294 +0,0 @@
|
||||
# tdc114plus 테스트 정책
|
||||
|
||||
작성일: 2026-07-02
|
||||
상태: v1.0 1차 개발 기준 확정
|
||||
|
||||
목적: `tdc114plus` Flutter 앱 개발 중 적용할 테스트 기준, 자동화 원칙, 단계별 검증 범위를 정의한다. 본 문서는 `docs/references/ai-testing/ai_testing_policy_draft.md`의 일반 원칙 중 `tdc114plus`에 적용 가능한 부분을 앱/API/보안 중심으로 재해석한 정식 정책이다.
|
||||
|
||||
## 1. 적용 범위
|
||||
|
||||
본 정책은 아래 영역에 적용한다.
|
||||
|
||||
- Flutter 앱 화면, 라우팅, 상태관리
|
||||
- API client, repository, provider
|
||||
- API 계약 기반 model, DTO, JSON 변환
|
||||
- Baron SSO 로그인 연동
|
||||
- orgFront 직원/조직 데이터 연동
|
||||
- 전화번호, 개인정보, 즐겨찾기 로컬 저장
|
||||
- 전화걸기, 문자보내기 등 플랫폼 액션
|
||||
|
||||
현재 `tdc114plus`는 LLM/AI 추론 기능을 포함하지 않으므로 아래 항목은 1차 적용 대상에서 제외한다.
|
||||
|
||||
- AI 모델 추론 결과 평가
|
||||
- Evaluator LLM 기반 자동 채점
|
||||
- multi-engine AI 교차 검증
|
||||
- 프롬프트 jailbreak/redteam matrix
|
||||
- PSI 기반 AI 학습 데이터 drift 계산
|
||||
|
||||
위 항목은 향후 앱에 실제 AI 기능이 추가될 경우 별도 정책으로 확장한다.
|
||||
|
||||
## 2. 기본 검증 게이트
|
||||
|
||||
Flutter 앱 코드를 변경한 모든 작업은 아래 검증을 통과해야 한다.
|
||||
|
||||
```bash
|
||||
./scripts/flutter-docker.sh analyze
|
||||
./scripts/flutter-docker.sh test
|
||||
```
|
||||
|
||||
추가로 Dart 파일을 많이 수정했거나 새 파일을 추가한 경우 formatter를 적용한다.
|
||||
|
||||
```bash
|
||||
./scripts/format-dart.sh
|
||||
```
|
||||
|
||||
검증 실패 상태의 코드는 `main` 브랜치에 반영하지 않는다.
|
||||
|
||||
자동화 스크립트의 구현 상태와 향후 보강 계획은 아래 문서를 따른다.
|
||||
|
||||
- `docs/tdc114plus-script-automation-plan-2026-07-02.md`
|
||||
|
||||
## 3. 테스트 강도 기준
|
||||
|
||||
### 3.1 강한 테스트가 필요한 영역
|
||||
|
||||
아래 영역은 결정론적 로직으로 보고 단위 테스트를 우선 작성한다.
|
||||
|
||||
- API model `fromJson`, `toJson`
|
||||
- API error parsing
|
||||
- 전화번호 입력 검증 및 정규화
|
||||
- 로그인 성공/실패 상태 전이
|
||||
- 인증 token 저장/삭제
|
||||
- 직원검색 query/filter 생성
|
||||
- 가족사/조직 필터 상태
|
||||
- 즐겨찾기 추가/삭제/조회
|
||||
- 개인정보 표시/마스킹 정책
|
||||
- API 실패, 401, 403, 404, timeout 처리
|
||||
|
||||
이 영역의 테스트는 통과율 100%를 기준으로 한다.
|
||||
|
||||
### 3.2 화면 테스트가 필요한 영역
|
||||
|
||||
아래 화면 흐름은 widget test 또는 integration test로 검증한다.
|
||||
|
||||
- 앱 실행 후 로그인 화면 표시
|
||||
- 전화번호 입력 후 로그인 성공/실패 흐름
|
||||
- 직원목록 진입
|
||||
- 직원 검색어 입력과 결과 표시
|
||||
- 가족사 필터 선택/해제
|
||||
- 조직도 화면 탐색
|
||||
- 직원 상세 화면 표시
|
||||
- 전화걸기/문자보내기 액션 노출
|
||||
- 즐겨찾기 토글
|
||||
|
||||
Phase 3에서는 실제 API가 없으므로 mock 데이터와 fake repository를 사용한다.
|
||||
|
||||
### 3.3 Playwright MCP 활용 예정 영역
|
||||
|
||||
향후 화면 회귀 검증과 브라우저 기반 점검에는 Playwright MCP를 활용한다.
|
||||
|
||||
적용 후보:
|
||||
|
||||
- Flutter web 또는 preview 환경에서 로그인/직원목록/상세 화면 흐름 점검
|
||||
- mock 데이터 기반 검색/필터 UI 회귀 확인
|
||||
- 화면 깨짐, overflow, 주요 텍스트 노출 여부 확인
|
||||
- screenshot 기반 수동 리뷰 자료 생성
|
||||
- Baron SSO orgFront/backend 관리 화면 확인이 필요한 경우 브라우저 자동화 보조
|
||||
|
||||
현재 1차 앱은 Android/iOS Flutter 앱 중심이므로 Playwright MCP는 필수 검증 게이트가 아니다. Phase 3에서 web/preview 실행 방식이 정해지면 Playwright MCP 검증 시나리오와 실행 로그 기록 방식을 추가한다.
|
||||
|
||||
## 4. 단계별 테스트 전략
|
||||
|
||||
### 4.1 Phase 3: Mock 기반 1차 UI
|
||||
|
||||
목표:
|
||||
|
||||
- API 없이 앱의 핵심 화면 흐름을 검증한다.
|
||||
- 확정 API 계약과 Dart model이 화면에서 자연스럽게 사용되는지 확인한다.
|
||||
|
||||
필수 테스트:
|
||||
|
||||
- mock 직원 목록 렌더링
|
||||
- 검색어 입력 시 목록 필터링
|
||||
- 가족사 필터 선택 시 목록 필터링
|
||||
- 직원 상세 진입
|
||||
- 즐겨찾기 토글 상태 변경
|
||||
- 로그인 화면에서 직원목록 화면으로 이동
|
||||
|
||||
선택 테스트:
|
||||
|
||||
- Playwright MCP 기반 web/preview 화면 smoke test
|
||||
- Playwright MCP screenshot 기반 UI 회귀 확인
|
||||
|
||||
완료 기준:
|
||||
|
||||
- `flutter analyze` 통과
|
||||
- `flutter test` 통과
|
||||
- 주요 mock 시나리오 widget test 추가
|
||||
|
||||
### 4.2 Phase 4: 실제 API 연동
|
||||
|
||||
목표:
|
||||
|
||||
- Baron SSO와 orgFront 연동 시 계약 불일치를 조기에 발견한다.
|
||||
- 인증/권한/오류 처리 흐름을 검증한다.
|
||||
|
||||
필수 테스트:
|
||||
|
||||
- API response parsing
|
||||
- 로그인 성공/실패
|
||||
- 미등록 사용자 오류
|
||||
- session token 저장/삭제
|
||||
- 직원목록 API 성공/실패
|
||||
- 조직도 API 성공/실패
|
||||
- 401/403 발생 시 재로그인 또는 오류 안내
|
||||
- 네트워크 timeout 대응
|
||||
|
||||
완료 기준:
|
||||
|
||||
- API client/repository 단위 테스트
|
||||
- staging 또는 mock server 기반 연동 테스트
|
||||
- API 계약 문서와 구현 응답 필드 일치 확인
|
||||
|
||||
### 4.3 Phase 5: 핵심 액션
|
||||
|
||||
목표:
|
||||
|
||||
- 전화걸기, 문자보내기, 즐겨찾기 기능을 사용자 흐름 기준으로 검증한다.
|
||||
|
||||
필수 테스트:
|
||||
|
||||
- 전화번호가 없는 직원의 call/sms 액션 비활성
|
||||
- 전화번호가 있는 직원의 call/sms URL 생성
|
||||
- 즐겨찾기 로컬 저장/삭제/복원
|
||||
- 앱 재실행 후 즐겨찾기 유지
|
||||
|
||||
완료 기준:
|
||||
|
||||
- 플랫폼 액션 wrapper 테스트
|
||||
- 즐겨찾기 repository 테스트
|
||||
- 수동 검증 체크리스트 작성
|
||||
|
||||
### 4.4 Phase 6: 빌드/배포 준비
|
||||
|
||||
목표:
|
||||
|
||||
- Android APK와 최소 iOS 준비 상태를 확인한다.
|
||||
- 운영 배포 전 보안 민감 영역을 재검토한다.
|
||||
|
||||
필수 테스트:
|
||||
|
||||
- Android debug APK 빌드
|
||||
- 앱 시작 smoke test
|
||||
- 로그인/검색/상세/즐겨찾기 주요 흐름 수동 검증
|
||||
- token 저장 위치 검토
|
||||
- 전화번호/이메일/직급 노출 범위 검토
|
||||
|
||||
완료 기준:
|
||||
|
||||
- APK 빌드 성공
|
||||
- 주요 수동 검증 체크리스트 통과
|
||||
- 운영 배포 전 보안 재검토 항목 문서화
|
||||
|
||||
## 5. 커버리지 정책
|
||||
|
||||
초기 개발 속도를 고려하여 전체 라인 커버리지 수치를 즉시 강제하지 않는다.
|
||||
|
||||
단계별 기준:
|
||||
|
||||
| 단계 | 기준 |
|
||||
| --- | --- |
|
||||
| Phase 3 | 핵심 model과 mock UI 흐름 테스트 확보 |
|
||||
| Phase 4 | API client/repository/error 처리 테스트 확보 |
|
||||
| Phase 5 | 즐겨찾기와 연락 액션 테스트 확보 |
|
||||
| Phase 6 | 주요 기능 회귀 테스트와 수동 검증 체크리스트 확보 |
|
||||
|
||||
장기 목표:
|
||||
|
||||
- 핵심 도메인/model/repository 라인 커버리지 80% 이상
|
||||
- 로그인, 개인정보, token 처리 영역 테스트 누락 없음
|
||||
- 주요 사용자 시나리오 90% 이상 테스트 또는 수동 체크리스트로 관리
|
||||
|
||||
## 6. 보안 민감 영역 테스트
|
||||
|
||||
아래 항목은 일반 UI 변경보다 높은 기준으로 검증한다.
|
||||
|
||||
- 전화번호 로그인
|
||||
- SSO 미등록 사용자 처리
|
||||
- session token 저장/삭제
|
||||
- 로그아웃
|
||||
- 개인정보 노출 필드
|
||||
- 직원 검색/상세 조회
|
||||
- 네트워크 오류와 인증 만료
|
||||
|
||||
원칙:
|
||||
|
||||
- 미등록 사용자 여부를 과도하게 드러내는 메시지를 피한다.
|
||||
- 전화번호 원문을 로그에 남기지 않는다.
|
||||
- token 값을 테스트 fixture나 로그에 실제값으로 남기지 않는다.
|
||||
- 개인정보 마스킹 정책이 변경되면 model, UI, test를 함께 갱신한다.
|
||||
|
||||
## 7. Mock 데이터 정책
|
||||
|
||||
Mock 데이터는 확정 API 계약과 같은 field 이름을 사용한다.
|
||||
|
||||
필수 mock case:
|
||||
|
||||
- 로그인 성공 사용자
|
||||
- 로그인 실패 사용자
|
||||
- 직원목록 0건
|
||||
- 직원목록 다건
|
||||
- 가족사 2개 이상
|
||||
- 조직도 parent/child 구조
|
||||
- 전화번호가 없는 직원
|
||||
- 이메일이 없는 직원
|
||||
- 즐겨찾기 등록된 직원
|
||||
|
||||
Mock 데이터가 API 계약과 달라지는 경우 API 계약 문서를 먼저 확인하고, 필요한 경우 계약 문서와 model/test를 함께 수정한다.
|
||||
|
||||
## 8. 리포트 및 기록
|
||||
|
||||
자동화 검증 결과는 커밋 메시지 또는 작업 완료 보고에 아래 형식으로 요약한다.
|
||||
|
||||
```text
|
||||
검증:
|
||||
- ./scripts/flutter-docker.sh analyze
|
||||
- ./scripts/flutter-docker.sh test
|
||||
```
|
||||
|
||||
세부 테스트 실행 결과는 월별 누적 로그에 기록한다.
|
||||
|
||||
```text
|
||||
docs/test-logs/YYYY-MM-test-execution-log.md
|
||||
```
|
||||
|
||||
예시:
|
||||
|
||||
```text
|
||||
docs/test-logs/2026-07-test-execution-log.md
|
||||
```
|
||||
|
||||
각 로그 항목은 `YYYY-MM-DD HH:mm KST` 단위로 남기고, 목적, 실행 명령, 결과, 주요 출력, 후속 조치를 포함한다.
|
||||
|
||||
실행하지 못한 검증이 있으면 이유를 함께 기록한다.
|
||||
|
||||
## 9. 참고 문서와 우선순위
|
||||
|
||||
참고 원문:
|
||||
|
||||
- `docs/references/ai-testing/ai_testing_policy_draft.md`
|
||||
- `docs/references/ai-testing/tdc114plus_test_strategy.md`
|
||||
- `docs/tdc114plus-script-automation-plan-2026-07-02.md`
|
||||
- `docs/test-logs/README.md`
|
||||
|
||||
본 문서는 위 참고문서보다 `tdc114plus` 개발에 우선 적용한다.
|
||||
|
||||
정책 우선순위:
|
||||
|
||||
1. `docs/tdc114plus-development-decision-brief-2026-07-01.md`
|
||||
2. `docs/tdc114plus-work-progress-timetable-2026-07-02.md`
|
||||
3. `docs/tdc114plus-development-policy-2026-07-02.md`
|
||||
4. `docs/tdc114plus-testing-policy-2026-07-02.md`
|
||||
5. `docs/tdc114plus-api-contract-2026-07-02.md`
|
||||
6. `docs/baron-sso-reference-source-policy-2026-07-02.md`
|
||||
7. `docs/references/`
|
||||
@@ -1,143 +0,0 @@
|
||||
# tdc114plus 작업진행 절차 및 타임테이블
|
||||
|
||||
작성일: 2026-07-02
|
||||
관리 원칙: 신규 작업이 발생하면 본 문서의 작업 목록과 타임테이블을 수정/추가하여 최신 상태로 유지한다.
|
||||
|
||||
## 1. 현재 기준
|
||||
|
||||
`tdc114plus`는 Baron SSO 등록 사용자를 대상으로 하는 직원검색/조직도 모바일 앱이다.
|
||||
|
||||
1차 개발은 아래 기본 기능에 집중한다.
|
||||
|
||||
- Baron SSO 전화번호 로그인
|
||||
- Baron SSO 등록 사용자만 앱 사용 허용
|
||||
- Baron SSO `orgFront` 기반 개인/조직 정보 연계
|
||||
- 직원검색
|
||||
- 전화번호검색
|
||||
- 가족사 필터
|
||||
- 조직도
|
||||
- 직원목록
|
||||
- 전화걸기
|
||||
- 문자보내기
|
||||
- 즐겨찾기
|
||||
|
||||
1차 보류 기능은 아래와 같다.
|
||||
|
||||
- 공지사항
|
||||
- 전자결재
|
||||
- 수신전화식별
|
||||
- 수신팝업
|
||||
|
||||
## 2. 작업진행 절차
|
||||
|
||||
| 순서 | 단계 | 상태 | 작업 내용 | 산출물 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | 저장소 초기화 | 완료 | Gitea `tdc114plus` 저장소 clone, `main` 브랜치 생성, 초기 문서/스크립트 구성 | 초기 커밋 |
|
||||
| 2 | 문서 이관 | 완료 | Baron SSO에 보관한 신규 앱 판단 문서와 개발환경 구성 문서를 `tdc114plus/docs/`로 이관 | `docs/*.md` |
|
||||
| 3 | Flutter 앱 골격 생성 | 완료 | `app/` 하위에 Android/iOS Flutter 프로젝트 생성 | Flutter 기본 프로젝트 |
|
||||
| 4 | Baron Safe식 기본 구조 반영 | 완료 | `core`, `features`, `shared` 방향의 기본 구조와 라우팅/상태관리 의존성 추가 | 앱 구조 초안 |
|
||||
| 5 | 기본 화면 뼈대 구성 | 완료 | Baron SSO 전화번호 로그인 화면, 직원검색 홈 화면 초안 구성 | 로그인/직원검색 화면 |
|
||||
| 6 | Docker Flutter 실행환경 구성 | 완료 | 로컬 Flutter 부재 대응용 Docker Flutter 스크립트 구성 | `scripts/flutter-docker.sh` |
|
||||
| 7 | 기본 검증 | 완료 | `flutter analyze`, `flutter test` 통과 확인 | 검증 결과 |
|
||||
| 8 | Baron Safe 참고 정책 이관 | 완료 | Baron Safe 진행 시 생성한 개발 정책 관련 md 파일을 참고 폴더로 복사 | `docs/references/baron-safe-policies/` |
|
||||
| 9 | Baron SSO 참조 소스 기준 정리 | 완료 | tdc114plus 개발 시 참조할 Baron SSO 원격/브랜치/업데이트 정책 정리 | `docs/baron-sso-reference-source-policy-2026-07-02.md` |
|
||||
| 10 | 최신 Baron SSO API 개발 worktree 생성 | 완료 | `origin/dev` 기준 `feature/tdc114plus-api` worktree를 생성해 orgFront/backend 확인 및 API 개발 준비 | `/home/ubuntu/workspace/baron-sso-tdc114plus-api` |
|
||||
| 11 | tdc114plus 개발 정책 정리 | 완료 | Baron SSO API 생성 우선 원칙, VS Code 기반 AI 개발 방식, Flutter/플랫폼 구현 원칙 정리 | `docs/tdc114plus-development-policy-2026-07-02.md` |
|
||||
| 12 | API 계약 정리 | 완료 | Baron SSO 로그인 API, orgFront 직원/조직 API 계약 정리 | `docs/tdc114plus-api-contract-2026-07-02.md` |
|
||||
| 13 | API 계약 검토 및 확정 | 완료 | API 계약 초안의 추가 확인사항 검토 후 1차 구현 기준 확정 | `docs/tdc114plus-api-contract-2026-07-02.md` |
|
||||
| 14 | 데이터 모델 설계 | 완료 | 직원, 조직, 가족사, 즐겨찾기 모델 정의 | Dart model 및 model test |
|
||||
| 15 | 테스트 정책 정식화 | 완료 | AI testing 참고 초안을 tdc114plus Flutter 앱/API/보안 중심 테스트 정책으로 재해석 | `docs/tdc114plus-testing-policy-2026-07-02.md` |
|
||||
| 16 | 테스트 자동화 스크립트 초기 구성 | 완료 | 테스트 정책 기반 scripts 추가 및 scaffold 상태 문서화 | `scripts/*.sh`, `docs/tdc114plus-script-automation-plan-2026-07-02.md` |
|
||||
| 17 | 테스트 실행 로그 관리 체계 생성 | 완료 | 월별 누적 테스트 로그 폴더와 2026-07 로그 파일 생성 | `docs/test-logs/` |
|
||||
| 18 | Mock 데이터 기반 화면 확장 | 완료 | 직원목록, 검색, 가족사 필터, 조직도, 직원 상세, 즐겨찾기 화면을 mock 데이터로 우선 구현 | 동작 가능한 UI 및 widget test |
|
||||
| 19 | Baron SSO 로그인 연동 | 다음 작업 | 전화번호 입력 후 SSO 등록 인원 여부 확인 연동 | 로그인 client/repository |
|
||||
| 20 | orgFront 데이터 연동 | 대기 | 직원/조직 데이터 API 연동 | directory/organization client |
|
||||
| 21 | 전화/문자 액션 구현 | 대기 | `url_launcher` 기반 전화걸기/문자보내기 구현 | 연락 액션 |
|
||||
| 22 | 즐겨찾기 구현 | 대기 | 1차 로컬 저장 기반 즐겨찾기 구현 | favorites feature |
|
||||
| 23 | Android APK 빌드 확인 | 대기 | debug APK 빌드 및 실행 확인 | APK 산출물 |
|
||||
|
||||
## 3. 단계별 타임테이블
|
||||
|
||||
| 단계 | 예상 순서 | 목표 | 주요 작업 | 완료 기준 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Phase 0 | 완료 | 저장소와 개발환경 출발점 확보 | clone, 문서 이관, README, scripts 구성 | Gitea `main` push 완료 |
|
||||
| Phase 1 | 완료 | Flutter 앱 실행 골격 확보 | Flutter create, 라우터, 로그인/직원검색 화면 초안 | analyze/test 통과 |
|
||||
| Phase 2 | 완료 | Baron SSO 참조 기준 확정 및 API 계약 준비 | 공식 `origin/dev` 기준 확인, API 개발 worktree 생성, Baron Safe 참고 정책 확인 | `feature/tdc114plus-api` worktree 생성 |
|
||||
| Phase 2-1 | 완료 | API 계약 초안 작성 | 개발 정책 확인 후 SSO 로그인 API, orgFront 직원/조직 API, 응답 필드, 오류 정책 정리 | API 계약 초안 작성 완료 |
|
||||
| Phase 2-2 | 완료 | API 계약 검토 및 확정 | token 종류, 전화번호 로그인 보안 수준, 개인정보 마스킹 범위, 즐겨찾기 동기화 여부 확인 | API 계약 확정본 |
|
||||
| Phase 2-3 | 완료 | Dart 데이터 모델 설계 | 확정된 API 계약 기준으로 직원, 조직, 로그인, 즐겨찾기 model 정의 | analyze/test 통과 |
|
||||
| Phase 2-4 | 완료 | 테스트 정책 정식화 | AI testing 참고 초안을 tdc114plus 적용 기준으로 정리 | `docs/tdc114plus-testing-policy-2026-07-02.md` |
|
||||
| Phase 2-5 | 완료 | 테스트 자동화 스크립트 초기 구성 | 즉시 실행 가능한 quality/format/report 스크립트와 scaffold 스크립트 추가 | `docs/tdc114plus-script-automation-plan-2026-07-02.md` |
|
||||
| Phase 2-6 | 완료 | 테스트 실행 로그 관리 체계 생성 | 월별 누적 테스트 로그 문서와 작성 규칙 추가 | `docs/test-logs/` |
|
||||
| Phase 3 | 완료 | Mock 기반 1차 UI 완성 | 직원목록, 검색, 가족사 필터, 조직도, 상세 화면 구성 | analyze/test 통과 |
|
||||
| Phase 4 | 다음 | 실제 API 연동 | SSO 로그인, orgFront 직원/조직 데이터 연동 | 등록 사용자 로그인 및 직원목록 조회 |
|
||||
| Phase 5 | 이후 | 핵심 액션 완성 | 전화걸기, 문자보내기, 즐겨찾기 저장 | 1차 기본 기능 수동 검증 |
|
||||
| Phase 6 | 이후 | 빌드/배포 준비 | Android debug APK, README 실행법, 잔여 이슈 정리 | APK 빌드 성공 |
|
||||
|
||||
## 4. 다음 작업 판단
|
||||
|
||||
현재 다음 작업은 **Phase 4: 실제 API 연동 준비 및 Baron SSO 로그인 연동**이다.
|
||||
|
||||
공식 Baron SSO `origin/dev` 기준의 API 개발용 worktree는 `/home/ubuntu/workspace/baron-sso-tdc114plus-api`에 생성 완료했다. 기존 `baron-sso` 작업 브랜치는 수정/미추적 파일이 많으므로 직접 merge/rebase하지 않는다.
|
||||
|
||||
API 계약 정리 시 아래 문서를 우선 참고한다.
|
||||
|
||||
- `docs/tdc114plus-development-policy-2026-07-02.md`
|
||||
- `docs/tdc114plus-testing-policy-2026-07-02.md`
|
||||
- `docs/baron-sso-reference-source-policy-2026-07-02.md`
|
||||
- `docs/references/baron-safe-policies/api-contract.md`
|
||||
- `docs/references/baron-safe-policies/runtime-config.md`
|
||||
- `docs/references/baron-safe-policies/nonstandard-phone-only-login-technical-review-2026-06-23.md`
|
||||
|
||||
우선 정리할 내용:
|
||||
|
||||
1. Baron SSO 전화번호 로그인 요청/응답 형식
|
||||
2. SSO 미등록 사용자 응답 정책
|
||||
3. 로그인 성공 후 앱이 저장하거나 유지해야 할 값
|
||||
4. orgFront 직원 목록 API 경로와 응답 필드
|
||||
5. orgFront 조직도 API 경로와 응답 필드
|
||||
6. 가족사 필터 기준 필드
|
||||
7. 개인정보 마스킹 또는 권한 필드 필요 여부
|
||||
8. API 실패/네트워크 오류 시 앱 표시 정책
|
||||
|
||||
API 계약 확정본:
|
||||
|
||||
- `docs/tdc114plus-api-contract-2026-07-02.md`
|
||||
|
||||
1차 구현 기준 확정사항:
|
||||
|
||||
1. 전화번호 로그인은 등록자 확인, rate limit, 감사 로그, generic error message 기준으로 구현한다.
|
||||
2. token은 기존 Baron SSO session token을 1차 재사용한다.
|
||||
3. 개인정보는 Baron SSO 등록 사용자에게 기본 필드를 노출한다.
|
||||
4. 즐겨찾기는 1차 앱 로컬 저장으로 구현한다.
|
||||
|
||||
## 5. 신규 작업 추가 규칙
|
||||
|
||||
새 작업이 발생하면 아래 기준으로 본 문서를 갱신한다.
|
||||
|
||||
- 바로 진행할 작업이면 `작업진행 절차`에 상태 `다음 작업`으로 추가한다.
|
||||
- 후속 검토 작업이면 상태 `대기`로 추가한다.
|
||||
- 보류 결정된 작업은 1차 범위와 섞지 않고 별도 보류 목록에 추가한다.
|
||||
- 완료된 작업은 상태를 `완료`로 바꾸고 산출물 위치를 기록한다.
|
||||
- 일정 또는 우선순위가 바뀌면 `단계별 타임테이블`의 Phase를 수정한다.
|
||||
|
||||
## 6. 질문 및 확인 발생 시 처리 순서
|
||||
|
||||
작업 진행 중 확인사항이나 질문이 발생하면 아래 순서로 처리한다.
|
||||
|
||||
1. 관련 정책/결정/참고 md 파일을 먼저 확인한다.
|
||||
2. 문서 기준으로 판단 가능한 내용은 문서 기준에 따라 진행한다.
|
||||
3. 문서 확인 후에도 결정이 필요하거나 정책 충돌이 있으면 사용자에게 질문한다.
|
||||
4. 질문 시에는 확인한 문서, 판단 지점, 가능한 선택지, 권장안을 함께 제시한다.
|
||||
5. 사용자 답변으로 새 결정이 생기면 관련 md 파일과 본 타임테이블을 갱신한다.
|
||||
|
||||
## 7. 현재 원격 반영 상태 확인
|
||||
|
||||
`tdc114plus` 원격 저장소 반영 상태는 아래 명령으로 확인한다.
|
||||
|
||||
```bash
|
||||
git -C /home/ubuntu/workspace/tdc114plus log --oneline origin/main -n 10
|
||||
git -C /home/ubuntu/workspace/tdc114plus status --short --branch
|
||||
```
|
||||
|
||||
현재 문서 기준 다음 작업은 `Phase 4: 실제 API 연동 준비 및 Baron SSO 로그인 연동`이다.
|
||||
@@ -5,103 +5,641 @@
|
||||
## 2026-07-02 11:38 KST - API 계약 초안 문서화
|
||||
|
||||
- 목적: Baron SSO 로그인, 직원검색, 조직도 API 계약 초안 작성 상태 확인
|
||||
- 실행 명령:
|
||||
- 문서 확인 및 git diff 확인
|
||||
- 결과: 통과
|
||||
- 주요 출력:
|
||||
- `docs/tdc114plus-api-contract-2026-07-02.md` 생성
|
||||
- `docs/tdc114plus-work-progress-timetable-2026-07-02.md` 갱신
|
||||
- 후속 조치:
|
||||
- API 계약 검토 및 확정 단계로 이동
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 12:10 KST - Dart API 모델 검증
|
||||
|
||||
- 목적: 확정 API 계약 기준 Dart model과 JSON parsing 테스트 검증
|
||||
- 실행 명령:
|
||||
- `./scripts/flutter-docker.sh analyze`
|
||||
- `./scripts/flutter-docker.sh test`
|
||||
- 결과: 통과
|
||||
- 주요 출력:
|
||||
- `flutter analyze`: No issues found
|
||||
- `flutter test`: All tests passed
|
||||
- 후속 조치:
|
||||
- Phase 2-3 Dart 데이터 모델 설계 완료
|
||||
- 다음 단계는 Phase 3 Mock 기반 1차 UI 완성
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 13:05 KST - 테스트 정책 정식화 검토
|
||||
|
||||
- 목적: `ai_testing_policy_draft.md`를 tdc114plus에 적용 가능한 정책으로 재해석
|
||||
- 실행 명령:
|
||||
- `docs/references/ai-testing/ai_testing_policy_draft.md` 확인
|
||||
- `docs/references/ai-testing/tdc114plus_test_strategy.md` 확인
|
||||
- 결과: 통과
|
||||
- 주요 출력:
|
||||
- LLM/AI 추론 테스트 정책은 1차 앱 범위에서 제외
|
||||
- Flutter 앱/API/model/repository/보안 중심 테스트 정책으로 정식화
|
||||
- 후속 조치:
|
||||
- `docs/tdc114plus-testing-policy-2026-07-02.md` 생성
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 13:20 KST - 테스트 자동화 스크립트 초기 검증
|
||||
|
||||
- 목적: 테스트 정책에 맞춘 자동화 스크립트 scaffold와 즉시 실행 가능 스크립트 검증
|
||||
- 실행 명령:
|
||||
- `bash -n scripts/*.sh scripts/redteam/run_all.sh`
|
||||
- `./scripts/perf_smoke.sh`
|
||||
- `./scripts/mock-server.sh status`
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- 결과: 통과
|
||||
- 주요 출력:
|
||||
- shell 문법 검사 통과
|
||||
- `perf_smoke.sh`: app/test 파일 수 출력, runtime probe는 아직 미구현
|
||||
- `mock-server.sh status`: mock server not running
|
||||
- `format-dart.sh`: Formatted 16 files, 0 changed
|
||||
- `quality-gate.sh`: analyze 통과, All tests passed
|
||||
- 후속 조치:
|
||||
- `docs/tdc114plus-script-automation-plan-2026-07-02.md` 생성
|
||||
- Phase 3부터 `format-dart.sh`, `quality-gate.sh`를 기본 검증 명령으로 사용
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 13:35 KST - 테스트 로그 관리 체계 생성
|
||||
|
||||
- 목적: 테스트 진행과 결과를 월별 md 파일에 누적 기록하는 구조 생성
|
||||
- 실행 명령:
|
||||
- `mkdir -p docs/test-logs`
|
||||
- `docs/test-logs/README.md` 작성
|
||||
- `docs/test-logs/2026-07-test-execution-log.md` 작성
|
||||
- 결과: 통과
|
||||
- 주요 출력:
|
||||
- 테스트 로그 저장 위치: `docs/test-logs/`
|
||||
- 월별 누적 파일명: `YYYY-MM-test-execution-log.md`
|
||||
- 세부 항목은 `YYYY-MM-DD HH:mm KST` 단위로 기록
|
||||
- 후속 조치:
|
||||
- 이후 테스트/검증 실행 시 `docs/test-logs/2026-07-test-execution-log.md`에 계속 누적
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 13:45 KST - Playwright MCP 향후 활용 정책 반영
|
||||
|
||||
- 목적: 추후 Playwright MCP를 tdc114plus 테스트 정책에 활용할 수 있도록 예정 영역 명시
|
||||
- 실행 명령:
|
||||
- `docs/tdc114plus-testing-policy-2026-07-02.md` 갱신
|
||||
- `docs/tdc114plus-script-automation-plan-2026-07-02.md` 갱신
|
||||
- 결과: 통과
|
||||
- 주요 출력:
|
||||
- Playwright MCP는 현재 필수 게이트가 아닌 향후 web/preview 화면 회귀 검증 후보로 분리
|
||||
- Phase 3 선택 테스트에 Playwright MCP 기반 smoke/screenshot 검증 후보 추가
|
||||
- 후속 조치:
|
||||
- Flutter web/preview 실행 방식이 정해지면 Playwright MCP 시나리오와 로그 기록 방식을 구체화
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 14:05 KST - Phase 3 Mock UI 1차 구현 검증
|
||||
|
||||
- 목적: 직원목록, 검색, 가족사 필터, 조직도, 직원 상세, 즐겨찾기 mock UI 구현 결과 검증
|
||||
- 실행 명령:
|
||||
- 결과: [실패 후 통과]
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- 결과: 1차 실패 후 수정하여 통과
|
||||
- 주요 출력:
|
||||
- `format-dart.sh`: `directory_screen.dart`, `widget_test.dart` 포맷 적용
|
||||
- 1차 `quality-gate.sh`: analyze 통과, widget test 4건 실패
|
||||
- 실패 원인: 전역 `GoRouter`가 이전 테스트의 `/directory` 위치를 유지하여 helper가 로그인 버튼을 찾지 못함
|
||||
- 수정 내용: 테스트 helper가 이미 직원검색 화면이면 로그인 단계를 건너뛰도록 보정
|
||||
- 최종 `quality-gate.sh`: analyze 통과, `flutter test` All tests passed
|
||||
- 원인: 전역 `GoRouter`가 이전 테스트의 `/directory` 위치를 유지해 로그인 버튼 탐색 실패
|
||||
- 조치: 테스트 helper가 이미 직원검색 화면이면 로그인 단계를 건너뛰도록 보정
|
||||
- 최종: analyze 통과, `flutter test` All tests passed
|
||||
- 후속 조치:
|
||||
- Phase 3 Mock 기반 1차 UI 완성 처리
|
||||
- 다음 단계는 Phase 4 실제 API 연동 준비 및 Baron SSO 로그인 연동
|
||||
- Phase 4 실제 API 연동 준비 및 Baron SSO 로그인 연동 진행
|
||||
|
||||
## 2026-07-02 14:25 KST - Phase 4 Baron SSO 로그인 client 1차 검증
|
||||
|
||||
- 목적: `POST /api/v1/tdc114plus/auth/phone-login` 계약 기반 Flutter auth client, repository, session store, 로그인 화면 상태 검증
|
||||
- 결과: [실패 후 통과]
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- 주요 출력:
|
||||
- 1차 `quality-gate.sh`: analyzer lint 5건 실패
|
||||
- 2차 `quality-gate.sh`: widget test 1건 실패
|
||||
- 원인: auth client/repository 생성자 초기화 lint, 전역 `GoRouter` 상태 공유
|
||||
- 조치: 생성자 필드 초기화 방식 정리, 앱 build 시 `createAppRouter()`로 새 router 생성
|
||||
- 최종: analyze 통과, `flutter test` All tests passed
|
||||
- 후속 조치:
|
||||
- Baron SSO backend 전용 phone-login endpoint 구현
|
||||
|
||||
## 2026-07-02 14:45 KST - Phase 4 Baron SSO phone-login endpoint 1차 검증
|
||||
|
||||
- 목적: Baron SSO backend에 `tdc114plus` 전용 전화번호 로그인 endpoint와 응답 DTO, 전화번호 audit body masking 구현 검증
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 15:10 KST - Phase 4 직원/조직 API client 1차 검증
|
||||
|
||||
- 목적: Baron SSO backend의 `tdc114plus` 직원/조직 endpoint와 Flutter directory/organization API client 계약 검증
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 15:20 KST - 테스트 로그 작성 규칙 간소화
|
||||
|
||||
- 목적: 통과 로그는 컴팩트하게, 실패 발생 로그만 자세히 남기도록 규칙과 기존 로그 정리
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 15:25 KST - 테스트 로그 형식 재정의
|
||||
|
||||
- 목적: 통과 시 `[목적/결과]`, 실패 시 `[목적/명령/주요 출력/후속 조치]` 형식으로 로그 작성 규칙 재정의
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 15:35 KST - Phase 4 직원검색 repository 상태 전환 검증
|
||||
|
||||
- 목적: Flutter 직원검색/조직도 mock 화면을 `DirectoryRepository`/`FutureProvider` 기반 상태로 전환하고 API repository 주입 구조와 기존 UI 흐름을 검증
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 15:45 KST - Phase 4 Baron SSO 직원/조직 응답 정합성 보강 검증
|
||||
|
||||
- 목적: tdc114plus backend 직원/조직 endpoint의 tenant type 제한, 하위 조직 포함 `totalMemberCount`, 직원 정렬, 상세 추가소속 변환 로직 검증
|
||||
- 결과: [통과]
|
||||
|
||||
## 2026-07-02 15:55 KST - Phase 4 API smoke 스크립트 및 로컬 gateway 확인
|
||||
|
||||
- 목적: `TDC114_API_BASE` 대상 tdc114plus API smoke 자동화 추가와 현재 로컬 Baron SSO gateway 접근 상태 확인
|
||||
- 결과: [실패]
|
||||
- 명령:
|
||||
- `bash -n scripts/api-smoke.sh`
|
||||
- `TDC114_API_BASE=http://127.0.0.1:5000 ./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- `bash -n scripts/api-smoke.sh`: 통과
|
||||
- `api-smoke.sh`: `GET /api/v1/tdc114plus/directory/employees` 단계에서 HTTP 502
|
||||
- Docker 상태: `baron_gateway`, DB, Redis, ClickHouse는 실행 중이나 `baron_backend` 컨테이너는 미실행
|
||||
- Baron SSO API worktree에는 `.env.sample`만 있고 `.env`/`config/.generated` 실행 설정이 없어 backend compose 실행 전 환경 준비 필요
|
||||
- 후속 조치:
|
||||
- Baron SSO backend 실행 환경 파일과 민감정보 없는 `TDC114_SMOKE_PHONE` 테스트 계정 준비 후 API smoke 재실행
|
||||
|
||||
## 2026-07-03 10:20 KST - Phase 4 org-context external fallback 보강
|
||||
|
||||
- 목적: 외부 Baron org-context `includeUsers=true` 오류 발생 시 tdc114plus backend가 기존 DB 기반 직원검색/조직도 fallback을 사용하도록 보강
|
||||
- 결과: [코드 수정 완료]
|
||||
- 주요 작업:
|
||||
- `backend/internal/handler/tdc114plus_handler.go`의 `ListEmployees`, `GetEmployee`, `ListTenants`, `GetOrgChart`에서 external org-context 요청 실패 시 DB fallback으로 전환
|
||||
- `backend/internal/handler/tdc114plus_handler_test.go`에 external org-context 500 에러 시 DB fallback 동작 검증 테스트 추가
|
||||
- 검증:
|
||||
- `go` tooling 부재로 로컬 `go test` 실행 불가
|
||||
- 코드 및 테스트 구조 수정 완료
|
||||
- 후속 조치:
|
||||
- `go` 환경 설치 후 `go test ./backend/internal/handler` 실행
|
||||
|
||||
## 2026-07-02 15:05 KST - Phase 4 Flutter integration_test scaffold 검증
|
||||
|
||||
- 목적: `app/integration_test/` scaffold와 `scripts/integration_tests.sh` Dart define 연동, 디바이스 사전조건 안내 동작 검증
|
||||
- 결과: [실패]
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- `TDC114_API_BASE=http://127.0.0.1:5000 ./scripts/integration_tests.sh`
|
||||
- 주요 출력:
|
||||
- `format-dart.sh`: 통과
|
||||
- `quality-gate.sh`: analyze 통과, `flutter test` All tests passed
|
||||
- `integration_tests.sh`: `integration_test` scaffold는 인식되지만 `No supported devices connected.`
|
||||
- 현재 앱 프로젝트는 Android/iOS runner만 있고, Docker Flutter 환경에서 연결된 Android emulator/device 또는 추가 desktop/web runner가 없어 integration runtime 시작 불가
|
||||
- 스크립트에 디바이스 부재 시 원인과 다음 조치를 안내하는 메시지 추가
|
||||
- 후속 조치:
|
||||
- Android emulator/device 연결 또는 추가 desktop/web runner 준비 후 `scripts/integration_tests.sh` 재실행
|
||||
|
||||
## 2026-07-02 15:15 KST - 연락 액션 wrapper 및 widget test 검증
|
||||
|
||||
- 목적: `url_launcher` 기반 전화/SMS wrapper와 직원 상세 액션 버튼 연동, 버튼 비활성/호출 흐름 검증
|
||||
- 결과: [실패 후 통과]
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- 주요 출력:
|
||||
- 1차 `quality-gate.sh`: analyzer lint 1건 실패
|
||||
- 2차 `quality-gate.sh`: widget test 1건 실패
|
||||
- 원인: async gap 뒤 `BuildContext` 사용 lint, 검색 입력과 직원명 텍스트가 같은 finder 충돌
|
||||
- 조치: `ScaffoldMessenger`를 await 전 미리 확보하고, widget test에서 직원 목록 항목 finder를 명확히 지정
|
||||
- 최종: analyze 통과, `flutter test` All tests passed
|
||||
- 후속 조치:
|
||||
- 실제 Android/iOS 환경에서 전화/문자 launch smoke 진행
|
||||
|
||||
## 2026-07-02 15:21 KST - Phase 5 로컬 즐겨찾기 구현 검증
|
||||
|
||||
- 결과: [실패 후 통과]
|
||||
- 목적: `SharedPreferences` 기반 즐겨찾기 로컬 저장소와 직원목록/조직도/상세 화면의 즐겨찾기 토글 흐름 검증
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- 주요 출력:
|
||||
- 1차 `quality-gate.sh`: analyzer lint 1건 실패
|
||||
- 2차 `quality-gate.sh`: favorites repository test 2건 실패
|
||||
- 원인: 생성자 필드 초기화 lint, `SharedPreferencesAsync`의 테스트 platform mock 초기화 부재
|
||||
- 조치: 저장소 생성자 정리, 테스트용 `FavoritesKeyValueStore` 주입 구조 추가
|
||||
- 최종: analyze 통과, `flutter test` All tests passed
|
||||
- 후속 조치:
|
||||
- 실제 Android/iOS 환경에서 앱 재실행 후 즐겨찾기 유지 수동 검증
|
||||
|
||||
## 2026-07-02 15:29 KST - Phase 4 세션 복원 및 인증 만료 재로그인 검증
|
||||
|
||||
- 결과: [실패 후 통과]
|
||||
- 목적: 앱 시작 시 저장 세션 자동 진입과 직원/조직 조회 `401/403` 발생 시 재로그인 흐름 검증
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `./scripts/quality-gate.sh`
|
||||
- 주요 출력:
|
||||
- 1차 `quality-gate.sh`: auth gate `BuildContext` async gap lint 1건, widget test helper const/lifecycle 문제로 test 실패
|
||||
- 원인: `AuthGateScreen` post-frame async redirect 구현의 context lint, root route가 추가되며 기존 widget test가 로그인 화면 렌더링 완료 전 입력
|
||||
- 조치: router 참조를 동기 확보해 redirect 처리, test helper가 `AuthGate` 완료 후 상호작용하도록 보정
|
||||
- 최종: analyze 통과, `flutter test` All tests passed
|
||||
- 후속 조치:
|
||||
- 실제 Baron SSO 환경에서 세션 만료 토큰 또는 권한 없는 응답 기준 재로그인 수동 검증
|
||||
|
||||
## 2026-07-02 15:34 KST - Phase 4 Baron SSO 실행 준비 상태 점검 스크립트 검증
|
||||
|
||||
- 결과: [실패]
|
||||
- 목적: Baron SSO API worktree의 `.env`, compose, config, Docker runtime 준비 상태를 자동 점검해 API smoke blocker를 빠르게 확인
|
||||
- 명령:
|
||||
- `bash -n scripts/check-baron-api-env.sh`
|
||||
- `./scripts/check-baron-api-env.sh`
|
||||
- 주요 출력:
|
||||
- `bash -n`: 통과
|
||||
- `check-baron-api-env.sh`: Baron SSO worktree, compose, `.env.sample`, restored compose reference 확인
|
||||
- blocker: `/home/ubuntu/workspace/baron-sso-tdc114plus-api/.env` 부재
|
||||
- warning: `baron_net`, `ory-net`, `baron_backend`, `baron_gateway` 상태가 미준비 또는 현재 세션에서 확인 불가
|
||||
- 후속 조치:
|
||||
- Baron SSO worktree에 `.env`를 준비하고 Docker runtime 상태를 맞춘 뒤 `check-baron-api-env.sh`, `api-smoke.sh` 순서로 재실행
|
||||
|
||||
## 2026-07-02 15:48 KST - Phase 4 Baron SSO 로컬 runtime 재기동 및 API smoke 재검증
|
||||
|
||||
- 결과: [실패 후 부분 통과]
|
||||
- 목적: Baron SSO worktree `.env` bootstrap, backend/userfront 재기동, `tdc114plus` 최소 API smoke 재확인
|
||||
- 명령:
|
||||
- `./scripts/bootstrap-baron-api-env.sh`
|
||||
- `./scripts/check-baron-api-env.sh`
|
||||
- `docker compose up -d backend userfront`
|
||||
- `TDC114_API_BASE=http://127.0.0.1:5000 ./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- `.env.sample` 기반 Baron SSO `.env` 생성 및 localhost/알림 비활성 override 추가
|
||||
- stale `baron_backend`, `baron_userfront` 컨테이너 이름 충돌 정리 후 runtime 재기동
|
||||
- 1차 `api-smoke.sh`: sandbox localhost 제한으로 `curl (7)` 또는 userfront/gateway 준비 타이밍 영향으로 실패
|
||||
- 재검증: `unauthorized directory guard` HTTP 401, `invalid phone-login validation` HTTP 400 통과
|
||||
- authenticated smoke는 `TDC114_SMOKE_PHONE` 미설정으로 skip
|
||||
- 후속 조치:
|
||||
- 민감정보 없는 `TDC114_SMOKE_PHONE` 테스트 계정 준비 후 authenticated smoke 재실행
|
||||
|
||||
## 2026-07-02 15:50 KST - Phase 4 ORY runtime 재가동 확인
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: authenticated smoke에 필요한 Kratos/Hydra/Keto/Oathkeeper 로컬 runtime 상태 복구 확인
|
||||
- 명령:
|
||||
- `docker start ory_postgres ory_clickhouse ory_kratos ory_hydra ory_keto ory_oathkeeper ory_vector`
|
||||
- `docker ps --format '{{.Names}} {{.Status}}'`
|
||||
- `TDC114_API_BASE=http://127.0.0.1:5000 ./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- `baron_backend`, `baron_userfront`, `baron_gateway` healthy 확인
|
||||
- `ory_postgres`, `ory_kratos`, `ory_hydra`, `ory_keto`, `ory_oathkeeper` running 확인
|
||||
- 최소 API smoke 재실행 시 401/400 guard 검증 유지, authenticated smoke는 테스트 계정 미설정으로 skip
|
||||
|
||||
## 2026-07-02 15:54 KST - Phase 4 authenticated smoke env 주입 경로 검증
|
||||
|
||||
- 결과: [실패]
|
||||
- 목적: `api-smoke.sh`, `integration_tests.sh`가 `scripts/.env.smoke.local` 기반으로 authenticated smoke 값을 자동 로드하는지 검증
|
||||
- 명령:
|
||||
- `bash -n scripts/api-smoke.sh`
|
||||
- `bash -n scripts/integration_tests.sh`
|
||||
|
||||
## 2026-07-06 08:40 KST - 신규 전화번호 승인 로그인 API 전환 검증
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: 기존 선인증 `phone-login` 흐름과 별도로 `link/init -> link/poll -> 앱 세션 저장` 경로를 신규 API 형태로 추가하고, 기존 화면 영향 최소화 원칙을 지키는지 점검
|
||||
- 주요 작업:
|
||||
- Flutter auth client, repository, model, login screen에 승인 링크 요청/대기/polling 흐름 추가
|
||||
- Baron SSO backend에 `POST /api/v1/tdc114plus/auth/link/init`, `POST /api/v1/tdc114plus/auth/link/poll` route 및 handler 추가
|
||||
- 기존 직원검색, 상세, 즐겨찾기 흐름이 신규 로그인 추가로 회귀하지 않도록 앱 측 상태 전이 보강
|
||||
- 검증:
|
||||
- Flutter unit/widget 기준 신규 로그인 상태 흐름 반영 확인
|
||||
- backend handler/server test 기준 신규 route 동작 확인
|
||||
- 후속 조치:
|
||||
- Android emulator 기준 수동 화면 점검과 실제 승인 완료 E2E 준비
|
||||
|
||||
## 2026-07-06 09:10 KST - local Baron SSO runtime 링크 로그인 smoke 검증
|
||||
|
||||
- 결과: [부분 통과]
|
||||
- 목적: local Baron SSO runtime에서 `link/init`, `link/poll` API 계약과 기본 오류 응답이 실제 route 기준으로 동작하는지 확인
|
||||
- 명령:
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.smoke.local ./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- invalid `link/init` validation 400 확인
|
||||
- 임의 `pendingRef` 기준 `link/poll` expired pending 응답 확인
|
||||
- 실제 전화번호 `010-9136-5338` 기준 `link/init`은 `401 login_failed`
|
||||
- 원인: local Baron SSO runtime에는 해당 번호의 identity/user mirror가 준비되지 않아 local 승인 완료 경로를 끝까지 검증할 수 없음
|
||||
- 후속 조치:
|
||||
- staging Baron SSO 또는 동등 검증 환경에서 실제 승인 완료 E2E 검증 진행
|
||||
|
||||
## 2026-07-06 09:35 KST - Android emulator 신규 로그인 화면 흐름 점검
|
||||
|
||||
- 결과: [부분 통과]
|
||||
- 목적: 에뮬레이터에서 신규 전화번호 승인 로그인 UI가 보이고, 로그인 이후 직원검색 진입 흐름이 기존처럼 유지되는지 확인
|
||||
- 검증:
|
||||
- 로그인 화면 표시 확인
|
||||
- 빈 전화번호 validation 확인
|
||||
- 사용자 전화번호 입력 영역 및 로그인 요청 버튼 확인
|
||||
- 로그인 성공 후 `직원검색`, `검색 결과`, 직원 목록 표시 확인
|
||||
- 제한 사항:
|
||||
- local runtime에서는 실제 승인 링크 완료까지 이어지는 E2E 성공을 아직 확인하지 못함
|
||||
- 후속 조치:
|
||||
- 인증 대기 문구, 재시도, 세션 복원, 인증 만료 후 재로그인 흐름 추가 점검
|
||||
|
||||
## 2026-07-06 10:05 KST - staging API base 후보 점검
|
||||
|
||||
- 결과: [실패]
|
||||
- 목적: staging Baron SSO 검증을 위해 제공된 `https://sso.hmac.kr`가 `tdc114plus` staging API base로 직접 사용 가능한지 확인
|
||||
- 명령:
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.staging.local ./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- `GET /api/v1/tdc114plus/directory/employees`에서 HTTP 404
|
||||
- 응답 본문: `{"error":"Cannot GET /api/v1/tdc114plus/directory/employees","code":"not_found"}`
|
||||
- 해석: `https://sso.hmac.kr`는 Baron SSO 진입 주소일 수는 있으나, 현재 확인 기준으로 `tdc114plus` API route가 직접 노출된 staging base는 아님
|
||||
- 후속 조치:
|
||||
- 정확한 staging `TDC114_API_BASE`와 신규 API 배포 여부 확인 필요
|
||||
|
||||
## 2026-07-06 10:30 KST - staging 반영 전 단계 분류 및 문서 반영
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: 팀장 보고 전 단계로, staging 배포 전에 로컬/에뮬레이터/문서 기준으로 무엇을 먼저 끝내야 하는지 순서화
|
||||
- 주요 작업:
|
||||
- 작업 기준 문서에 `Phase 4-2-a ~ 4-2-g` 하위 단계 추가
|
||||
- 각 단계별 실행 체크포인트 추가
|
||||
- staging 검증 시나리오 문서에 배포 전 수동 점검 체크리스트와 직전 확인 항목 추가
|
||||
- 후속 조치:
|
||||
- 수동 점검 체크리스트 문서화 및 실제 체크 결과 누적
|
||||
|
||||
## 2026-07-06 11:20 KST - 로그인 완료 가정 Android emulator 기능점검 재시도
|
||||
|
||||
- 결과: [실패]
|
||||
- 목적: local 승인 완료 E2E 대신, 로그인 완료를 가정한 post-login 기능을 Android emulator에서 integration test로 점검
|
||||
- 명령:
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/integration_tests.sh`
|
||||
- 주요 출력:
|
||||
- local `phone-login` bootstrap은 `401 login_failed`
|
||||
- 스크립트는 이에 대응해 mock directory fallback 모드로 전환
|
||||
- 이후 Docker local ADB 연결에서 `172.21.128.1:5555 offline`
|
||||
- Flutter runner는 Android target을 잡지 못해 `No supported devices connected.`로 종료
|
||||
- 해석:
|
||||
- post-login mock fallback 로직 자체는 준비되었으나, 이번 실패 원인은 앱 기능이 아니라 현재 emulator/ADB 연결 상태다.
|
||||
- 후속 조치:
|
||||
- Windows emulator 실행 상태와 `5555` 연결 상태를 다시 확인한 뒤 integration test 재실행
|
||||
- `cp scripts/smoke.env.example /tmp/tdc114plus-smoke.env`
|
||||
- `TDC114_SMOKE_ENV_FILE=/tmp/tdc114plus-smoke.env ./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- shell 문법 검사 통과
|
||||
- 임시 smoke env 파일 자동 로드 확인
|
||||
- 최소 guard smoke는 통과
|
||||
- 예시 전화번호 기준 `phone-login success` 단계는 HTTP 401 `login_failed`
|
||||
- 후속 조치:
|
||||
- `scripts/.env.smoke.local`에 실제 민감정보 없는 `TDC114_SMOKE_PHONE` 테스트 계정을 넣고 authenticated smoke 재실행
|
||||
|
||||
## 2026-07-02 16:03 KST - Phase 4 runtime 및 최소 API smoke 재검증
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: Baron SSO local runtime 준비 상태와 tdc114plus 최소 API guard smoke 유지 여부 확인
|
||||
|
||||
## 2026-07-02 16:03 KST - Phase 4/5 Flutter quality gate 재검증
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: 현재 Flutter 변경분의 format, analyze, widget/unit test 회귀 상태 확인
|
||||
|
||||
## 2026-07-02 16:08 KST - Phase 4 authenticated API smoke 재시도
|
||||
|
||||
- 결과: [실패 후 통과]
|
||||
- 목적: `scripts/.env.smoke.local`의 실제 등록 전화번호로 tdc114plus phone-login, 직원목록, 조직도 authenticated smoke 확인
|
||||
- 명령:
|
||||
- `./scripts/api-smoke.sh`
|
||||
- `./scripts/check-baron-api-env.sh`
|
||||
- `docker ps -a --format '{{.Names}} {{.Status}}'`
|
||||
- `docker logs --tail 120 baron_backend`
|
||||
- `docker exec baron_backend sh -lc 'cd /app && GOCACHE=/tmp/baron-sso-go-cache /usr/local/go/bin/go test ./internal/handler -run TestTdc114Plus -count=1'`
|
||||
- `docker compose up -d --build backend`
|
||||
- 주요 출력:
|
||||
- unauthorized directory guard HTTP 401 통과
|
||||
- invalid phone-login validation HTTP 400 통과
|
||||
- 1차 phone-login success 단계에서 HTTP 503 `identity_provider_unavailable`
|
||||
- backend 로그: `[Tdc114Plus] phone login session issue failed`, `IssueSession(loginID)` 경로에서 Ory provider가 `405 Method Not Allowed` 반환
|
||||
- 조치: `tdc114plus` phone-login session 발급을 기존 Baron SSO phone-login/headless 흐름과 같은 `InitiateLinkLogin` + Redis session polling 방식으로 전환
|
||||
- 2차 backend 로그: Kratos `return_to`가 `http://127.0.0.1`로 계산되어 `self_service_flow_return_to_forbidden`
|
||||
- 조치: `tdc114plus` code-flow 초기화는 request host보다 configured `USERFRONT_URL`을 우선 사용하도록 보정
|
||||
- Docker runtime 점검은 0 failure, 0 warning이며 `baron_backend`, `baron_gateway`, Ory 핵심 컨테이너는 실행 중
|
||||
- focused backend test 통과: `ok baron-sso-backend/internal/handler`
|
||||
- 최종 `api-smoke.sh`: phone-login HTTP 200, employee list HTTP 200, tenant list HTTP 200, orgchart HTTP 200
|
||||
- 실제 응답 shape/count 점검 중 directory에 tenant 없는 active 계정이 포함되는 불일치 발견
|
||||
- 조치: `tdc114plus` directory 대상 사용자를 조직도 표시 상태와 primary tenant 보유 기준으로 제한
|
||||
- 최종 count 재확인: directory employees 1, total 1, with_tenant 1, orgchart employees 1
|
||||
|
||||
## 2026-07-03 08:11 KST - Android integration 준비 시나리오 1차 진행
|
||||
|
||||
- 결과: [실패]
|
||||
- 목적: Android emulator/device 통합테스트 실행을 위한 runtime, API smoke, device 인식 상태 확인
|
||||
- 명령:
|
||||
- `./scripts/check-baron-api-env.sh`
|
||||
- `docker compose up -d backend`
|
||||
- `docker start ory_postgres ory_clickhouse ory_kratos ory_hydra ory_keto ory_oathkeeper ory_vector baron_userfront`
|
||||
- `./scripts/api-smoke.sh`
|
||||
- `./scripts/flutter-docker.sh devices`
|
||||
- `which adb`
|
||||
- `adb devices`
|
||||
- `./scripts/integration_tests.sh`
|
||||
- 주요 출력:
|
||||
- 최초 runtime 점검에서 `baron_backend` 미실행 확인 후 backend 시작
|
||||
- 최초 API smoke는 Ory/Kratos/Hydra/Keto 컨테이너 중지로 phone-login HTTP 503
|
||||
- Ory/UserFront 컨테이너 시작 후 API smoke 통과: phone-login, employee list, tenant list, orgchart HTTP 200
|
||||
- Docker Flutter devices는 `Linux desktop`만 표시
|
||||
- WSL에는 `adb`가 없어 `adb devices` 실행 불가
|
||||
- integration test는 앱에 Linux runner가 없고 Android/iOS device가 없어 `No supported devices connected.`
|
||||
- 후속 조치:
|
||||
- Windows Android Studio emulator 또는 Android 실기기를 준비하고, WSL/Docker에서 ADB/device 접근이 가능하도록 구성한 뒤 재실행
|
||||
|
||||
## 2026-07-03 10:22 KST - Android emulator integration test 2차 진행
|
||||
|
||||
- 결과: [실패]
|
||||
- 목적: Windows Android Studio emulator를 WSL/Docker Flutter CLI에서 인식시킨 뒤 `app/integration_test/app_smoke_test.dart` 실행
|
||||
- 명령:
|
||||
- `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices`
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/integration_tests.sh`
|
||||
- `nc -vz 172.21.128.1 5555`
|
||||
- 주요 출력:
|
||||
- Docker Flutter devices에서 Android emulator 인식 성공: `emulator-5554`, Android 15 API 35
|
||||
- `scripts/integration_tests.sh`를 실시간 출력 방식으로 개선해 Gradle 진행 상황 확인 가능
|
||||
- 첫 Android 빌드 중 Docker Flutter image 내부에 NDK 28.2.13676358, CMake 3.22.1 자동 설치
|
||||
- APK 빌드 성공: `Built build/app/outputs/flutter-apk/app-debug.apk`
|
||||
- APK 설치 성공
|
||||
- test loading 단계에서 실패: `WebSocketChannelException: SocketException: Connection refused`, address `127.0.0.1`, dynamic VM service port
|
||||
- 판단:
|
||||
- 앱/API 로그인 실패가 아니라 remote Windows ADB server와 Docker Flutter CLI 조합에서 VM service port forward가 컨테이너의 `127.0.0.1`로 연결되지 않는 구조적 문제
|
||||
- Windows ADB server는 emulator를 볼 수 있고 Docker도 ADB server에는 접근 가능하지만, Flutter test runner가 연결해야 하는 forwarded VM service port는 Docker container localhost가 아니라 Windows host localhost 쪽에 생성되는 것으로 판단
|
||||
- WSL에서 Windows emulator adbd port `172.21.128.1:5555`는 현재 `Connection refused`
|
||||
- 후속 조치:
|
||||
- Windows 관리자 PowerShell에서 emulator adbd port `5555`도 `portproxy`로 노출 검토
|
||||
- Docker container 내부 ADB server가 `172.21.128.1:5555`에 직접 `adb connect`한 뒤 integration test를 실행하는 방식 검증
|
||||
- 또는 Windows host에서 Flutter CLI를 직접 실행하는 경로를 대안으로 검토
|
||||
|
||||
## 2026-07-03 11:06 KST - Android emulator integration test 3차 진행
|
||||
|
||||
- 결과: [실패 후 통과]
|
||||
- 목적: Windows emulator adbd `5555` portproxy와 Docker local ADB server 방식으로 Flutter integration test 최종 검증
|
||||
- 명령:
|
||||
- `nc -vz 172.21.128.1 5555`
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/flutter-docker.sh devices`
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/integration_tests.sh`
|
||||
- `./scripts/api-smoke.sh`
|
||||
- 주요 출력:
|
||||
- `172.21.128.1:5555` 연결 성공
|
||||
- 1차 Docker local ADB 연결은 `unauthorized`로 표시
|
||||
- Windows 사용자 ADB key(`/mnt/c/Users/user/.android/adbkey`)를 git ignored `.android-adb/`에 복사해 Docker `/root/.android`로 마운트
|
||||
- 이후 Docker local ADB 연결 성공: `172.21.128.1:5555 device`
|
||||
- 최초 integration test 재실행은 앱 테스트 2건 통과 후 real API login test 실패
|
||||
- 원인 확인 중 host API smoke가 `502 Bad Gateway`로 실패했고 `baron_backend` 및 Ory 계열 컨테이너가 내려가 있었음
|
||||
- Ory/UserFront 컨테이너와 `baron_backend` 재시작 후 `api-smoke.sh` 통과: phone-login, employee list, tenant list, orgchart HTTP 200
|
||||
- 최종 integration test 통과: `+3: All tests passed!`
|
||||
- 후속 조치:
|
||||
- `ghcr.io/cirruslabs/flutter:stable` 컨테이너가 매번 새로 뜨며 NDK/CMake를 반복 설치해 Android integration test 시간이 길어짐
|
||||
- 반복 실행 시간을 줄이려면 Android SDK/Gradle cache volume을 `scripts/flutter-docker.sh`에 추가 검토
|
||||
|
||||
## 2026-07-06 15:15 KST - local 로그인 가능 사용자 확보 및 emulator post-login 점검 재시도
|
||||
|
||||
- 결과: [부분 성공]
|
||||
- 목적: local Baron SSO runtime에서 테스트 번호를 실제 로그인 가능한 사용자로 맞춘 뒤 host smoke와 Android emulator post-login 기능점검을 재검증
|
||||
- 명령:
|
||||
- `./scripts/api-smoke.sh`
|
||||
- `/bin/bash -lc 'TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/integration_tests.sh'`
|
||||
- `/bin/bash -lc 'ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices'`
|
||||
- `/bin/bash -lc 'TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/flutter-docker.sh devices'`
|
||||
- 주요 작업:
|
||||
- local Kratos에 테스트 번호 `010-9136-5338`용 identity 생성
|
||||
- 동일 identity ID로 local Baron `users` row 동기화
|
||||
- `tdc114plus` `link/init`이 `pendingRef`를 반환하는 것과 `link/poll` 첫 응답이 `authorization_pending`인 것을 직접 확인
|
||||
- 주요 출력:
|
||||
- host `api-smoke.sh` 재통과: `phone-login`, 직원목록, 가족사목록, 조직도 HTTP 200
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555` 경로: `failed to connect`, `172.21.128.1:5555 offline`
|
||||
- 해당 상태로 `integration_tests.sh`는 Android device를 잡지 못하고 `No supported devices connected.` 종료
|
||||
- `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037` 경로: `adb: failed to check server version: protocol fault (couldn't read status)`
|
||||
- 판단:
|
||||
- local 앱/API 쪽 blocker였던 "로그인 가능한 사용자 없음" 문제는 해소됨
|
||||
- 현재 blocker는 Android emulator/Windows ADB/portproxy 계층이며, 앱 코드 변경 없이 Windows 측 emulator 재기동 또는 portproxy 복구가 우선
|
||||
- 다음 조치:
|
||||
- Windows `adb devices`가 `device`인지 재확인
|
||||
- Windows `5037`, `5555` portproxy 상태 재확인
|
||||
- emulator가 `device` 상태로 돌아오면 동일 명령으로 `5-B` post-login 기능점검 재실행
|
||||
|
||||
## 2026-07-06 16:20 KST - emulator post-login 기능점검 최종 통과
|
||||
|
||||
- 결과: [성공]
|
||||
- 목적: Windows emulator 복구 후 Android emulator에서 post-login 상태 기능점검과 integration smoke를 최종 통과
|
||||
- 명령:
|
||||
- `/bin/bash -lc 'TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5557 ./scripts/flutter-docker.sh devices'`
|
||||
- `/bin/bash -lc 'TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5557 ./scripts/integration_tests.sh'`
|
||||
- 주요 작업:
|
||||
- Windows `adb devices`에서 `emulator-5556 device` 확인
|
||||
- 관리자 PowerShell에서 `0.0.0.0:5557 -> 127.0.0.1:5557` portproxy 추가
|
||||
- smoke override 타입 처리와 integration test 시나리오를 `assume logged in` 모드와 충돌하지 않도록 정리
|
||||
- 주요 출력:
|
||||
- Docker Flutter devices: `172.21.128.1:5557 device`
|
||||
- Android APK 빌드/설치 성공
|
||||
- 최종 integration test 결과: `+4: All tests passed!`
|
||||
- 확인 범위:
|
||||
- 로그인 화면 smoke
|
||||
- 빈 전화번호 validation smoke
|
||||
- post-login 상태 기준 직원검색 진입
|
||||
- 즐겨찾기/직원 상세/전화/문자 버튼 노출 smoke
|
||||
|
||||
## 2026-07-07 00:00 KST - Phase 6 실제 API smoke 완료, Android integration runtime 기준 재정렬
|
||||
|
||||
- 결과: [부분 통과]
|
||||
- 목적: 실제 API smoke 완료 후 Android emulator bridge 기준 포트와 integration 실행 흐름을 최신 정책 기준으로 재정렬
|
||||
- 명령:
|
||||
- `./scripts/api-smoke.sh`
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5559 ./scripts/check-android-emulator-env.sh`
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5559 ./scripts/integration_tests.sh`
|
||||
- 주요 출력:
|
||||
- `api-smoke.sh`: unauthorized guard, validation, phone-login, employee list, tenant list, orgchart까지 통과
|
||||
- `check-android-emulator-env.sh`: `172.21.128.1:5559 offline`
|
||||
- `integration_tests.sh`: Android preflight를 먼저 수행하도록 보강했고, 현재는 Flutter 실행 전에 `offline` 상태에서 중단
|
||||
- 현재 blocker는 앱/API 코드가 아니라 Windows emulator 또는 ADB/portproxy 상태다
|
||||
- 후속 조치:
|
||||
- Windows Android Studio에서 emulator 1대만 실행
|
||||
- Windows `adb.exe devices`에서 `device` 상태 확인
|
||||
- `5559 -> 127.0.0.1:5559` portproxy 및 방화벽 rule 확인 후 integration 재실행
|
||||
|
||||
## 2026-07-07 00:20 KST - Phase 6 Android emulator integration smoke 재통과
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: 활성 emulator `emulator-5560 device` 기준 bridge `172.21.128.1:5561`로 Android integration runner를 `flutter drive` 방식으로 재정렬한 뒤 실제 smoke를 재검증
|
||||
- 명령:
|
||||
- `TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5561 ./scripts/check-android-emulator-env.sh`
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5561 ./scripts/integration_tests.sh`
|
||||
- 주요 출력:
|
||||
- preflight 통과: `172.21.128.1:5561 device`
|
||||
- `scripts/integration_tests.sh`를 `flutter drive --driver=test_driver/integration_driver.dart --target=integration_test/app_smoke_test.dart` 기준으로 전환
|
||||
- Android APK 빌드/설치 성공
|
||||
- VM service 연결 성공 후 `All tests passed!`
|
||||
- 확인 범위:
|
||||
- 로그인 화면 smoke
|
||||
- 빈 전화번호 validation smoke
|
||||
- post-login 상태 기준 직원검색/상세/즐겨찾기 액션 smoke
|
||||
|
||||
## 2026-07-07 02:55 KST - 직원검색 상단 칩/조직 drill-down 정책 반영 검증
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: 직원검색 화면에서 `본인팀 칩 고정 노출`, `다른 회사 선택 후에도 본인팀 칩 유지`, `전체 > 회사 > 부서 > 개인` drill-down 규칙을 정책대로 반영했는지 검증
|
||||
- 명령:
|
||||
- `./scripts/format-dart.sh`
|
||||
- `../scripts/flutter-docker.sh test test/widget_test.dart test/directory/directory_filters_test.dart`
|
||||
- 주요 출력:
|
||||
- `DirectoryQuery`에 `department` scope를 추가해 회사/부서 drill-down 조회를 분리
|
||||
- 세션 `department`와 tenant 이름을 매칭해 본인팀 고정 칩 slug를 계산하도록 변경
|
||||
- widget test 추가:
|
||||
- 초기 화면에서 본인팀 칩 노출
|
||||
- 다른 회사 선택 후에도 본인팀 칩 유지
|
||||
- `전체 > 한맥 > 기술연구소 > 직원목록` drill-down
|
||||
- 최종 결과: `All tests passed!`
|
||||
|
||||
## 2026-07-07 03:10 KST - manual-postlogin-run 경로 복구 및 emulator 실행 확인
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: Android emulator 수동 점검 기본 경로인 `manual-postlogin-run.sh`가 실제 `flutter run` 설치/실행까지 이어지는지 확인
|
||||
- 명령:
|
||||
- `./scripts/check-baron-api-env.sh`
|
||||
- `./scripts/api-smoke.sh`
|
||||
- `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5561 ./scripts/manual-postlogin-run.sh`
|
||||
- 주요 출력:
|
||||
- Baron runtime ready-ish, API smoke 전체 통과
|
||||
- `scripts/flutter-docker.sh`의 첫 인자 중복 전달 문제를 수정
|
||||
- `manual-postlogin-run.sh`를 `flutter-docker.sh run ...` 조합으로 정렬
|
||||
- Android APK 빌드 성공, emulator `172.21.128.1:5561 device`에 설치 성공
|
||||
- `Launching lib/main.dart on sdk gphone64 x86 64 in debug mode...` 이후 VM service 연결과 앱 실행 확인
|
||||
|
||||
## 2026-07-07 04:20 KST - leaf 조직 0건 표시 수정 및 칩 영역 구분선 반영
|
||||
|
||||
- 결과: [통과]
|
||||
- 목적: 실제 화면에서 leaf 조직 칩 선택 시 `검색 결과 0명`이 나오던 원인을 수정하고, 상단 칩 영역과 하위 경로 칩 영역 사이 구분선을 추가
|
||||
- 주요 작업:
|
||||
- leaf 조직 선택 시 직원 조회를 `회사 tenantSlug + department` 조합이 아니라 `선택 tenantSlug` 기준으로 변경
|
||||
- mock/fake/smoke repository도 같은 기준으로 정렬
|
||||
- 상단 회사/고정팀 칩 영역과 breadcrumb 칩 영역 사이에 `Divider` 추가
|
||||
- 검증:
|
||||
- `../scripts/flutter-docker.sh test test/widget_test.dart test/directory/directory_filters_test.dart`
|
||||
- 결과: `All tests passed!`
|
||||
|
||||
## 2026-07-08 16:55 KST - 독립형 실기기 전환용 split API base 지원 및 production host 검증
|
||||
|
||||
- 결과: [부분 통과]
|
||||
- 목적: USB 없는 독립형 실기기 테스트를 위해 `로그인은 staging`, `직원/조직 데이터는 production` 조합까지 수용할 수 있도록 앱과 실행 스크립트의 API base 주입 구조를 분리하고, 현재 알려진 production host가 실제 신규앱 route를 제공하는지 확인
|
||||
- 주요 작업:
|
||||
- `AppEnvironment`에 `TDC114_AUTH_API_BASE`, `TDC114_DIRECTORY_API_BASE`, `TDC114_ORGANIZATION_API_BASE` override 추가
|
||||
- auth/directory/organization provider가 각자 분리된 base URL을 사용하도록 변경
|
||||
- `manual-postlogin-run.sh`, `integration_tests.sh`가 위 override를 `--dart-define`으로 전달하도록 보강
|
||||
- staging/production 실기기 env example과 Android 설치 정책 문서에 split-base 규칙 추가
|
||||
- 검증:
|
||||
- `../scripts/flutter-docker.sh test test/widget_test.dart test/auth test/directory test/organization`
|
||||
- 결과: `All tests passed!`
|
||||
- `TDC114_SMOKE_ENV_FILE=/tmp/tdc114plus-noenv TDC114_API_BASE=https://admin.brsw.kr TDC114_SKIP_AUTH_SMOKE=true ./scripts/api-smoke.sh`
|
||||
- 결과: `GET /api/v1/tdc114plus/directory/employees` 기준 HTTP 404 `not_found`
|
||||
- 해석:
|
||||
- `https://admin.brsw.kr`는 Baron org-context 참고 host로는 사용 가능하지만, 현재 확인 기준 `tdc114plus` 신규앱 public API base는 아니다
|
||||
- 따라서 USB 없는 독립형 실기기 최종 검증의 외부 blocker는 `신규앱 public TDC114_API_BASE` 확정이다
|
||||
|
||||
## 2026-07-08 18:40 KST - 전용 tdc114plus API 전제 철회 및 Swagger 직접 소비 기준으로 재정렬
|
||||
|
||||
- 결과: [기준 수정]
|
||||
- 목적: 사용자 확인 사항인 `tdc114plus 앱 전용 API는 없다`를 정책 문서에 반영하고, 앱이 Baron Swagger 공개 API를 직접 소비하는 방향으로 기준을 수정
|
||||
- 확인 사실:
|
||||
- `https://admin.brsw.kr`는 org-context 참고 host로는 사용 가능하지만 `GET /api/v1/tdc114plus/directory/employees` 기준 HTTP 404
|
||||
- `https://sorg.hmac.kr/login?returnTo=%2Fchart`는 HTML 로그인 화면이며 JSON API endpoint가 아님
|
||||
- Swagger 캡쳐상 `Public /api/v1/public/orgchart` 같은 조직도 관련 공개 API 흔적은 존재
|
||||
- 사용자 확인 기준: `tdc114plus 앱 전용 API는 없고, 저 사이트가 주는 API를 사용해서 앱 내용을 구성`
|
||||
- 조치:
|
||||
- `00_guide_tdc114plus_external_api_usage`, `00_contract_tdc114plus_api`, 타임테이블 문서를 전용 API 전제 철회 기준으로 개정
|
||||
- 현재 코드의 `/api/v1/tdc114plus/...` 경로는 확정 계약이 아니라 재매핑 대상이라고 명시
|
||||
- 다음 단계:
|
||||
- Swagger 공개 path 기준으로 직원검색/조직도/로그인 대응 endpoint를 다시 표준화
|
||||
- 코드 변경은 실제 공개 path가 확정되기 전까지 보류
|
||||
|
||||
## 2026-07-08 19:10 KST - org-context 응답을 현재 앱 화면/모델 기준으로 매핑 판단
|
||||
|
||||
- 결과: [진행]
|
||||
- 목적: `GET /api/v1/integrations/org-context` 설명과 예시 응답을 기준으로, 현재 앱 화면 정책과 데이터 모델에 얼마나 직접 매핑 가능한지 판단
|
||||
- 확인 사실:
|
||||
- `tenantSlug` 기준 subtree 조회가 가능하다
|
||||
- `tree`, `tenants[]`, `tenant.members[]` 구조가 존재한다
|
||||
- `includeUsers=true`면 조직별 직접 소속 사용자 목록이 들어온다
|
||||
- `includeUserIds=true`일 때만 `members[].id`, `members[].phone`가 포함된다
|
||||
- 판단:
|
||||
- 조직도/가족사/하위조직 drilldown 구조에는 매우 잘 맞는다
|
||||
- 현재 `Employee.tenantId`, `tenantName`, `tenantSlug`는 상위 tenant 정보를 member에 주입하는 flatten 가공이 필요하다
|
||||
- `totalMemberCount`, `profileImageUrl` 같은 필드는 직접 제공되지 않는다
|
||||
- 데이터 구조 기준 API로는 유력하지만, 운영 Key 필요 API이므로 모바일 앱 직접 호출 방식은 보안 검토 전까지 확정하지 않는다
|
||||
- 산출물:
|
||||
- `docs/00_guide_tdc114plus_org_context_mapping_2026-07-08.md`
|
||||
|
||||
## 2026-07-08 19:35 KST - headless 계약 + Baron 기존 API 활용 기준 재정렬 고정
|
||||
|
||||
- 결과: [기준 수정]
|
||||
- 목적: 사용자 지시에 따라 `바론SSO 문서 정책`과 `현재 일부 구현 흔적` 불일치를 정식 정책으로 고정하고, 옛 `tdc114plus` 전용 API 가정은 기능 보존 테스트를 동반해 단계적으로 제거하는 원칙을 반영
|
||||
- 조치:
|
||||
- `docs/00_policy_tdc114plus_decoupled_api_migration_2026-07-07.md`
|
||||
- `docs/00_guide_tdc114plus_work_progress_timetable_2026-07-02.md`
|
||||
- `docs/00_guide_tdc114plus_external_api_usage_2026-07-03.md`
|
||||
- `docs/00_contract_tdc114plus_api_2026-07-02.md`
|
||||
- 반영 내용:
|
||||
- 신규 앱 기준을 `headless 로그인 계약 + Baron 기존 Swagger API 활용`으로 명시
|
||||
- `/api/v1/tdc114plus/...` 경로 가정을 레거시 흔적으로 분류
|
||||
- 레거시 제거 순서를 `실제 사용처 확인 -> 대체 path/DTO 반영 -> mock/real 테스트 통과 -> 실제 화면 확인 -> 제거`로 고정
|
||||
- 타임테이블에 `레거시 전용 API 흔적 단계적 제거` 단계를 추가
|
||||
- 다음 단계:
|
||||
- 현재 코드의 레거시 path를 `유지`, `교체`, `제거`로 분류
|
||||
- `교체` 대상부터 Swagger endpoint 재매핑과 기능 보존 테스트를 병행
|
||||
## 2026-07-09 TDC114PLUS PKCE/App Link 검증
|
||||
|
||||
- RP Client ID: `39d6190d-72f6-4a58-a84f-cdc5ece3e8af`
|
||||
- Redirect URI: `https://114.hmac.kr/auth/callback`
|
||||
- `assetlinks.json` 외부 HTTPS 200 및 `application/json` 응답 확인
|
||||
- debug APK 공기계 설치 성공
|
||||
- callback URL이 `kr.co.baron.tdc114plus/.MainActivity`를 직접 실행하고 test code를 수신하는 것 확인
|
||||
- PKCE S256 verifier/challenge/state 생성 계층 구현
|
||||
- Client Secret 없는 authorization code token 요청 계층 구현
|
||||
- PKCE 신규 테스트 및 기존 auth 회귀 테스트: 13건 통과
|
||||
- Flutter analyze: `No issues found`
|
||||
- 확인된 blocker:
|
||||
- 등록 RP는 PKCE 공개 클라이언트이며 Client Secret/개인키가 없음
|
||||
- Swagger headless API는 `private_key_jwt client_assertion`을 필수 요구
|
||||
- 모바일 공개 RP용 assertion 발급 또는 면제 계약 확인 전 실제 headless 호출 연결 보류
|
||||
|
||||
@@ -32,16 +32,35 @@ YYYY-MM-test-execution-log.md
|
||||
|
||||
각 실행 결과는 년월일시까지 남긴다.
|
||||
|
||||
권장 형식:
|
||||
기본 원칙:
|
||||
|
||||
- 결과가 `[통과]`인 경우에는 `목적`과 `결과`만 컴팩트하게 기록한다.
|
||||
- 테스트 진행 중 실패가 발생한 경우에만 `목적`, `명령`, `주요 출력`, `후속 조치`를 기록한다.
|
||||
- 반복된 Docker dependency download 출력이나 전체 로그를 붙이지 않는다.
|
||||
- 실패 없이 통과한 항목에는 명령 목록, 주요 출력, 후속 조치를 길게 남기지 않는다.
|
||||
|
||||
통과 시 권장 형식:
|
||||
|
||||
```markdown
|
||||
## YYYY-MM-DD HH:mm KST - 작업명
|
||||
|
||||
- 목적:
|
||||
- 실행 명령:
|
||||
- 결과:
|
||||
- 결과: [통과]
|
||||
- 목적: 무엇을 확인했는지 1문장
|
||||
```
|
||||
|
||||
실패 후 수정하여 통과한 경우 권장 형식:
|
||||
|
||||
```markdown
|
||||
## YYYY-MM-DD HH:mm KST - 작업명
|
||||
|
||||
- 결과: [실패 후 통과]
|
||||
- 목적: 무엇을 확인했는지 1문장
|
||||
- 명령:
|
||||
- `실패 또는 재검증에 사용한 핵심 명령`
|
||||
- 주요 출력:
|
||||
- 실패 원인, 수정 내용, 최종 통과 결과
|
||||
- 후속 조치:
|
||||
- 필요한 경우만 작성
|
||||
```
|
||||
|
||||
## 4. 기록 대상
|
||||
@@ -63,6 +82,7 @@ YYYY-MM-test-execution-log.md
|
||||
|
||||
- 성공 결과뿐 아니라 실패 결과도 남긴다.
|
||||
- 실패 로그는 원인, 재현 명령, 후속 조치를 함께 적는다.
|
||||
- 성공 로그는 `목적`과 `[통과]` 결과만 남긴다.
|
||||
- 비슷한 성격의 테스트는 같은 월별 로그 파일에 계속 누적한다.
|
||||
- 월이 바뀌면 새 월별 로그 파일을 만든다.
|
||||
- 테스트 정책 변경이 있으면 `docs/tdc114plus-testing-policy-2026-07-02.md`와 함께 갱신한다.
|
||||
- 테스트 정책 변경이 있으면 `docs/00_policy_tdc114plus_testing_2026-07-02.md`와 함께 갱신한다.
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# Android Studio / WSL ADB 연동 트러블슈팅 타임테이블
|
||||
|
||||
작성일: 2026-07-03
|
||||
대상 작업: Windows Android Studio emulator 준비, Windows ADB 확인, WSL/Docker Flutter CLI 연동
|
||||
관련 시나리오: `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`
|
||||
|
||||
## 1. 요약
|
||||
|
||||
2026-07-03 오전에는 `tdc114plus` Flutter integration test 실행을 위해 Windows Android Studio에서 Android emulator를 만들고, WSL 및 Docker 기반 Flutter CLI에서 해당 emulator를 인식하도록 연결했다.
|
||||
|
||||
최종적으로 아래 상태까지 확인했다.
|
||||
|
||||
- Windows PowerShell `adb devices`: `emulator-5554 device` 확인
|
||||
- Windows `netsh interface portproxy`: `0.0.0.0:5037 -> 127.0.0.1:5037` 설정
|
||||
- WSL에서 Windows host `172.21.128.1:5037` 연결 성공
|
||||
- Flutter Docker 컨테이너 내부 `adb devices`: `emulator-5554 device` 확인
|
||||
- `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices`: Android emulator 표시 확인
|
||||
|
||||
통합테스트 실행은 아직 최종 성공/실패 판정 전이다. 기존 `scripts/integration_tests.sh`가 출력을 임시 파일에 모았다가 종료 후 출력하는 구조라, Android 첫 빌드 중 진행 상태 확인이 어려웠다. 다음 단계에서는 실시간 출력이 가능하도록 스크립트를 보강한 뒤 재실행한다.
|
||||
|
||||
## 2. 기대 시간과 실제 소요 시간
|
||||
|
||||
| 구간 | 설치/연동 전 기대 시간 | 실제 소요 시간 | 판정 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| Android Studio 설치 및 Setup Wizard | 15-25분 | 약 25-35분 추정 | 대체로 정상 범위 |
|
||||
| AVD 생성 및 system image 다운로드 | 10-20분 | 약 15-25분 추정 | 정상 범위 |
|
||||
| Windows `adb devices` 확인 | 5분 | 약 5-10분 | 정상 범위 |
|
||||
| WSL/Docker에서 Windows ADB 접근 구성 | 10-15분 | 최소 49분 이상 | 지연 발생 |
|
||||
| Flutter Docker에서 emulator 인식 확인 | 5-10분 | 약 10분 | 정상 범위 |
|
||||
| 전체 Android Studio 설치부터 Docker device 인식까지 | 30-45분 | 약 50-70분 추정 | 지연 발생 |
|
||||
|
||||
실제 소요 시간 중 명령 로그로 확인 가능한 핵심 구간은 아래와 같다.
|
||||
|
||||
- 08:45 KST: `adb -a -P 5037 nodaemon server` 첫 실패 확인
|
||||
- 08:54 KST: `adb -a -P 5037 nodaemon server` 재시도 실패 확인
|
||||
- 09:00 ~ 09:30 KST: 업무회의참여
|
||||
- 09:34 KST: emulator용 local env 파일 생성
|
||||
- 09:34 KST 이후: `flutter-docker.sh devices`에서 Android emulator 인식 확인
|
||||
|
||||
따라서 Windows ADB를 WSL/Docker에서 접근 가능하게 만드는 구간만 최소 49분 이상 소요되었다.
|
||||
|
||||
## 3. 타임테이블
|
||||
|
||||
| 시간(KST) | 단계 | 수행 내용 | 결과 |
|
||||
| --- | --- | --- | --- |
|
||||
| 오전 초반 | Android Studio 설치 시작 | Android Studio 공식 다운로드 페이지에서 Windows용 Android Studio 설치 | 설치 진행 |
|
||||
| 오전 초반 | Setup Wizard | usage statistics는 전송하지 않는 방향으로 선택, Standard 설치, SDK license 수락 | Android Studio 초기 설정 완료 |
|
||||
| 오전 중반 | Device Manager 진입 | Android Studio Welcome 화면에서 Device Manager 열기 | 가상 기기 목록 화면 진입 |
|
||||
| 오전 중반 | AVD 생성 | Medium Phone 선택, Android 15 API 35, Google Play Intel x86_64 system image 선택 | `Medium Phone` AVD 생성 |
|
||||
| 오전 중반 | Emulator 실행 | Device Manager에서 `Medium Phone` 실행 | Windows ADB에서 emulator 확인 가능 상태 |
|
||||
| 오전 중반 | Windows ADB 경로 확인 | PowerShell에서 기본 `adb devices` 실행 | `adb`가 PATH에 없어 실패 |
|
||||
| 오전 중반 | Windows ADB 직접 실행 | `& "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" devices` | `emulator-5554 device` 확인 |
|
||||
| 08:45 | ADB 외부 바인딩 1차 시도 | `adb -a -P 5037 nodaemon server` | `10048`, `0.0.0.0:5037` bind 실패 |
|
||||
| 08:45-08:54 | 포트 점유 원인 확인 | `Get-Process adb`, `netstat -ano`, `taskkill`, `Get-CimInstance` 반복 | Android Studio/ADB client가 일반 ADB server를 계속 재기동하는 패턴 확인 |
|
||||
| 08:54 | ADB 외부 바인딩 재시도 | 기존 ADB 종료 후 `adb -a -P 5037 nodaemon server` 재실행 | 동일하게 `10048` 실패 |
|
||||
| 08:54 이후 | 2순위 방식 전환 | `adb -a` 대신 Windows `portproxy` 방식으로 전환 결정 | 우회 경로 확정 |
|
||||
| 오전 후반 | 관리자 PowerShell 실행 | 관리자 권한 PowerShell에서 `netsh interface portproxy` 설정 | `0.0.0.0:5037 -> 127.0.0.1:5037` 등록 |
|
||||
| 오전 후반 | 방화벽 허용 | `netsh advfirewall firewall add rule name="ADB 5037 for WSL"` | 방화벽 rule 추가 완료 |
|
||||
| 오전 후반 | WSL 연결 확인 | WSL에서 Windows host `172.21.128.1:5037` TCP 연결 확인 | 연결 성공 |
|
||||
| 오전 후반 | Docker 내부 ADB 확인 | `ghcr.io/cirruslabs/flutter:stable` 컨테이너에서 `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 adb devices` | `emulator-5554 device` 확인 |
|
||||
| 오전 후반 | 스크립트 보강 | `scripts/flutter-docker.sh`가 `ADB_SERVER_SOCKET`을 Docker 컨테이너에 전달하도록 수정 | 프로젝트 스크립트에서도 emulator 인식 가능 |
|
||||
| 오전 후반 | Flutter device 확인 | `ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices` | Android emulator와 Linux desktop 표시 |
|
||||
| 09:34 | Emulator env 준비 | `scripts/.env.android-emulator.local` 생성, API base를 `http://10.0.2.2:5000`으로 설정 | 민감정보 없는 방식으로 local env 준비 |
|
||||
| 09:34 이후 | Integration test 1차 실행 | `TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local ADB_SERVER_SOCKET=... ./scripts/integration_tests.sh` | 출력이 종료 후 표시되는 구조라 진행 상태 판단 곤란 |
|
||||
| 09:50 전후 | 실행 방식 재검토 | 프로세스 확인 및 실시간 출력 재실행 준비 | 다음 단계에서 스크립트 출력 개선 필요 |
|
||||
|
||||
## 4. 지연 원인
|
||||
|
||||
가장 큰 지연 원인은 `adb -a -P 5037 nodaemon server` 방식이 Windows 환경에서 안정적으로 동작하지 않은 점이다.
|
||||
|
||||
세부 원인은 아래와 같다.
|
||||
|
||||
- Windows ADB server가 기본적으로 `127.0.0.1:5037`에 먼저 바인딩되었다.
|
||||
- Android Studio, Device Manager, emulator 또는 다른 ADB client가 일반 ADB server를 자동으로 다시 띄웠다.
|
||||
- 기존 ADB PID를 종료해도 즉시 새 PID가 `127.0.0.1:5037`을 다시 점유했다.
|
||||
- `netstat`에는 잠깐 포트가 비어 보였지만, `adb -a` 실행 시점에는 다시 점유되어 `10048` 오류가 반복되었다.
|
||||
- WSL 내부에는 `adb`, `flutter`, `java`, `sdkmanager`, `emulator`가 PATH에 없어서 WSL 단독 emulator 방식으로 바로 전환할 수 없었다.
|
||||
- `scripts/integration_tests.sh`는 출력을 임시 파일에 모았다가 종료 후 출력하므로, Android 첫 빌드가 오래 걸릴 때 진행 상태를 실시간으로 확인하기 어려웠다.
|
||||
|
||||
## 5. 다음 동일 상황에서 지연을 줄이는 방법
|
||||
|
||||
다음부터 Windows Android Studio emulator를 WSL/Docker Flutter에서 사용할 때는 아래 순서를 우선 적용한다.
|
||||
|
||||
1. Windows에서 emulator를 먼저 실행하고 `adb.exe devices`로 `device` 상태를 확인한다.
|
||||
2. `adb -a -P 5037 nodaemon server`는 1차 시도만 한다.
|
||||
3. `10048`이 1회라도 재현되면 즉시 `portproxy` 방식으로 전환한다.
|
||||
4. 관리자 PowerShell에서 아래를 적용한다.
|
||||
|
||||
```powershell
|
||||
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=5037 connectaddress=127.0.0.1 connectport=5037
|
||||
netsh advfirewall firewall add rule name="ADB 5037 for WSL" dir=in action=allow protocol=TCP localport=5037
|
||||
netsh interface portproxy show v4tov4
|
||||
```
|
||||
|
||||
5. WSL에서 Windows host IP를 확인한다.
|
||||
|
||||
```bash
|
||||
awk '/nameserver/ {print $2; exit}' /etc/resolv.conf
|
||||
```
|
||||
|
||||
6. Docker Flutter 실행 시 아래 환경변수를 넘긴다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:<WINDOWS_HOST_IP>:5037
|
||||
```
|
||||
|
||||
이번 환경에서는 `<WINDOWS_HOST_IP>`가 `172.21.128.1`이었다.
|
||||
|
||||
7. 프로젝트 스크립트 기준으로 device 인식을 먼저 확인한다.
|
||||
|
||||
```bash
|
||||
ADB_SERVER_SOCKET=tcp:172.21.128.1:5037 ./scripts/flutter-docker.sh devices
|
||||
```
|
||||
|
||||
8. emulator에서 host API는 `127.0.0.1`이 아니라 `10.0.2.2`를 사용한다.
|
||||
|
||||
```bash
|
||||
TDC114_API_BASE=http://10.0.2.2:5000
|
||||
```
|
||||
|
||||
## 6. 후속 작업
|
||||
|
||||
- `scripts/integration_tests.sh`를 실시간 출력이 가능하도록 개선한다.
|
||||
- 동일 환경에서 integration test를 재실행한다.
|
||||
- 성공/실패 결과를 `docs/test-logs/2026-07-test-execution-log.md`에 누적 기록한다.
|
||||
- `docs/scenario_android_emulator_device_integration_test_2026-07-03.md`의 3-B 단계에 portproxy 우선 전환 기준을 보강한다.
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
# Flutter Docker 반복 지연 대응 정리
|
||||
|
||||
작성일: 2026-07-03
|
||||
대상: Windows Android Studio emulator + WSL/Docker Flutter CLI 조합에서 반복 실행 시 느려지는 항목
|
||||
|
||||
## 1. 목적
|
||||
|
||||
Android integration test와 Docker Flutter 실행에서 반복적으로 오래 걸리는 문제를 따로 모아, 다음 실행부터 시간을 줄일 수 있는 대응안을 정리한다.
|
||||
|
||||
## 2. 반복 지연 항목
|
||||
|
||||
| 항목 | 실제 증상 | 원인 | 우선 대응 |
|
||||
| --- | --- | --- | --- |
|
||||
| NDK 재설치 | 매 integration test에서 NDK license 확인 및 설치 반복 | Docker container가 매번 새로 뜨고 Android SDK 쓰기 경로가 유지되지 않음 | `.docker-cache/flutter/android-sdk/ndk` 유지 |
|
||||
| CMake 재설치 | 매 integration test에서 CMake license 확인 및 설치 반복 | 위와 동일 | `.docker-cache/flutter/android-sdk/cmake` 유지 |
|
||||
| Android SDK license 재확인 | license accept 로그 반복 | licenses 디렉터리 비지속 | `.docker-cache/flutter/android-sdk/licenses` 유지 |
|
||||
| Gradle dependency 준비 시간 | `assembleDebug`가 매번 길어짐 | `/root/.gradle` 비지속 | `.docker-cache/flutter/gradle` 유지 |
|
||||
| Flutter pub dependency 준비 | `flutter pub get` 반복 시간이 누적 | `/root/.pub-cache` 비지속 | `.docker-cache/flutter/pub` 유지 |
|
||||
| ADB unauthorized | emulator 연결은 되지만 `unauthorized` | Docker ADB key와 Windows 승인 key 불일치 | `.android-adb/`에 Windows ADB key 재사용 |
|
||||
| Integration test 직전 API 실패 | real API login test만 실패 | Baron/Ory runtime 중단 | `./scripts/api-smoke.sh` 선행 |
|
||||
|
||||
## 3. 이미 적용한 대응
|
||||
|
||||
현재 저장소에는 아래 대응이 이미 반영되어 있다.
|
||||
|
||||
- `scripts/flutter-docker.sh`
|
||||
- `.android-adb/`를 Docker `/root/.android`로 마운트
|
||||
- `.docker-cache/flutter/gradle`를 Docker `/root/.gradle`로 마운트
|
||||
- `.docker-cache/flutter/pub`를 Docker `/root/.pub-cache`로 마운트
|
||||
- `.docker-cache/flutter/android-sdk/licenses`를 Docker `/opt/android-sdk-linux/licenses`로 마운트
|
||||
- `.docker-cache/flutter/android-sdk/ndk`를 Docker `/opt/android-sdk-linux/ndk`로 마운트
|
||||
- `.docker-cache/flutter/android-sdk/cmake`를 Docker `/opt/android-sdk-linux/cmake`로 마운트
|
||||
- `.gitignore`
|
||||
- `.android-adb/`
|
||||
- `.docker-cache/`
|
||||
|
||||
## 4. 권장 실행 순서
|
||||
|
||||
반복 지연과 실패를 줄이려면 아래 순서를 기본값으로 사용한다.
|
||||
|
||||
1. Windows emulator를 먼저 실행한다.
|
||||
2. Windows `adb.exe devices`에서 `device` 상태를 확인한다.
|
||||
3. `5555` portproxy까지 준비한다.
|
||||
4. host 기준 `./scripts/api-smoke.sh`를 먼저 실행한다.
|
||||
5. 아래 명령으로 Docker local ADB 상태를 확인한다.
|
||||
|
||||
```bash
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/flutter-docker.sh devices
|
||||
```
|
||||
|
||||
6. 이후 integration test를 실행한다.
|
||||
|
||||
```bash
|
||||
TDC114_SMOKE_ENV_FILE=scripts/.env.android-emulator.local \
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 \
|
||||
./scripts/integration_tests.sh
|
||||
```
|
||||
|
||||
## 5. 지연을 더 줄이는 추가 후보
|
||||
|
||||
아래는 아직 이번 턴에서 적용하지 않았지만, 추가로 검토할 가치가 있다.
|
||||
|
||||
### 5.1 Flutter Docker image 고정
|
||||
|
||||
`ghcr.io/cirruslabs/flutter:stable` 대신 검증된 tag를 고정하면 image 내부 Android SDK 구성이 갑자기 바뀌는 위험을 줄일 수 있다.
|
||||
|
||||
예:
|
||||
|
||||
```bash
|
||||
FLUTTER_DOCKER_IMAGE=ghcr.io/cirruslabs/flutter:3.32.5
|
||||
```
|
||||
|
||||
효과:
|
||||
|
||||
- 예측 가능한 SDK/Gradle 조합 유지
|
||||
- cache 호환성 추적이 쉬워짐
|
||||
|
||||
주의:
|
||||
|
||||
- 프로젝트 Flutter 버전과 맞지 않는 tag는 피한다.
|
||||
|
||||
### 5.2 Android 빌드 전용 warm-up 명령
|
||||
|
||||
긴 integration test 전에 아래를 먼저 실행해 build cache를 예열할 수 있다.
|
||||
|
||||
```bash
|
||||
TDC114_ADB_CONNECT_ADDRESS=172.21.128.1:5555 ./scripts/flutter-docker.sh build apk --debug
|
||||
```
|
||||
|
||||
효과:
|
||||
|
||||
- 첫 integration test에서 체감 지연 감소
|
||||
|
||||
주의:
|
||||
|
||||
- 근본 해결은 cache 유지이며, warm-up은 보조 수단이다.
|
||||
|
||||
### 5.3 runtime health gate 자동화
|
||||
|
||||
integration test 시작 전에 `./scripts/check-baron-api-env.sh`와 `./scripts/api-smoke.sh`를 자동으로 선행하도록 `integration_tests.sh`를 확장할 수 있다.
|
||||
|
||||
효과:
|
||||
|
||||
- 앱 테스트 실패와 backend runtime 실패를 더 빨리 구분
|
||||
|
||||
주의:
|
||||
|
||||
- 테스트 시작 시간은 조금 늘어나지만, 재시도 횟수는 줄일 가능성이 크다.
|
||||
|
||||
## 6. 언제 cache를 비워야 하는가
|
||||
|
||||
아래 상황이 아니면 cache 삭제를 먼저 하지 않는다.
|
||||
|
||||
- Flutter Docker image를 크게 변경했다.
|
||||
- Gradle/NDK/CMake 관련 이상한 충돌이 반복된다.
|
||||
- cache 안 파일이 root 권한 꼬임으로 재사용되지 않는다.
|
||||
|
||||
부분 삭제 우선순위:
|
||||
|
||||
1. `.docker-cache/flutter/android-sdk/cmake`
|
||||
2. `.docker-cache/flutter/android-sdk/ndk`
|
||||
3. `.docker-cache/flutter/gradle`
|
||||
4. `.docker-cache/flutter/pub`
|
||||
|
||||
전체 삭제는 마지막 수단으로 둔다.
|
||||
|
||||
## 7. 현재 결론
|
||||
|
||||
매번 너무 오래 걸리는 문제는 어느 정도 해결 또는 완화가 가능하다.
|
||||
|
||||
- 해결 가능한 부분:
|
||||
- ADB unauthorized
|
||||
- NDK/CMake 반복 설치
|
||||
- Gradle/pub cache 반복 준비
|
||||
- backend runtime 미감지 상태에서 앱 테스트를 먼저 돌리는 문제
|
||||
|
||||
- 완화만 가능한 부분:
|
||||
- Android 첫 빌드 자체의 절대 시간
|
||||
- Docker image pull 또는 변경 직후 초기 warm-up 비용
|
||||
- emulator 자체 부팅 시간
|
||||
|
||||
다음 실행부터는 `5555 + Docker local ADB + cache 유지 + api-smoke 선행` 조합을 기본값으로 사용한다.
|
||||
Reference in New Issue
Block a user