Files
llm-wiki/raw/branch-notes/feature-keycloak-bff-vs-spa-direct.md

28 KiB

title, source_type, status, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, branch, parent_branch, related_projects, tags, created, target_merge, status_label, contract_packet_sha256
title source_type status id kind project work_item inherits refines overrides depends_on contract_packet branch parent_branch related_projects tags created target_merge status_label contract_packet_sha256
branch / feature-keycloak-bff-vs-spa-direct (BFF 대안 비교 — SPA Direct vs Backend-for-Frontend) branch-note raw BR-KEYCLOAK-CHILD-2BFCDCAB branch-child keycloak-patterns-overview WI-KEYCLOAK-PATTERNS-OVERVIEW-020
DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1
1 feature-keycloak-bff-vs-spa-direct feature-keycloak-patterns
keycloak-patterns
branch
keycloak-patterns
p2a
bff
spa
xss-surface
session
oauth2-login
2026-05-25 in-progress f0b2fdad99f29c8e633580dc9d5b65c5b88879f90ace63f773a6ded847306d5f

branch: feature-keycloak-bff-vs-spa-direct — BFF 대안 비교

Layer: raw/branch-notes/raw/branch-notes/feature-keycloak-patterns의 branch-child. 목적: P2A(SPA Direct, 토큰을 SPA가 보유) vs BFF(Backend-for-Frontend, 토큰을 백엔드가 보유)의 XSS surface 차이와 stateful trade-off를 명확히 정리. status_label: in-progress | review | merged | abandoned

부모 (필수)

raw/branch-notes/feature-keycloak-patterns

브랜치 계약 패킷

  • 생성 시 프로젝트 개정: 1
  • 패킷 스키마: contract_packet: 1
  • 완료 조건: project governance hub가 AP1~AP4 taxonomy와 child progress index를 유지한다

상속한 프로젝트 결정

Decision Ref Project Summary Branch Application Source
DEC-KEYCLOAK-PATTERNS-OVERVIEW-AUTH-TAXONOMY-001@1 canonical 분류축은 AP1~AP4 인증 통합 아키텍처와 cross-cutting 변형이다 SPA Direct와 BFF 비교를 AP taxonomy의 대안 근거로 유지한다 raw/project-notes/keycloak-patterns-overview

브랜치 지역 결정

Decision ID Decision Relation Supporting Claims Status
D1 학습 baseline은 SPA Direct로 둔다 local raw/project-notes/keycloak-patterns-overview proposed
D2 BFF 구현은 비교 문서 범위로 제한한다 local raw/project-notes/keycloak-patterns-overview proposed
D3 native client는 별도 PKCE 흐름이 필요함을 기록한다 local raw/project-notes/keycloak-patterns-overview proposed
D4 browser token XSS surface를 BFF motivation으로 기록한다 local raw/project-notes/keycloak-patterns-overview proposed
D5 BFF 권고의 적용 조건을 client credential 사용 여부로 제한한다 local raw/project-notes/keycloak-patterns-overview proposed

선언한 예외

Override ID Overrides Reason Approval Status

없음.

목표

P2A SPA Direct는 OIDC + PKCE의 canonical 흐름이지만 토큰이 브라우저(JS 컨텍스트)에 존재한다는 근본적 위험이 있다. BFF는 이 위험을 제거하는 변형 — 백엔드가 OAuth client 역할을 하고, 브라우저는 httpOnly session cookie만 보유. Curity 등 보안 벤더가 권고하는 패턴.

핵심 질문:

  • BFF 아키텍처에서 토큰이 흐르는 경계는? 누가 보관하는가?
  • Spring Security oauth2Login + session vs Spring Authorization Server (AS 자체 구축) 차이?
  • BFF 단점은? (stateful, scale-out 시 session sharing 필요)
  • 어떤 기준으로 SPA Direct vs BFF를 결정하는가? (XSS 민감도 / 모바일 클라이언트 유무 / 운영 복잡도)

본 sub-sub-branch는 아키텍처 다이어그램 + Spring 구현 옵션 + 결정 기준 매트릭스를 정리.

  • 이슈: (학습 노트, 이슈 없음)
  • PR: (구현 없음)

범위

