본문 바로가기
인증 · 보안

Keycloak으로 SSO 구축한 이야기

코딩패트릭 2026. 7. 18.

회사에는 서비스가 여러 개 있었고, 각 서비스마다 회원 정보와 로그인이 따로 놀고 있었다. 같은 사람이 서비스마다 다른 계정을 만들고, 서비스를 옮길 때마다 다시 로그인하는 상황이었다. 이걸 하나의 통합 인증 체계로 묶는 일을 맡게 되면서, 어떤 기술을 골랐고 왜 그렇게 정했는지를 정리해 두려고 한다.

이 글은 앞 글(구글·카카오 로그인은 실제로 어떻게 동작할까)에서 다룬 OIDC와 OAuth 2.0 원리를 이미 안다는 전제로 쓴다. 로그인 흐름이 아직 낯설다면 그 글을 먼저 읽고 오길 권한다. 핵심만 다시 말하면, 소셜 로그인은 인증 전담 서버(IdP)가 세션을 들고 있고, 표준 프로토콜로 신원을 주고받는 구조였다. 이번 글의 주인공인 Keycloak은 그 "인증 전담 서버"를 우리가 직접 운영하는 버전이다.

왜 통합 인증이 필요했나 — 문제와 요구조건

흩어진 로그인이 만든 문제

먼저 어떤 문제를 풀어야 했는지부터 정리한다. 우리 서비스는 기업 고객을 대상으로 하는 B2B 서비스이고, 서로 다른 세 개의 서비스를 운영하고 있었다. 문제는 이 세 서비스의 회원 체계가 완전히 따로 놀았다는 점이다. 같은 회사가 세 서비스를 모두 쓰고 싶어도, 서비스마다 따로 회원가입을 해야 했고 계정 정보도 각각 따로 들고 있어야 했다. 회사 정보는 똑같은데, 그 정보가 서비스 수만큼 복제돼 각자 관리되는 셈이었다.

사실 플랫폼을 운영하는 입장에서 이 구조 자체가 크게 어려운 건 아니었다. 각 서비스가 자기 회원만 관리하면 되니, 관리 난이도만 놓고 보면 그럭저럭 돌아갔다. 진짜 문제는 사용자 경험이었다. B2B에서는 한 회사가 우리 서비스 여러 개를 함께 도입하는 경우가 많은데, 그때마다 같은 담당자가 서비스별로 새로 가입하고 계정을 따로 관리해야 했다. 같은 회사, 같은 사람인데 서비스를 옮길 때마다 남남처럼 처음부터 다시 시작해야 하니 불편할 수밖에 없었다.

여기에 하나 더, 정보가 흩어져 있다는 게 계속 걸렸다. 같은 회사의 정보가 세 서비스에 각각 저장돼 있으니, 한쪽에서 회사 정보가 바뀌면 나머지와 어긋났다. 이걸 맞추려면 서비스 사이에 정보를 계속 동기화해 줘야 했는데, 이 동기화 부담이 은근히 컸다. 결국 흩어진 계정과 정보를 하나로 모으는 게 답이었다. 세 서비스의 회원을 하나의 기준으로 관리하는 통합 계정센터를 만들고, 그동안 플랫폼마다 따로 흩어져 있던 정보를 그쪽으로 이관하는 것. 이 과업을 맡게 되면서 통합 인증 작업이 시작됐다.

세 가지 요구조건

이 상황을 정리하기 위한 요구조건은 크게 세 가지였다.

첫째, 여러 플랫폼 환경에서 한 곳에서 로그인하면 다른 곳에서도 자동으로 로그인되어야 했다. 예를 들어 사용자가 service-a.com에서 로그인하면, service-b.comservice-c.com에서는 다시 로그인 화면을 보지 않고 바로 들어가지는 것이다. 이게 바로 앞 글에서 다룬 SSO다. 각 서비스가 각자 로그인을 관리하는 대신, 인증을 한 곳에 모아야 가능하다.

