Skip to content

필사 모드: Keycloak로 SSO 구축하기 — Realm·Client·플로우부터 2026 신기능까지

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

들어가며 — 로그인은 왜 직접 만들면 안 되는가

사내 앱이 20개라고 합시다. 각각에 회원가입·비밀번호 재설정·2FA·소셜 로그인·세션 관리를 따로 구현하면, 보안 구멍이 20배가 됩니다. SSO(Single Sign-On)의 아이디어는 단순합니다 — 로그인이라는 일을 전담하는 서버를 하나 두고, 모든 앱이 그 서버에 "이 사람 누구야?"를 위임하는 것입니다. 사용자는 한 번 로그인하면 20개 앱을 다 쓰고, 앱들은 비밀번호를 아예 만지지 않습니다.

Keycloak은 이 아이덴티티 서버의 오픈소스 표준입니다(현재 CNCF 인큐베이팅 프로젝트, Red Hat build of Keycloak의 업스트림). OIDC와 SAML을 모두 말하고, 소셜 로그인 브로커링·LDAP 연동·2FA·WebAuthn을 기본 제공합니다. 이 글은 Keycloak을 4개의 핵심 개념으로 이해하고, 로그인 흐름을 한 단계씩 따라간 뒤, 배포의 함정과 2026년 신기능까지 정리합니다. 인증 흐름 자체가 낯설다면 인증 플로우 시각화 도구를 먼저 만져 보면 이 글이 훨씬 쉬워집니다.

1부 — 4개의 핵심 개념으로 보는 Keycloak

Keycloak의 관리 콘솔은 메뉴가 수십 개지만, 뼈대는 네 개입니다.

개념                역할                                    비유
─────────────────  ──────────────────────────────────────  ──────────────────
Realm              완전히 격리된 테넌트 (자체 유저·설정)    하나의 "왕국"
Client             인증을 위임받는 애플리케이션             왕국의 "출입증 발급 대상"
Role / Group       권한과 사용자 묶음                       "직책"과 "부서"
Identity Provider  외부 로그인 소스 (구글·상위 OIDC/SAML)   "다른 왕국의 여권 인정"
  • Realm(렐름) 은 격리 경계입니다. Realm 하나에는 자체 사용자·클라이언트·역할·로그인 설정이 들어 있고, 다른 Realm과 완전히 분리됩니다. 관리자 계정이 사는 master Realm은 오직 Keycloak 자체를 관리하는 용도로만 쓰고, 실제 서비스는 별도 Realm을 새로 파는 것이 정석입니다. "고객사별로 사용자를 나누고 싶다"면 처음 떠오르는 답이 Realm이지만 — 뒤에서 볼 Organizations가 더 나은 경우가 많습니다.
  • Client(클라이언트) 는 "인증을 위임받는 앱"입니다. 브라우저에서 도는 SPA는 시크릿을 숨길 수 없으니 public 클라이언트(+PKCE 필수), 백엔드 서버는 시크릿을 지킬 수 있으니 confidential 클라이언트입니다. 각 클라이언트는 프로토콜(OIDC 또는 SAML), 허용된 redirect URI, 토큰 수명 등을 자기 설정으로 가집니다.
  • Role / Group 은 권한 모델입니다. Role은 "직책"(admin, editor), Group은 "부서"(사용자 묶음 + 공통 역할·속성)입니다. 역할을 다른 역할에 포함하는 composite role로 계층도 만들 수 있습니다. 원칙: 역할은 앱이 이해하는 권한, 그룹은 사람을 조직하는 방법으로 나눠 생각하세요.
  • Identity Provider(IdP) 는 "외부 로그인 소스"입니다. 구글·깃허브 소셜 로그인, 혹은 회사의 상위 OIDC/SAML IdP를 브로커링해서, Keycloak이 그 앞에 서는 중개자가 됩니다. LDAP·Kerberos는 IdP가 아니라 User Federation으로 붙습니다(사용자 저장소를 그대로 읽어 옴).

2부 — OIDC 로그인 흐름 한 단계씩

가장 많이 쓰는 흐름은 Authorization Code + PKCE입니다. SPA가 Keycloak에 로그인을 위임하는 과정을 따라가 봅시다.

① 사용자가 앱의 "로그인" 클릭
   → 앱이 브라우저를 Keycloak authorize 엔드포인트로 리다이렉트
     (client_id, redirect_uri, scope=openid, code_challenge 포함)

② Keycloak이 로그인 화면 표시 → 사용자가 인증 (비밀번호 + OTP 등)
   ※ 이미 Keycloak 세션이 있으면 이 화면을 건너뜀 = SSO의 핵심