포함 범위

  • BFF(Backend-for-Frontend)와 SPA Direct(P2A)의 XSS surface 차이 정리 — 토큰이 브라우저(JS 컨텍스트)에 있는가 vs 백엔드에 있는가의 경계
  • BFF 아키텍처 다이어그램 + 토큰 흐름 경계(누가 access/refresh token holder 인가)
  • Spring Security oauth2Login (BFF) 구현 옵션의 사전 명세documented-only (실 구현 아님, §구현 가이드)
  • SPA Direct vs BFF 결정 기준 매트릭스 — "언제 어느 패턴" 선택 조건 (XSS 민감도 / 모바일 클라이언트 유무 / 백엔드 stateless / 운영 복잡도 / revocation 즉시성 / OAuth 2.1의 client-credentials 조건부 권고)
  • Curity(company-tech-blog) + OAuth 2.1 draft(official-standard) 인용으로 BFF motivation 근거화

제외 범위

의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.

  • BFF 실 구현/배포 — 문서화만. documented-only 유지(D2). P3A 실 구현 이후 XSS 민감 요구 발생 시 별도 확장 branch
  • Spring Authorization Server (AS 자체 구축) — Keycloak 대체 프로젝트로 BFF 결정과 직교. Keycloak을 AS로 두고 oauth2Login만으로 BFF 성립하므로 본 학습 범위 밖
  • P1A Edge ForwardAuth 상세 — 형제 raw/branch-notes/feature-keycloak-edge-forwardauth-no-google 소관 (본 branch는 BFF와의 개념 구분만)
  • SPA Direct 토큰 저장 위치 상세 — 형제 raw/branch-notes/feature-keycloak-spa-token-storage-tradeoff 소관
  • refresh token rotation/revocation 상세 — 형제 raw/branch-notes/feature-keycloak-refresh-token-rotation 소관
  • 모바일/native OAuth client 실 흐름 — RFC 8252 public-client PKCE 흐름 자체의 구현. 본 branch는 "BFF가 모바일을 커버 못 함"의 한계 명시까지만(D3)

근거 (필수, 최소 1개+)

TODO

각 항목 옆에 증거 등급 표기: actually-implemented | locally-verified | prod-verified | documented-only | planned | needs-confirmation

  • BFF 아키텍처 다이어그램 — 등급: planned
                                            ┌─────────────────┐
                                            │  Keycloak       │
                                            └────────▲────────┘
                                                     │ OIDC (server-side)
                                                     │  access/refresh
                                                     │  token 보유
                                            ┌────────┴────────┐
    Browser (SPA) ── httpOnly session ────► │   BFF (Backend) │ ── Bearer token ──► Resource API
                  cookie (JSESSIONID 등)    │  - session store│   (BFF가 token
                                            │  - token cache  │    holder)
                                            └─────────────────┘
    
    • 브라우저: 토큰 0개, session cookie만
    • BFF: OAuth client 역할 + session ↔ token mapping 보관 (in-memory / Redis)
  • Spring Security oauth2Login 구현 옵션 — 등급: documented-only
    • 의존성: spring-boot-starter-oauth2-client
    • application.yml:
      spring:
        security:
          oauth2:
            client:
              registration:
                keycloak:
                  client-id: bff-client
                  client-secret: <secret>
                  authorization-grant-type: authorization_code
                  redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
                  scope: openid, profile, email
              provider:
                keycloak:
                  issuer-uri: https://<keycloak>/realms/<realm>
      
    • http.oauth2Login(...) + http.sessionManagement(...) (stateful session)
    • 백엔드가 자동으로 authorization code flow 수행 + session 생성 + OAuth2AuthorizedClient에 토큰 보관
  • Spring Authorization Server 대안 — 등급: documented-only
    • Spring Authorization Server는 AS 자체를 직접 구축하는 프로젝트 (Keycloak 대체). BFF와 직교한 결정.
    • BFF 본질은 "백엔드가 OAuth client" — Keycloak을 AS로 두고 Spring oauth2Login만으로 충분.
    • 본 P2A 학습 범위 외 (Keycloak 대체 안 함)
  • BFF 단점 — 등급: documented-only
    • Stateful: session store 필요 → scale-out 시 sticky session 또는 Redis 등 외부 session store
    • 모바일 클라이언트: BFF는 web SPA 전용. 모바일은 별도 OAuth client 흐름 필요 → BFF가 모바일까지 커버하려면 추가 endpoint 설계
    • CSRF surface 증가: session cookie 자동 첨부 → CSRF token 또는 SameSite 필요
    • 운영 복잡도: session store 장애 시 전체 로그인 무효화
  • 결정 기준 매트릭스 — 등급: documented-only
    기준 SPA Direct (P2A) 우위 BFF 우위
    XSS 민감도 (금융/의료)
    모바일/네이티브 동일 흐름
    백엔드 stateless 유지
    운영 단순성 (session store 불필요)
    토큰 revocation 즉시성 (session 종료)
    OAuth 2.1 draft 권고 public client + PKCE client credentials가 필요한 browser app (D5)
    다중 backend microservice (각자 JWT 검증) △ (BFF가 fan-out)
  • Curity / OAuth 2.1 draft 인용 — 등급: documented-only
    • Curity: "The only way to protect tokens from being accessed by any malicious code is to keep them away from the browser."
    • OAuth 2.1 draft §2.1: browser-based app 이 client credentials 를 사용하려는 경우 BFF 패턴을 권고 (OA21-C4 — "browser-based app 전반 의무" 아님, 조건부)