둘째, 그동안 서비스마다 따로 관리되던 회원 정보를 하나의 통합 회원관리 시스템으로 이관해야 했다. 같은 사람이 서비스마다 계정이 흩어져 있으면 관리도 어렵고, 탈퇴나 정보 수정 같은 요청을 처리하기도 번거롭다. 회원의 원장을 한 곳으로 모아, 한 사람은 하나의 계정으로 관리되도록 만드는 작업이 필요했다. 다만 기존 회원을 옮기는 이관 작업은 조심스러운데, 이미 쓰던 사람들의 로그인이 끊기면 안 되기 때문이다. 그래서 통합 계정 체계로 옮기되 기존 사용자의 접속은 유지되도록 설계해야 했다.

셋째, ISMS와 ISMS-P 같은 정보보호 인증 취득을 염두에 둔 설계여야 했다. 이 인증들은 접근 통제, 계정 관리, 로그 기록 같은 항목을 꼼꼼히 본다. 누가 언제 로그인했는지, 권한이 어떻게 부여됐는지, 이상 접근을 어떻게 막는지를 증빙해야 한다. 로그인과 계정 관리가 서비스마다 제각각이면 이런 항목을 하나하나 증빙하기가 어렵다. 반대로 인증 체계를 한 곳으로 모으고, 접근 기록과 세션 관리를 일관되게 남길 수 있으면 심사 대응이 한결 수월해진다.

세 가지 중에서도 첫 번째, 자동 로그인은 사용자 경험에 직접 와닿는 부분이었다. 지금까지는 사용자가 우리 서비스 A에서 B로 넘어갈 때마다 다시 로그인해야 했다. 같은 회사의 서비스인데도 매번 아이디와 비밀번호를 요구하니, 사용자 입장에서는 남남처럼 느껴졌을 것이다. 통합 인증을 붙이면 한 번 로그인한 뒤로는 서비스 사이를 자유롭게 오갈 수 있다. 작은 차이 같지만, 여러 서비스를 함께 쓰는 사용자일수록 이 편의가 크게 다가온다. 결국 세 가지 요구조건은 "인증을 한 곳으로 모은다"는 하나의 방향으로 수렴했다. 인증이 흩어져 있어서 생기던 문제들이었으니, 모으면 자연스럽게 풀리는 구조였다.

이 세 가지를 종합하면 결론은 하나였다. 인증을 전담하는 중앙 서버를 두고, 회원 정보를 그쪽으로 모으고, 접근과 세션을 일관되게 관리하는 구조. 그게 우리가 만들어야 할 그림이었다. 이제 그 중앙 서버를 무엇으로 세울지 고를 차례였다.

SSO 솔루션 비교와 Keycloak 선택

SSO를 지원하는 대표적인 오픈소스 솔루션을 놓고, 우리 환경에 맞는 걸 골랐다. 후보는 Keycloak, CAS, Identity Server, 그리고 처음부터 직접 구현하는 방법까지 넷이었다. 비교표로 먼저 보자.

비교 항목 Keycloak CAS Identity Server 직접 구현
레퍼런스 풍부도 매우 풍부 (Red Hat 후원, 글로벌 커뮤니티) 보통 (학술 기관 중심) 보통 (.NET 생태계 중심) 없음
커스터마이징 유연성 SPI 기반 확장 구조로 매우 유연 제한적 프레임워크 종속적 완전 자유 (단, 전부 직접 구현)
JWT / 세션 만료 관리 내장 지원, 관리 콘솔에서 설정 지원 지원 직접 구현 필요
강제 로그아웃 (세션 강제 만료) 내장 지원 부분 지원 부분 지원 직접 구현 필요
로깅 / 감사 추적 강력한 내장 로깅 (관리자·사용자 이벤트) 기본 수준 기본 수준 직접 구현 필요
ISMS / ISMS-P 대응 접근통제·감사 증빙에 유리 레퍼런스 부족 레퍼런스 부족 자체 증빙 필요
OIDC / OAuth 2.0 표준 완전 지원 CAS 프로토콜 중심, OIDC 부분 지원 지원 직접 구현 필요
채택 여부 ✅ 채택 미채택 미채택 미채택