③ Keycloak이 redirect_uri로 되돌려보냄 + 일회용 authorization code

④ 앱 백엔드(또는 SPA)가 code + code_verifier를 token 엔드포인트로 교환
   → access_token(JWT) + id_token + refresh_token 수령

⑤ 앱은 access_token을 API 호출 Authorization 헤더에 실어 보냄
   API는 Keycloak의 공개키(JWKS)로 서명만 검증 — 매 요청 Keycloak에 안 물어봄

여기서 세 가지가 핵심입니다. 첫째, PKCE(code_challenge/code_verifier)는 탈취된 authorization code를 무력화합니다 — public 클라이언트라면 필수입니다. 둘째, ②의 "세션이 있으면 건너뜀"이 바로 SSO입니다. 두 번째 앱이 로그인을 위임하면 Keycloak은 이미 브라우저 쿠키로 사용자를 알아보고 로그인 화면 없이 즉시 code를 발급합니다. 셋째, ⑤에서 API는 매 요청 Keycloak을 호출하지 않습니다 — access_token은 서명된 JWT이므로 공개키로 로컬 검증만 하면 됩니다. 이 무상태성이 SSO가 확장되는 이유입니다.

토큰 세 종류의 역할도 헷갈리지 마세요:

id_token       "누가 로그인했는가" — 사용자 정보. 앱(클라이언트)이 소비
access_token   "무엇을 할 수 있는가" — 권한. API(리소스 서버)가 검증
refresh_token  "다시 발급받을 권리" — access_token 만료 시 갱신용, 안전하게 보관

세션·토큰 수명 튜닝은 Realm 설정의 핵심 레버입니다. access_token은 짧게(수 분), refresh_token은 길게(SSO 세션 수명까지) 잡는 것이 표준이며, 짧은 access_token + 로컬 서명 검증의 조합이 "탈취돼도 곧 만료"와 "빠른 검증"을 동시에 줍니다.

3부 — 배포: Quarkus 2단계 모델과 프로덕션 함정

Keycloak 17부터 배포판은 Quarkus 기반입니다(옛 WildFly/JBoss 배포는 제거됨). 여기서 처음 만지는 사람이 가장 많이 걸리는 함정이 build/start 2단계 모델입니다.

# ① 빌드 단계(augmentation): DB 벤더·활성 기능을 "구워 넣는다"
#    — 이 단계는 느리지만 자주 하지 않음
bin/kc.sh build --db=postgres --features=organizations,token-exchange

# ② 실행 단계: 런타임 설정(호스트명·DB 접속·TLS)만 넘김
bin/kc.sh start --optimized \
  --hostname=https://auth.example.com \
  --db-url=jdbc:postgresql://db/keycloak \
  --db-username=keycloak --db-password="$KC_DB_PASSWORD"

# 로컬 개발용은 두 단계를 합쳐 주는 편의 명령
bin/kc.sh start-dev

--optimized 플래그는 "이미 build 했으니 start에서 재빌드하지 마"라는 뜻입니다. 컨테이너 이미지에서는 빌드 단계를 Dockerfile에 넣어 이미지에 구워 두고, 런타임에는 start --optimized만 도는 것이 정석입니다.