진행 중 메모

작업하며 떠오른 메모. 자유 형식.

  • BFF는 "토큰을 백엔드에 두는 OAuth client" 패턴. P1A(Edge ForwardAuth)와 헷갈리기 쉬운데 두 가지가 다름:
    • P1A는 reverse proxy가 인증 검문소(별도 컴포넌트 oauth2-proxy)
    • BFF는 application backend 자체가 OAuth client + session holder
  • Spring Security oauth2Login은 본질적으로 BFF 패턴을 자동 구현해 줌. SPA Direct와 다른 starter(oauth2-client vs oauth2-resource-server)를 쓴다는 점이 명확한 분기점.

결정 사항 (decisions)

추후 면접/회고에서 "왜 이렇게 했나" 답할 근거. 대안과 함께 기록.

  • 2026-05-25: 본 keycloak-patterns 프로젝트는 SPA Direct (P2A)를 학습 목적의 1순위로 채택. BFF는 비교 문서로만 정리. 이유: canonical OIDC + PKCE 흐름을 먼저 이해하는 것이 목표.
  • 2026-05-25: BFF 실 구현은 본 sub-sub-branch 범위 외 — SSOT §8 자신 없는 부분에 BFF 미경험으로 명시되어 있고, P3A 구현 이후 별도 확장 시 고려.
  • 2026-05-25: BFF의 모바일 한계는 분명히 기록 (P2A 형제 branch에서 다중 클라이언트 장점을 활용한 결정과 연결).

결정-근거 매핑

각 결정이 어떤 raw source claim 으로 뒷받침되는지. company-tech-blog 인 Curity 는 company-case-study 강도이며, OAuth 2.1 draft (official-standard) 와 Keycloak 공식 doc (official-vendor-doc) 으로만 official best practice 단언 가능. 단독 company-tech-blog 만으로는 official 단언 금지.

선택 조건 열(R2): "이 조건일 때 이 결정, 다른 조건이면 어떤 대안". 본 branch 는 SPA Direct vs BFF 선택 자체가 주제이므로 각 결정의 선택 기준을 명시한다.

