# EG-BIM Q&A 로그인부터 글 저장까지 전이맵 기준일: 2026-09-21 대상: `qa-test.baroncs.co.kr` / EG-BIM Q&A 구성: 목록(`index.html`) · 작성(`write.html`) · 상세(`detail.html`) ## 1. 전체 흐름 홈페이지 로그인 정보를 Q&A 사이트로 직접 전달하지 않는다. 홈페이지의 Q&A 링크는 별도 호스트로 이동하고, Q&A는 같은 BRSW OIDC SSO에 직접 인증을 요청한다. 이미 중앙 SSO 세션이 있으면 사용자는 로그인 화면을 보지 않고 Q&A 세션을 발급받는다. ```mermaid flowchart TD A[바론 홈페이지
EG-BIM Q&A 링크] --> B[Q&A 목록 진입
https://qa-test.baroncs.co.kr/egbim/] B --> C{Q&A 세션 쿠키
baron_qa_session_v2 유효?} C -- 예 --> G[정적 목록 페이지 표시] C -- 아니오 --> D[302 /auth/login
return_url 보관] D --> E[Worker가 PKCE 생성
state · verifier · nonce] E --> F[BARON-SSO OIDC
sso.hmac.kr/oidc] F --> F1{중앙 SSO 세션 존재?} F1 -- 아니오 --> F2[SSO 로그인 화면] F2 --> F3[최초 동의 화면
필요 시 1회] F1 -- 예 --> H[승인 코드 발급] F3 --> H H --> I[/auth/callback?code&state] I --> J[Worker가 state 검증
PKCE code_verifier 검증] J --> K[Token Endpoint 호출
Public Client · client_secret 없음] K --> L[UserInfo 조회 및 claim 정규화] L --> M[baron_qa_session_v2 발급
HttpOnly · Secure · SameSite=Lax] M --> G G --> N[문의 등록 버튼] N --> O[작성 페이지
write.html] O --> P[GET /auth/session
작성자·tenant 표시] P --> Q{userUuid와 tenantId 존재?} Q -- 아니오 --> R[제출 차단
다시 로그인 안내] Q -- 예 --> S[카테고리·제목·내용·비밀글 입력] S --> T[등록 버튼 클릭] T --> U[브라우저 UUID 생성
feedbackId] U --> V{첨부파일 존재?} V -- 아니오 --> Y[첨부 메타데이터 빈 배열] V -- 예 --> W[POST presign 요청] W --> X[qa_cdn presigned URL로
파일 PUT 업로드] X --> Y[첨부파일 메타데이터 확정] Y --> Z[feedback envelope 생성] Z --> AA{apiBaseUrl 설정 여부} AA -- 비어 있음
현재 테스트 모드 --> AB[localStorage에 임시 저장] AA -- 설정됨
실서비스 모드 --> AC[POST /v1/qa/feedbacks
feedback.hmac.kr API] AB --> AD[등록 완료 toast
상세 페이지 이동] AC --> AE{API 성공?} AE -- 예 --> AD AE -- 아니오 --> AF[오류 표시
재시도 가능] ``` ## 2. 상태 전이표 | 상태 | 화면/주소 | 진입 조건 | 주요 처리 | 다음 상태 | |---|---|---|---|---| | `S0` | 홈페이지 | Q&A 메뉴 클릭 | 외부 Q&A URL로 이동 | `S1` | | `S1` | `/egbim/` | Q&A 세션 유효 | R2의 목록 HTML 제공 | `S5` | | `S2` | `/auth/login` | 세션 없음 | PKCE 상태 생성, SSO로 redirect | `S3` | | `S3` | `sso.hmac.kr/oidc` | SSO 세션 없음 | 최초 로그인 및 동의 | `S4` | | `S4` | `/auth/callback` | `code`, `state` 수신 | state/PKCE 검증, token/userinfo 조회 | `S5` | | `S5` | 목록 또는 작성 페이지 | `baron_qa_session_v2` 유효 | `/auth/session`에서 사용자 확인 | `S6` | | `S6` | `write.html` | `userUuid`, `tenantId` 확인 | 작성 폼 입력 대기 | `S7` | | `S7` | 작성 페이지 | 등록 클릭 | `feedbackId` UUID 생성 및 입력 검증 | `S8` | | `S8` | 작성 페이지 | 첨부 있음 | presign → `qa_cdn` 업로드 | `S9` | | `S9` | 작성 페이지 | payload 준비 | feedback/support ticket envelope 생성 | `S10` | | `S10` | API 또는 localStorage | `apiBaseUrl` 상태에 따라 분기 | 실제 DB 저장 또는 테스트 저장 | `S11` | | `S11` | `detail.html?id=...` | 저장 성공 | 등록 완료 및 상세 이동 | 종료 | ## 3. 화면별 사용자 경험 ### A. 홈페이지 - EG-BIM 메뉴의 Q&A 링크만 제공한다. - 로그인 정보, 쿠키, token, `SESSION_SECRET`을 Q&A로 전달하지 않는다. - 링크 대상: ```text https://qa-test.baroncs.co.kr/egbim/ ``` ### B. 중앙 SSO - Q&A RP는 `https://sso.hmac.kr/oidc`를 사용한다. - 최초 사용자는 SSO 로그인 및 동의 화면을 볼 수 있다. - 같은 중앙 SSO 세션이 있으면 다음 접근부터 로그인 화면 없이 authorization code가 발급된다. - Q&A RP는 PKCE Public Client이므로 client secret을 보내지 않는다. ### C. Q&A 목록 - Worker가 `baron_qa_session_v2`를 검사한다. - 세션이 없으면 `/auth/login?return_url=...`로 이동한다. - 세션이 있으면 R2의 `egbim/index.html`을 제공한다. ### D. Q&A 작성 - 브라우저가 `GET /auth/session`을 호출한다. - 다음 작성자 정보를 화면과 payload에 사용한다. ```text userUuid ssoSubject / requesterId tenantId / requesterTenantId tenantIds scope roles email name department phone ``` - `requesterId` 또는 `requesterTenantId`가 없으면 제출을 차단한다. ### E. 글 저장 - 브라우저에서 `feedbackId` UUID를 1회 생성한다. - 같은 UUID를 다음 식별자로 재사용한다. ```text feedback.id feedback.source_record_id support_tickets.idempotency_key ``` - 첨부파일은 `qa_cdn`에 저장하고, DB에는 bucket/key 및 파일 메타데이터를 기록한다. - 실제 운영에서는 feedback API가 서버 측에서 Q&A 세션 또는 SSO token을 검증해야 한다. ## 4. 현재 테스트 모드와 운영 모드 현재 `egbim/config.js`는 다음과 같이 `apiBaseUrl`이 비어 있다. ```js apiBaseUrl: '' ``` 따라서 현재 등록 결과는 다음과 같이 동작한다. ```text 글 작성 → UUID 생성 → localStorage 저장 → 상세 페이지 이동 ``` 운영 API 주소를 설정하면 다음 흐름으로 변경된다. ```text 첨부 presign 요청 → qa_cdn 직접 업로드 → feedback.hmac.kr/v1/qa/feedbacks 호출 → feedbacks/support_tickets 트랜잭션 저장 → 상세 페이지 이동 ``` ## 5. 주요 실패 전이 | 실패 지점 | 사용자 화면 | 원인/확인 항목 | |---|---|---| | SSO 로그인 전 | 로그인 화면 | 중앙 SSO 세션 없음 또는 다른 SSO 환경 | | callback | `invalid_oauth_state` | OAuth cookie 만료, 호스트 변경, state 불일치 | | token 교환 | `oauth_token_exchange_failed` | issuer/endpoint/client ID/PKCE 설정 불일치 | | 세션 확인 | `authenticated:false` | `baron_qa_session_v2` 없음·만료·`SESSION_SECRET` 불일치 | | 작성자 확인 | UUID/tenant 오류 | SSO scope 또는 claim mapping 누락 | | 첨부 업로드 | 업로드 실패 | presign API 또는 `qa_cdn` 권한 오류 | | DB 저장 | API 요청 오류 | `apiBaseUrl`, CORS, API 인증, DB envelope 규격 오류 |