프로덕션에서 밟는 대표적인 지뢰 세 가지:

  • hostname v2 — Keycloak 26부터 hostname 설정이 완전히 바뀌었습니다. 이제 --hostname에 호스트명 조각이 아니라 전체 URL(https://auth.example.com)을 주고, 관리 콘솔을 다른 주소로 노출하려면 --hostname-admin을 따로 줍니다. 리버스 프록시 뒤라면 --proxy-headers=xforwarded도 함께. 잘못 설정하면 리다이렉트 URI가 내부 주소로 새어 나가거나 로그인 루프에 빠집니다.
  • 프로덕션 모드는 TLS를 강제start(dev가 아닌)는 HTTPS·hostname·DB가 제대로 없으면 뜨지 않습니다. 프록시가 TLS를 종료한다면 --proxy-headers로 알려 줘야 Keycloak이 자기 외부 주소를 올바로 인식합니다.
  • DB는 곧 상태 전부 — Keycloak 서버 자체는 무상태에 가깝고, 사용자·세션·설정은 전부 외부 DB(Postgres 권장)에 있습니다. 그래서 수평 확장이 쉽지만, DB 백업·마이그레이션이 곧 아이덴티티 백업입니다.

쿠버네티스라면 Keycloak OperatorKeycloak·KeycloakRealmImport CRD로 이 모든 것을 선언형으로 감싸 줍니다. 쿠버네티스 감각이 필요하면 쿠버네티스 놀이터에서 CRD·오퍼레이터 패턴을 먼저 익혀 두면 좋습니다.

4부 — 2026년의 Keycloak: 26.x 신기능

이 글 기준 최신은 26.6.3입니다(내부 Quarkus 3.33.2). 26 계열에서 정식 기능이 된 것들 중 실무 임팩트가 큰 넷:

  • Organizations — 26.0에서 정식 출시된, "멀티테넌시의 정답"입니다. 그동안 "고객사별 격리"는 Realm을 여러 개 파거나 그룹으로 흉내 냈는데, 둘 다 아팠습니다(Realm은 무겁고, 그룹은 격리가 약함). Organizations는 하나의 Realm 안에서 조직별 멤버·도메인·전용 IdP를 두고, 조직 컨텍스트로 로그인하면 그 멤버십이 OIDC 토큰·SAML 어서션에 자동으로 실립니다. 26.x를 거치며 조직별 격리된 그룹 계층과 외부 클레임 기반 자동 그룹 배정(IdP 매퍼)까지 갖췄습니다. "Realm은 서로 완전히 남남인 시스템, Organizations는 같은 시스템 안의 여러 고객" 으로 기억하세요.
  • JWT Authorization Grant (RFC 7523) — 외부에서 서명한 JWT 어서션으로 Keycloak 액세스 토큰을 받는 표준 방식입니다. 기존의 "외부→내부 토큰 교환"을 대체하는 권장 경로로, 서비스 간 신뢰를 표준 프로토콜로 세우게 해 줍니다.
  • Workflows — Realm 관리 작업(예: 비활성 사용자 정리, 특정 이벤트에 따른 후속 조치)을 자동화하는 기능이 정식화됐습니다. 그동안 커스텀 익스텐션이나 외부 크론으로 하던 일이 서버 기능으로 들어온 것.
  • 무중단 패치 릴리스 — 패치 버전 간 롤링 업데이트가 지원되어, 클러스터를 멈추지 않고 보안 패치를 적용할 수 있습니다. 아이덴티티 서버는 "절대 안 죽어야 하는" 인프라라는 점에서 큰 진전입니다.

토큰 교환(token exchange)에는 아직 경계가 있습니다 — 현재 OIDC/OAuth 교환만 지원하고 SAML 기반 클라이언트·IdP 교환은 향후 과제입니다. 그래서 외부 신뢰 수립은 위의 JWT Authorization Grant가 더 표준적인 답입니다.

5부 — 언제 쓰고, 언제 다시 생각할까

Keycloak이 빛나는 곳: 온프레미스·하이브리드에서 데이터 주권이 필요할 때, 프로토콜(OIDC+SAML) 커버리지가 넓어야 할 때, 라이선스 비용 없이 대규모로 확장할 때. 관리형 SaaS(Auth0·Okta·Entra ID)와의 갈림길은 대개 "운영 부담을 질 것인가, 비용·종속을 질 것인가"입니다 — Keycloak은 DB·업그레이드·가용성을 직접 책임지는 대신, 데이터와 커스터마이징의 완전한 통제를 줍니다.

다시 생각할 지점: 아이덴티티 서버는 단일 장애점입니다. 죽으면 20개 앱이 동시에 로그인 불가가 됩니다. 그래서 다중 인스턴스 + 외부 세션 저장(Infinispan/DB) + 무중단 패치가 선택이 아니라 필수입니다. 그리고 토큰·세션 수명, redirect URI 화이트리스트, PKCE 강제 같은 보안 기본기를 놓치면 SSO는 오히려 공격면을 한곳에 모아 주는 꼴이 됩니다. 이 감각은 인증·보안 실습 랩에서 OAuth·OIDC·JWT를 직접 손으로 돌려 보며 다지는 것을 권합니다.

마치며

Keycloak은 결국 "로그인을 한 곳으로 모으는" 인프라입니다. Realm(격리)·Client(앱)·Role/Group(권한)·IdP(외부 연동) 네 개념으로 뼈대를 세우고, Authorization Code + PKCE로 흐름을 이해하고, build/start 2단계 + hostname v2로 배포 함정을 피하고, Organizations로 멀티테넌시를 풀면 — 20개 앱의 로그인이 하나의 잘 지켜지는 문으로 수렴합니다. 오픈소스이면서 표준을 정직하게 따른다는 점이, 10년 넘게 이 프로젝트가 사랑받는 이유입니다.

참고 자료

현재 단락 (1/58)

사내 앱이 20개라고 합시다. 각각에 회원가입·비밀번호 재설정·2FA·소셜 로그인·세션 관리를 따로 구현하면, 보안 구멍이 20배가 됩니다. SSO(Single Sign-On)의 ...

작성 글자: 0원문 글자: 6,166작성 단락: 0/58