표만 보면 결론이 이미 나 있는 것 같지만, 각 후보를 왜 이렇게 봤는지 하나씩 짚어 보자.

CAS·Identity Server·직접 구현을 접은 이유

CAS는 오래된 SSO 솔루션이다. 대학이나 학술 기관에서 많이 쓰여 왔고 안정적이다. 다만 CAS 고유의 프로토콜을 중심으로 발전해 와서, 우리가 표준으로 쓰려는 OIDC 지원은 상대적으로 덜 무르익어 있었다. 자료도 학술 환경 사례가 많아, 우리 같은 일반 서비스 환경에 바로 참고할 게 적었다.

Identity Server는 .NET 생태계에서 널리 쓰이는 솔루션이다. 기능은 충분하지만 .NET 프레임워크에 밀접하게 묶여 있다. 우리 백엔드 환경과 결이 맞지 않았고, 라이선스 정책이 바뀐 이력도 있어 장기적으로 부담이 될 수 있다고 봤다.

직접 구현은 자유도가 100%다. 원하는 대로 다 만들 수 있다. 하지만 그 말은 뒤집으면, 표에 나온 모든 기능을 우리가 다 만들어야 한다는 뜻이다. 토큰 만료 관리, 강제 로그아웃, 감사 로깅, 통합 로그아웃까지 전부 직접 짜고, 보안 검증도 스스로 책임져야 한다. 인증은 한 번 잘못 만들면 사고가 크게 나는 영역이라, 검증된 도구가 있는데 처음부터 짜는 건 위험도 크고 품도 크다고 판단했다.

그래서 Keycloak을 골랐다

이렇게 후보를 하나씩 지워 나가니 Keycloak이 남았다. 택한 이유를 네 가지로 추리면 이렇다.

첫째, 오픈소스 SSO 솔루션 중에서 레퍼런스와 커뮤니티가 가장 두텁다. Keycloak은 Red Hat이 뒤를 받치고 있고 글로벌 커뮤니티가 크다. 도입 초기에 막히는 지점이 많은데, 문제를 검색하면 대부분 누군가 먼저 겪은 흔적이 나온다. 참고할 자료가 많다는 건 그 자체로 큰 힘이다.

둘째, SPI 기반 확장 구조 덕분에 커스터마이징에 가장 열려 있다. SPI는 Service Provider Interface의 약자로, Keycloak이 정해 둔 자리에 우리가 만든 코드를 끼워 넣을 수 있게 해 주는 확장 구조다. 예를 들어 로그인할 때 우리만의 추가 검증을 넣거나, 로그인·로그아웃 같은 이벤트가 일어날 때 우리 시스템에 기록을 남기는 리스너를 붙일 수 있다. 통합 회원 시스템처럼 우리만의 규칙이 필요한 상황에서 이 유연함이 중요했다.

셋째, 직접 구현하면 공수가 많이 드는 기능들을 내장으로 제공한다. 토큰과 세션 만료 시간은 관리 콘솔에서 값만 바꾸면 되고, 특정 사용자의 세션을 강제로 끊는 것도 화면에서 버튼 하나로 된다. 누가 언제 로그인했고 관리자가 무엇을 바꿨는지도 이벤트 로그로 남는다. 이걸 직접 만들 시간에 서비스 통합 자체에 집중하는 편이 낫다고 봤다.