Decision ID Decision 선택 조건 (언제 이 결정 / 언제 대안) Supporting Claims Evidence Strength Open Risk
D1 본 keycloak-patterns 프로젝트는 SPA Direct (P2A) 를 학습 1순위로 채택, BFF 는 비교 문서로만 정리 canonical OIDC + PKCE 흐름 학습이 1차 목표일 때 SPA Direct. XSS 민감 데이터(금융/의료) 운영 요구가 우선이면 BFF 를 1순위로 전환 raw/official-docs/oauth-v2-1-draft-ietf.md#OA21-C1 (PKCE MUST — canonical SPA Direct 흐름), raw/official-docs/oauth-v2-1-draft-ietf.md#OA21-C4 (BFF 권고는 client credentials 사용 시) official-standard P2A SPA Direct 가 OAuth 2.1 §2.1 의 "client credentials 없는 public client + PKCE" 시나리오에 정합한지 본 프로젝트 client 설정 (Standard Flow + Public + PKCE S256) 으로 실 검증 필요
D2 BFF 실 구현은 본 sub-sub-branch 범위 외 (documented-only 유지) 학습 우선순위/시간 제약 하에서는 문서화만. P3A 실 구현 완료 + XSS 민감 요구 발생 시 별도 확장 branch 로 실 구현 UNSUPPORTED_DECISION (운영 결정 — 학습 우선순위 / 시간 제약 사유, 외부 자료가 직접 뒷받침하지 않음) UNSUPPORTED_DECISION 미구현 상태에서 면접/포트폴리오에 BFF 경험을 주장하면 거짓. 본 branch 의 모든 BFF 관련 등급은 documented-only 로 유지해야 함
D3 BFF 의 모바일 한계 (모바일은 별도 OAuth client 흐름 필요) 를 명시적으로 기록 web SPA 단일 클라이언트면 BFF 성립. 모바일/native 클라이언트가 공존하면 native 는 별도 public-client PKCE 흐름(RFC 8252)이 MUST → BFF 단독으로 커버 불가, SPA Direct 가 다중 클라이언트에 유리 raw/official-docs/security-oauth2-pkce-rfc-8252.md#RFC8252-C1 (native public client 는 자체 PKCE 흐름 MUST — "별도 흐름 필요" 절반을 corroborate) official-standard (부분 — "모바일은 별도 흐름 필요"만 근거; "BFF 가 모바일에서 동작 불가"는 여전히 추론) RFC8252-C1 은 native 가 자체 PKCE 흐름을 MUST 사용함을 보장할 뿐, "BFF session cookie 모델이 모바일에서 동작 안 한다"는 절대 표현은 직접 없음. 모바일 SDK 측 cookie 처리 / native browser handoff 는 별도 검증(Claims To Verify) 필요
D4 "토큰을 브라우저 밖에 두는 것이 XSS 로부터 보호하는 방법" 이라는 BFF motivation 인용 XSS 위협 모델이 유의(브라우저에 token 존재 = 탈취 표면)한 SPA 일 때 이 motivation 이 BFF 채택 근거. XSS 표면이 무의미할 만큼 통제(CSP/sanitization)되면 SPA Direct 도 허용 raw/company-tech-blogs/curity-bff-pattern-spa.md#CURITY-BFF-C1, raw/company-tech-blogs/curity-bff-pattern-spa.md#CURITY-BFF-C3, raw/company-tech-blogs/curity-bff-pattern-spa.md#CURITY-BFF-C4 company-case-study Curity 는 vendor 이며 본 인용은 official best practice 가 아님. "유일한 방법" 표현은 vendor 의 강한 주장 — OAuth 2.1 OA21-C4 로만 official 권고 corroborate 가능
D5 OAuth 2.1 draft 가 browser-based app 에서 BFF 패턴을 권고한다는 진술 SPA 가 client credentials 를 사용하려는 경우(§2.1 조건)에 BFF 권고. public client + PKCE 만이면 SPA Direct 도 표준 허용 — "browser-based app 전반 의무" 아님 raw/official-docs/oauth-v2-1-draft-ietf.md#OA21-C4 official-standard OA21-C4의 조건은 source-grounded이나, 본 프로젝트는 confidential BFF client와 client-secret runtime을 아직 구현하지 않았다. 실제 BFF 선택·동작 evidence는 documented-only

구현 가이드

본 branch 는 documented-only 비교/학습 branch — 실행 코드가 아니라 BFF 대안의 사전 명세 + 결정 기준 매트릭스의 근거 매핑이 산출물이다. 아래 in-scope 항목은 D1·D4·D5 결정의 도출이며, 소스가 원칙만 권고하고 detail 을 사용자가 정해야 하는 cell 은 UNSUPPORTED_IMPL_DECISION 라벨을 단다. 실 구현(코드) 등급은 모두 planned.

1. 토큰 holder 명세

Trace: D4 (Curity BFF motivation — CURITY-BFF-C1/C3/C4) + D5 (OAuth 2.1 조건부 권고 — OA21-C4). BFF 의 핵심은 토큰이 흐르는 경계와 holder 를 SPA Direct 대비 이동시키는 것.

  • UNSUPPORTED_IMPL_DECISION: session store 백엔드(in-memory vs Redis)는 소스 미권고 — scale-out 요구에 따른 사용자 결정. trade-off: 학습 문서라 단일 인스턴스 in-memory 가정으로 충분, HA 필요 시 Redis 로 승격.