넷째, 정보보호 인증 대응에 유리하다. ISMS·ISMS-P 심사는 접근 통제와 감사 기록을 중요하게 보는데, Keycloak처럼 검증된 인증 솔루션을 쓰면 그 근거를 만들기가 쉽다. 특히 비밀 값 관리 측면에서 이점이 있다. 앞 글에서 이야기한 client_secret처럼, 인증에 쓰이는 비밀 키를 서비스 코드 곳곳에 흩뿌리지 않고 인증 서버 한 곳에 캡슐화해서 관리할 수 있다. 다만 오해하면 안 되는 게 있다. ISMS·ISMS-P 심사는 특정 제품을 쓰는지가 아니라, 운영을 제대로 하고 있는지를 본다. 즉 "Keycloak을 썼으니 통과"가 아니라 "접근 통제와 로그 관리를 일관되게 하고 있음"을 증빙해야 한다. Keycloak은 그 인증을 대신 따 주는 게 아니라, 증빙을 만들기 쉬운 환경을 제공해 주는 도구라고 이해하는 편이 정확하다.

Keycloak은 내가 운영하는 구글 — 소셜 로그인과 같은 원리

구글이 하던 일을 그대로 한다

여기서 앞 글의 내용이 그대로 연결된다. 소셜 로그인에서 구글이 하던 역할을 다시 떠올려 보자.

  • 사용자를 인증한다 (로그인 화면을 띄우고 아이디·비밀번호를 검증한다)
  • 인가 코드를 발급한다
  • 코드를 토큰(Access Token + ID Token)으로 바꿔 준다
  • Access Token으로 물어보면 사용자 정보를 알려 준다

Keycloak은 이 구글의 역할을 그대로 한다. 다른 점은 딱 하나, 남의 서버가 아니라 우리가 직접 운영하는 IdP라는 것이다. 그래서 우리 회원 정보를 우리 규칙대로 관리할 수 있다. Keycloak에서는 이렇게 인증 세계를 하나 만들어 두는 단위를 렘(realm)이라고 부르고, 그 안에 서비스별로 접속 정보를 등록하는 단위를 클라이언트(client)라고 부른다. 렘을 어떻게 나눌지는 상황에 따라 다르다. 서비스마다 렘을 따로 두는 구조도 있고, 렘 하나에 여러 서비스를 몰아넣는 구조도 있다. 우리는 회원을 하나로 통합하는 게 목적이었으니, 렘 하나 안에 service-a, service-b, service-c를 각각 클라이언트로 등록하는 구조를 선택했다. 이렇게 해야 세 서비스가 같은 회원 풀과 같은 로그인 세션을 공유하기 때문이다.

동작 원리는 앞 글과 완전히 똑같다. Keycloak도 로그인이 끝나면 ID Token을 발급하고, 그 ID Token으로 사용자를 식별한다. 구글 로그인을 이해했다면 Keycloak SSO도 이미 이해한 셈이다. 프로토콜이 같은 OIDC와 OAuth 2.0이기 때문이다. 실제로 나도 소셜 로그인 흐름을 먼저 정리해 두고 나니, Keycloak 문서가 훨씬 빨리 읽혔다.

ID Token과 Access Token, 역할이 다르다

본격적인 이야기에 앞서 두 토큰의 역할을 한 번 더 못 박아 두자. ID Token은 "로그인한 사용자가 누구인지"를 확인하는 신분증(로그인 처리용)이고, Access Token은 "API에 접근할 권한"을 나타내는 출입증(자원 접근용)이다. 이 구분을 잡고 있어야 아래 이야기가 헷갈리지 않는다.

매 요청마다 사용자를 확인하는 두 방식

이제 실무적인 차이를 짚어 보자. 소셜 로그인과 Keycloak은 "매 요청마다 사용자를 어떻게 확인하느냐"에서 갈린다. 다만 먼저 오해를 하나 막아 두면, 지금부터 말할 방식은 Keycloak만 특별해서 가능한 게 아니다. JWT 형태의 Access Token을 발급하는 OIDC Provider라면 어디든 같은 방식을 쓸 수 있다. Auth0, Cognito, Okta 같은 다른 솔루션도 마찬가지다. 애초에 이건 특정 제품 기능이 아니라 표준에 가까운 구조다. Keycloak은 그걸 기본으로 잘 지원할 뿐이다.

먼저 소셜 로그인(구글·카카오 등)의 경우를 보자. 로그인 시점에 사용자 정보를 얻는데, 방법은 두 가지다. ID Token 안에 이미 sub, email, name 같은 정보가 들어 있으면 그걸 바로 쓰고, 부족하면 Access Token으로 UserInfo 엔드포인트를 한 번 호출해 받아 온다. 구글도 ID Token에 기본 정보가 들어 있어 UserInfo를 굳이 안 부르는 경우가 많다. 어느 쪽이든, 그 뒤로는 받은 정보를 바탕으로 우리 서비스가 자체 세션이나 토큰을 따로 만들어 쓴다.

[로그인 시] 백엔드 --Access Token--> 구글 UserInfo API --사용자 정보--> 백엔드
                                                              ↓
                                          받은 정보로 자체 세션/토큰 생성

[이후 매 요청] 브라우저 --자체 세션/토큰--> 백엔드 (소셜 플랫폼과 통신 없음)

즉, 로그인 이후에는 구글과 더 이상 통신하지 않고, 우리가 만든 세션으로 사용자를 확인한다. 이 방식은 구현하기 나름이라 팀마다 조금씩 다르다.

Keycloak은 토큰을 스스로 검증한다

반면 JWT 방식은 여기서 한 걸음 더 나아갈 수 있다. Keycloak이 발급하는 Access Token은 그 자체가 JWT라, 안에 이미 iss, sub, aud 같은 사용자 식별 정보가 들어 있다. 그리고 Keycloak은 이 토큰의 서명을 검증할 수 있는 공개 키(Public Key)를 제공한다. 이 공개 키 묶음을 JWKS라고 부른다.

여기서 잠깐, 서명 검증이 왜 필요한지 짚어야 한다. Access Token은 누구나 내용을 열어 볼 수 있는 형식이라, 악의를 가진 사람이 내용을 위조할 수도 있다. 그래서 "이 토큰이 진짜 Keycloak이 발급한 게 맞는지"를 확인해야 하는데, 그 확인에 쓰는 게 바로 공개 키다. Keycloak은 자기만 아는 비밀 키로 토큰에 서명을 찍어 두고, 검증에 쓰는 공개 키는 누구나 받아 갈 수 있게 열어 둔다.

백엔드 서버는 이 공개 키를 받아서 캐싱해 두면, 그 뒤로는 Keycloak에 매번 물어보지 않고도 토큰이 진짜인지 스스로 검증할 수 있다. 다만 "한 번 받고 영원히 쓴다"는 아니다. 인증 서버는 보안을 위해 주기적으로 키를 교체(Key Rotation)하는데, 이때 키에 붙은 식별자인 kid가 바뀐다. 그래서 실무에서는 평소에는 캐싱한 키를 쓰다가, 토큰의 kid가 캐시에 없으면 그때 JWKS를 다시 받아 오도록 만든다. 대부분의 라이브러리가 이 과정을 알아서 처리해 준다.

[최초 1회] 백엔드 --공개 키 요청--> Keycloak JWKS 엔드포인트
                                       ↓
                            공개 키를 캐싱 (이후 네트워크 통신 불필요)

[이후 매 요청] 브라우저 --Access Token--> 백엔드
                                       ↓
                            캐싱된 공개 키로 서명 검증
                                       ↓
                            유효하면 → 토큰 안의 sub, aud로 사용자 식별 후 권한 부여

JWKS 엔드포인트는 이런 모양이고, 응답으로 공개 키 정보를 준다.

GET https://keycloak.example.com/realms/myrealm/protocol/openid-connect/certs
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "abc123",
      "use": "sig",
      "n": "0vx7agoebGc...",
      "e": "AQAB"
    }
  ]
}