경계 무엇을 보유 메커니즘 근거 등급
브라우저 (SPA) 토큰 0개, httpOnly session cookie(JSESSIONID 등)만 BFF 가 발급한 session cookie 로 세션 식별 CURITY-BFF-C4 (OAuth Agent 가 httpOnly session cookie 발급) documented-only
BFF (백엔드) access/refresh token + session↔token mapping server-side authorization code flow 수행 후 서버 메모리/store 에 보관 CURITY-BFF-C3 (모든 통신이 backend OAuth Agent 경유, token 은 SPA 미도달) documented-only
BFF ↔ Keycloak — (server-to-server) server-side authorization_code flow, access/refresh 서버 보유 OA21-C4 (client credentials 시 BFF 권고) documented-only
BFF ↔ Resource API BFF 가 보유 token 을 Bearer 로 fan-out OAuth2AuthorizedClient 의 access token 을 downstream 호출에 첨부 UNSUPPORTED_IMPL_DECISION — Curity "OAuth Agent" 의 Spring 대응이 OAuth2AuthorizedClient 인지 미확정(Claims To Verify #4). trade-off: Spring 표준 API 로 가정, vendor 1:1 대응은 미검증 planned

2. Spring Security oauth2Login (BFF) 구성 사전 명세

Trace: D5 (OA21-C4 — BFF 권고) + D4 (CURITY-BFF-C4 — session cookie 모델). BFF 를 Spring 으로 구현하면 SPA Direct 의 oauth2-resource-server 대신 oauth2-client starter 를 쓴다는 것이 명확한 분기점(진행 중 메모).

  • UNSUPPORTED_IMPL_DECISION: client-id: bff-client·scope·redirect-uri 의 구체 값은 소스가 아니라 배포 환경이 정함. trade-off: 본 명세는 형태(shape)만 확정, 값은 실 realm 등록 시점에 채움.
항목 명세 근거 등급
의존성 spring-boot-starter-oauth2-client (SPA Direct 의 -resource-server 와 대비되는 분기점) 진행 중 메모 + D5 documented-only
flow wiring http.oauth2Login(...) + http.sessionManagement(...) — 백엔드가 authorization code flow 자동 수행 + session 생성 + OAuth2AuthorizedClient 에 토큰 보관 D5 (OA21-C4) documented-only
브라우저 세션 oauth2Login 이 인증 후 httpOnly session cookie 발급 (Curity 의 OAuth Agent 역할과 동등) CURITY-BFF-C4 documented-only
application.yml registration.keycloak (client-id/secret/authorization_code/redirect-uri) + provider.keycloak.issuer-uri — 값은 UNSUPPORTED_IMPL_DECISION D5 planned
실 동작 검증 Boot 3.x 에서 /login/oauth2/code/keycloak callback 200 + session cookie 발급 확인 Claims To Verify #1 planned

3. SPA Direct vs BFF 결정 기준 매트릭스 — 셀별 근거 매핑

Trace: D1 (SPA Direct 채택) + D5 (조건부 BFF 권고). 본 매트릭스가 "언제 어느 패턴" 선택 조건의 근거. §TODO 의 매트릭스(원본 표) 각 셀을 supporting claim 또는 UNSUPPORTED_IMPL_DECISION 으로 분해 — Claims To Verify #5(셀→claim 매핑 planned)를 종결.

  • UNSUPPORTED_IMPL_DECISION: "백엔드 stateless"·"운영 단순성"·"다중 microservice"·"revocation 즉시성" 셀은 본 branch Sources 에 직접 인용이 없는 아키텍처 분석 통찰이다. trade-off: 일반 원리(BFF=stateful session store / JWT=stateless revocation 난이도)로 성립하나 official 단정 불가 — 형제 branch 결정에 위임(§엣지·실패·의존).
매트릭스 셀 우위 뒷받침 근거 판정
XSS 민감도 (금융/의료) BFF CURITY-BFF-C1 (token 브라우저 밖 = XSS 보호), CURITY-BFF-C2 (SPA 악성코드가 token read 가능), CURITY-BFF-C6 (refresh token 탈취 위험) company-case-study
모바일/네이티브 동일 흐름 SPA Direct RFC8252-C1 (native 는 자체 public-client PKCE 흐름 — SPA Direct token 흐름 재사용 가능, BFF session cookie 는 부적합) official-standard (부분)
백엔드 stateless 유지 SPA Direct UNSUPPORTED_IMPL_DECISION — BFF 는 session store 필요(stateful)라는 일반 원리. CURITY-BFF-C4 의 "session cookie 발급"이 stateful 함의를 뒷받침하나 직접 단정은 아님 분석 통찰
운영 단순성 (session store 불필요) SPA Direct UNSUPPORTED_IMPL_DECISION — 위와 동일(session store 유무) 분석 통찰
토큰 revocation 즉시성 BFF (session 종료) UNSUPPORTED_IMPL_DECISION — JWT stateless = revocation 난이도는 형제 raw/branch-notes/feature-keycloak-refresh-token-rotation 소관. 본 branch 직접 인용 없음 위임
OAuth 2.1 draft 권고 BFF (조건부) OA21-C4 (client credentials 사용 시 BFF 권고 — 무조건 아님) official-standard
다중 backend microservice SPA Direct (각자 JWT 검증) UNSUPPORTED_IMPL_DECISION — 각 RS 의 aud 검증은 형제 raw/branch-notes/feature-keycloak-spring-rs-audience-validator 소관. 본 branch 직접 인용 없음 위임

엣지·실패·의존

R4(깊이 게이트) 캡처용. BFF 는 SPA Direct 대비 stateful 로 전환되므로 정상 경로 밖의 실패/엣지가 늘어난다. 본 branch 는 documented-only 이나, 실 구현 시 부딪힐 실패 경로와 형제 계약 의존을 미리 열거한다.

  • 실패·엣지 경로:

    • session store 장애 → 전체 로그인 무효화: BFF 는 session↔token mapping 을 보유(§구현 가이드 §1)하므로 store 장애 시 모든 활성 세션 유실. 기대 동작: 외부 session store(Redis) HA 또는 sticky session. 근거: CURITY-BFF-C4 의 session cookie 모델(D4).
    • CSRF surface 증가: session cookie 는 브라우저가 자동 첨부 → CSRF 취약. 기대 동작: CSRF token(동기화 토큰) 또는 SameSite=Lax/Strict cookie 속성 필수. CURITY-BFF-C4 는 "session cookie 발급"만 보장하고 CSRF 통제는 미언급 — 별도 명시 필요.
    • scale-out 시 session sharing: 다중 BFF 인스턴스면 session 공유(Redis) 필수. sticky session 은 인스턴스 장애 시 해당 세션 유실. UNSUPPORTED_IMPL_DECISION(§구현 가이드 §3 "백엔드 stateless" 셀과 동일 원리).
    • 모바일 클라이언트 handoff: BFF session cookie 모델은 native 앱에 부적합. native 는 RFC8252-C1 의 public-client PKCE 별도 흐름이 MUST(D3). BFF 로 모바일까지 커버하려면 추가 endpoint 설계 필요.
    • Keycloak 미가용: BFF 는 server-side authorization code flow 로 token 을 획득하므로 로그인 시점 Keycloak 장애 → 신규 로그인 차단(기존 세션은 BFF 보유 token 만료 전까지 유지). SPA Direct 와 달리 브라우저가 직접 Keycloak 을 치지 않음.
  • 다른 계약 의존:

    • raw/branch-notes/feature-keycloak-internal-spa-direct-no-google (P2A parent) 의 D1(SPA Direct = 브라우저 token 보유 정의) — 본 비교의 SPA Direct 기준선. 그 정의가 바뀌면 본 매트릭스 전체가 영향.
    • raw/branch-notes/feature-keycloak-spa-token-storage-tradeoff D1 — pure SPA는 access/refresh 모두 memory-only이며 reload 시 재인증한다. HttpOnly refresh cookie는 TMB/BFF variant일 때만 평가하며, 본 매트릭스의 SPA Direct 기준선은 owner 결론을 consume한다.
    • raw/branch-notes/feature-keycloak-refresh-token-rotationD1(rotation 활성화 — reuse detection) + D2(access token revocation = 짧은 TTL 로 해결) — 매트릭스 "revocation 즉시성" 셀(§구현 가이드 §3, UNSUPPORTED_IMPL_DECISION 위임)이 이 결정에 의존. 그 branch 가 rotation 정책을 바꾸면 SPA Direct 의 revocation 약점 평가가 달라짐.
    • raw/branch-notes/feature-keycloak-spring-rs-audience-validatorD1(iss+sig+exp+aud 4종 검증, aud 는 custom validator 필수) + D4(SPA client scope 에 Audience mapper 등록 필수) — 매트릭스 "다중 microservice" 셀(위임)이 각 RS 의 aud 검증에 의존. fan-out 시 각 downstream 이 자기 client 를 aud 로 검증해야 cross-client reuse 방지.
    • raw/branch-notes/feature-keycloak-edge-forwardauth-no-google (P1A) — BFF 와 개념 혼동 방지(진행 중 메모). P1A = 별도 reverse proxy 가 인증 검문소, BFF = application backend 자체가 OAuth client. 계약 의존은 아니나 경계 구분 유지 필요.

검증해야 할 주장

공식 문서 / 사례는 근거지만, 본 프로젝트의 실제 동작은 자동 보장되지 않는다. 구현 전후 검증 항목.

Claim Why uncertain How to verify Status
Spring Security oauth2Login (spring-boot-starter-oauth2-client) 가 본 branch 본문 yml 설정 그대로 Keycloak 과 authorization code flow 를 성공시키는지 본 branch 의 yml 은 documented-only 단계 — 실 구현 없음. starter 버전 / Spring Boot 3.x compat 확인 안 됨 실제 Spring Boot 3.x project 에 의존성 추가 + application.yml 적용 후 /login/oauth2/code/keycloak callback 200 확인, session cookie 발급 확인 planned
Keycloak 의 client 설정 (Standard Flow + Public + PKCE S256) 이 P2A SPA Direct 와 정합한지 본 branch 는 BFF 비교만 다루고 P2A client 설정의 실 등록을 안 했음 Keycloak realm export → client config JSON 에서 standardFlowEnabled=true, publicClient=true, attributes.pkce.code.challenge.method=S256 확인 needs-confirmation
BFF 가 모바일 클라이언트에서 실제로 동작 불가한지 (또는 별도 흐름이 정확히 필요한지) 본 branch Sources 에 직접 인용 없음 — 본문 통찰만 RFC 8252 (OAuth 2.0 for Native Apps) 정독 + raw/official-docs/security-oauth2-pkce-rfc-8252.md 와 cross-check, 모바일 SDK 에서 BFF session cookie 핸들링 동작 확인 needs-confirmation
Curity 의 "OAuth Agent" 명명이 다른 vendor (Auth0, IdentityServer, Spring Authorization Server) 의 BFF 구현에도 1:1 대응되는지 CURITY-BFF-C3 의 "OAuth Agent" 는 vendor-specific 명명 각 vendor 의 BFF docs 정독 — Spring Security oauth2LoginOAuth2AuthorizedClient 가 동등 역할인지 확인 planned
결정 기준 매트릭스 (XSS 민감도 / 모바일 / stateless / 운영 / revocation / OAuth 2.1 권고 / multi-microservice) 의 각 셀이 본 sources 중 어느 인용으로 직접 뒷받침되는지 본 branch 본문 매트릭스는 종합 판단 — 셀별 source mapping 부재 각 셀마다 supporting claim 명시 또는 UNSUPPORTED 표시로 분해 planned

마주친 문제

  • 이슈 1: P1A(Edge ForwardAuth)와 BFF의 차이를 한 문장으로 설명하기 까다로움.
    • 원인: 둘 다 "토큰을 브라우저에서 분리"하지만 분리 주체와 위치가 다름
    • 시도: (문서 정리)
    • 해결: P1A = 별도 reverse proxy가 인증 / BFF = application backend 자체가 OAuth client — documented-only

묶음

본 sub-sub-branch 는 leaf — 자식 자료 없음. Phase 3 P3A 실 구현 또는 외부 산출물 단계에서 errors / interview prep / lectures 가 누적되면 본 섹션에서 그룹화.

오류 기록 (이 sub-sub-branch 작업 중 발생)

  • (없음 — 현재 documented-only 단계)

면접 준비 (이 작업에서 나올 수 있는 면접 질문)

  • (없음 — Phase 3 실 구현 단계에 누적)

관련 일일 노트

완료 후 정리

머지/종료 시점에 채움. /ingest가 이 섹션을 기준으로 wiki/projects/에 추출.

  • PR 링크: (미구현 — 문서까지만)
  • 리뷰 메모:
  • 머지 결과 / 배포 환경: 없음 (P2A는 documented-only 범위)
  • wiki 추출 대상: 현 단계 없음. 6 패턴 + BFF 매트릭스 완성 후 wiki/concepts/bff-vs-spa-direct.md 합성 후보.
  • 추출하지 않을 항목: BFF 자체 구현 없음. SPA Direct도 P2A 구현 없음. documented-only 유지.