세션을 둘 수도, 안 둘 수도 있다

정리하면, Access Token 자체에 사용자 정보가 들어 있고 공개 키로 직접 검증할 수 있으니, 서버에 세션을 따로 두지 않고 토큰만으로 인증하는 방식(Stateless)을 택할 수 있다. 매 요청마다 인증 서버에 물어볼 필요가 없어 통신 비용도 줄고, 서비스가 여러 대로 늘어나도 각자 알아서 토큰을 검증하니 확장에도 유리하다. 물론 이건 선택이다. 세션을 아예 안 만드는 건 아니고, Stateless로 운영하기로 정했을 때 그렇게 할 수 있다는 뜻이다. 예를 들어 Spring Security도 세션을 만들지 않으려면 SessionCreationPolicy.STATELESS처럼 명시적으로 설정해야 하고, 그러지 않으면 세션이 생긴다. 서비스 성격에 따라 세션을 유지하는 편이 나을 때도 있다. 두 방식을 표로 비교하면 차이가 분명해진다.

구분 소셜 로그인 (구글) Keycloak SSO
프로토콜 OIDC + OAuth 2.0 OIDC + OAuth 2.0 (동일)
IdP 역할 구글 Keycloak
인증 방식 구글 계정 Keycloak에 등록된 계정
토큰 발급 Access Token + ID Token Access Token + ID Token (동일)
SSO 범위 서비스별 개별 연동 다중 서비스 통합 (중앙 관리, 통합 로그아웃)
세션 관리 구글이 관리 Keycloak이 관리 (커스터마이징 가능)

마무리 — 도입하며 정리한 것들

프로토콜은 사실 정해져 있다

웹에서 SSO를 만든다면 사실 프로토콜 선택지는 거의 정해져 있다. 대표적인 표준은 SAML 2.0과 OIDC 두 가지인데, SAML은 지금도 기업 내부 시스템에서 꾸준히 쓰이지만 새로 웹이나 모바일 서비스를 만든다면 OIDC와 OAuth 2.0의 Authorization Code Flow가 사실상의 표준이다. 우리가 매일 쓰는 소셜 로그인이 전부 이 방식 위에서 돌아간다. 기존에 SAML로 엮인 시스템이 없다면, 표준인 OIDC로 가면 된다.

프로토콜을 정했다면 그다음은 구현 방식이다. Keycloak은 어디까지나 선택이다. 직접 구현해도 된다. 다만 Keycloak이 기본으로 주는 것들 — 세션 관리, 강제 로그아웃, 감사 로깅, 공개 키(JWKS) 기반 토큰 검증, 통합 로그아웃 — 을 처음부터 만들려면 품이 상당히 든다. 이미 검증된 도구가 있는데 같은 바퀴를 다시 발명할 이유는 없다고 봤다. 물론 규모가 아주 작거나 인증 요구사항이 단순하다면, 무거운 솔루션을 얹는 대신 직접 가볍게 구현하는 편이 나을 수도 있다. 정답이 하나는 아니라는 뜻이다. 우리처럼 여러 서비스를 묶어야 하고 정보보호 인증까지 고려해야 하는 상황에서는, 검증된 솔루션이 주는 안정감이 분명히 컸다.

도입 전 미리 정해 둘 것들

도입하면서 몇 가지는 미리 정해 두는 게 좋다고 느꼈다. 먼저 세션과 토큰의 만료 시간을 얼마로 할지다. 너무 길게 잡으면 편하지만 보안이 느슨해지고, 너무 짧게 잡으면 사용자가 자꾸 로그아웃되어 불편해한다. 서비스 성격에 맞게 균형을 잡아야 한다. 다음으로 쿠키와 도메인 설정이다. SSO는 IdP 도메인의 쿠키에 기대는 구조라, HTTPS 적용과 쿠키 도메인·옵션 설정을 처음부터 정확히 맞춰 두지 않으면 자동 로그인이 엉뚱하게 동작한다. 마지막으로 기존 회원 이관이다. 이미 쓰던 사용자들의 계정을 통합 체계로 옮길 때 로그인이 끊기지 않도록, 이관 절차와 예외 상황을 미리 그려 두는 게 좋다.

잊지 말 위험 — 단일 장애점(SPOF)

한 가지 더, 인증을 한 곳에 모으는 구조에는 그림자도 있다. 그 중앙 서버가 멈추면 연결된 모든 서비스의 로그인이 함께 멈춘다는 점이다. 인증을 몰아 둔 대가로, 그곳이 단일 장애점(SPOF)이 된다. 편의와 관리 일관성을 얻는 대신 감수해야 하는 위험이다. 그래서 실제 운영에서는 인증 서버를 여러 대로 이중화해 한 대가 죽어도 서비스가 이어지도록 하고, 상태를 지켜보는 모니터링과 장애 알림을 함께 갖춰 두는 게 좋다. 통합 인증은 잘 붙이면 편하지만, "여기가 멈추면 전부 멈춘다"는 점을 처음부터 염두에 두고 설계해야 한다는 뜻이다.

학습 곡선, 그리고 해보고 느낀 것

Keycloak의 학습 곡선이 부담스러울 수 있다. 나도 처음엔 그랬다. 관리 콘솔의 설정 항목이 많고, 렘·클라이언트·SPI 같은 낯선 용어가 한꺼번에 쏟아진다. 그런데 막상 붙어 보니 생각만큼 높은 벽은 아니었다. 특히 SPI 확장이나 커스터마이징에서 막히는 부분은 Claude 같은 AI의 도움을 받아 학습하고 적용했다. 공식 문서와 예제를 같이 놓고 물어 가며 진행하니, 실무에 쓸 수 있는 수준까지 커스터마이징할 수 있었다.

직접 도입해 보고 나서 가장 크게 느낀 건, 처음의 막막함에 비해 결과가 깔끔했다는 점이다. 흩어져 있던 세 서비스의 로그인이 한 곳으로 모이니, 계정 관리도 접속 기록도 한 화면에서 볼 수 있게 됐다. 사용자는 한 번 로그인으로 서비스를 오가고, 운영하는 쪽은 정책을 한 곳에서 관리한다. 앞에서 걱정한 단일 장애점 같은 위험은 이중화와 모니터링으로 관리하면 되는 문제이지, 통합 자체를 포기할 이유는 아니었다.

이 글 하나로 SSO 구현의 모든 걸 담기는 어렵다. 세부 설정이나 SPI 코드까지 들어가면 그것만으로도 글 여러 편 분량이다. 다만 어떤 프로토콜을 골라야 하는지, 기술 스택은 어떻게 정하면 되는지, 그리고 전체 방향을 잡는 데 작은 이정표가 되었으면 한다. 결국 핵심은 하나다. 소셜 로그인의 원리를 이해하면 Keycloak SSO의 원리도 이해한 것이고, 나머지는 그 위에서 우리 상황에 맞게 다듬는 일이다. 그리고 이 원리는 Keycloak에만 묶여 있지 않다. 프로토콜(OIDC + OAuth 2.0)을 이해해 두면 제품이 Keycloak이든 Auth0든 Cognito든 바뀌어도 원리는 거의 같다. 도구는 갈아 끼울 수 있지만 원리는 남는다. 이 두 편의 글이 그 원리의 첫 단추를 끼우는 데 도움이 되었으면 한다.

 

이 글에서 Keycloak의 강점으로 SPI(Service Provider Interface)를 몇 번 언급했지만, 정작 그게 뭔지는 다루지 못했다. 사실 우리 요구사항을 실제로 맞춰 준 건 대부분 이 SPI 커스터마이징이었다. 다음 글에서는 SPI가 무엇이고 어떻게 직접 만드는지를 예제와 함께 정리해 보려 한다.