Keycloak 서버 이관 작업 정리: 사전 점검, DB 이관, 검증, 롤백 체크리스트 (Keycloak 26.x 기준)

2026.11 · Keycloak 26.x 기준 이관 체크리스트
Keycloak 서버 이관 작업 정리: 사전 점검부터 DB 이관, 검증, 롤백까지
Keycloak은 회사의 모든 서비스 로그인이 걸려 있는 인증 서버라서, 이관 중에 작은 설정 하나만 틀어져도 모든 앱의 로그인이 동시에 깨질 수 있습니다. 서버(VM, 클라우드, 쿠버네티스)를 옮길 때 해야 할 작업을 순서대로 정리했습니다. 2026년 10월 기준 최신인 Keycloak 26.8 문서를 기준으로 했습니다.
핵심 원칙 3가지
1. issuer(호스트명)와 서명 키를 그대로 유지하면 연동된 앱들은 이관을 알아채지 못합니다. 둘 중 하나라도 바뀌면 모든 클라이언트 설정과 토큰 검증이 영향을 받습니다.
2. DB 백업·복원이 기본이고 realm export/import는 보조 수단입니다. export에는 이벤트, 세션, 폐기된 토큰이 들어가지 않습니다.
3. 이관과 버전 업그레이드를 한 번에 하지 마세요. 같은 버전으로 먼저 옮기고, 안정화된 뒤 업그레이드하면 문제가 생겨도 원인을 좁히기 쉽습니다.
1. 이관 유형부터 정하기
| 유형 | 예시 | 권장 방식 | 난이도 |
|---|---|---|---|
| A. 인프라만 이동 | VM → 새 VM, 온프레미스 → 클라우드, VM → 쿠버네티스 | 같은 버전 + DB 백업·복원 + 같은 호스트명 | 낮음 |
| B. 이관 + 버전 업그레이드 | 22.x VM → 26.8 컨테이너 | A로 먼저 옮긴 뒤 업그레이드(또는 스테이징에서 충분히 리허설) | 중간 |
| C. DB 엔진 변경 | MySQL → PostgreSQL, H2 → 실제 DB | kc.sh export/import (덤프 이식 불가) | 높음 |
| D. 호스트명 변경 | sso.old.com → auth.new.com | 가능하면 피하기. 불가피하면 모든 클라이언트·IdP 재설정 계획 필요 | 높음 |
※ WildFly 기반 구버전(Keycloak 16 이하, standalone.xml 사용)이라면 Quarkus 기반 배포판으로 설정 방식이 완전히 바뀌므로 B 유형보다 더 큰 작업으로 봐야 합니다.
2. 사전 인벤토리: 무엇을 옮겨야 하는지 목록 만들기
| 항목 | 확인할 내용 |
|---|---|
| 버전·실행 방식 | 정확한 버전, 배포 형태(zip, Docker, Operator), 실행 옵션과 환경변수 전체 |
| 설정 파일 | conf/keycloak.conf, 수정했다면 cache-ispn.xml, JVM 옵션(JAVA_OPTS) |
| 데이터베이스 | 종류·버전, 크기, 접속 계정 권한, 백업 방식, 문자셋/콜레이션 |
| 커스텀 자산 | providers/의 SPI JAR, themes/의 커스텀 테마, 이벤트 리스너 |
| 네트워크 | 호스트명, TLS 인증서·키스토어, 리버스 프록시/LB 설정, 방화벽, 관리 콘솔 접근 제한 |
| 외부 연동 | LDAP/AD 사용자 연동(새 서버에서 접속 가능한지), 외부 IdP(Google, Azure AD, SAML), SMTP |
| 클라이언트 | Realm별 클라이언트 목록, Redirect URI, Web Origins, 서비스 계정, SAML SP 인증서 |
| 규모 | Realm 수, 사용자 수, 활성 세션 수, 피크 시간대 TPS (점검 시간대 정하기) |
# 현재 버전과 실제 적용된 설정 확인 (구 서버)
bin/kc.sh --version
bin/kc.sh show-config
# 커스텀 자산 목록
ls -l providers/ themes/
cat conf/keycloak.conf
# 각 realm의 issuer 값 기록 (이관 후 똑같아야 함)
curl -s https://auth.example.com/realms/myrealm/.well-known/openid-configuration | jq -r .issuer
3. 데이터 이관 방식: DB 백업·복원 vs realm export
| 구분 | DB 백업·복원 | kc.sh export / import |
|---|---|---|
| 옮겨지는 것 | 전부(설정, 사용자, 비밀번호 해시, 키, 세션, 이벤트) | Realm 설정, 클라이언트, 역할, 그룹, 사용자·자격증명 |
| 빠지는 것 | 없음 | 사용자·관리자 이벤트, 저장된 세션, 워크플로 상태, 폐기된 토큰 |
| 사용자 영향 | 세션 유지 가능(26.x는 세션이 DB에 저장) | 모두 재로그인 |
| 언제 쓰나 | 같은 DB 엔진으로 이관(대부분의 경우) | DB 엔진 변경, 일부 realm만 분리, 정리 후 새 출발 |
| 주의 | 구·신 서버 버전이 같아야 안전 | 모든 노드를 멈춘 상태에서 실행해야 일관성 보장 |
※ 관리 콘솔의 Partial export는 비밀번호·클라이언트 시크릿이 *로 가려지고 사용자도 빠지므로 서버 간 이관용으로 쓰면 안 됩니다(공식 문서).
4. 새 서버 구성
새 서버는 구 서버와 같은 버전으로, 같은 provider·theme을 넣어 빌드합니다. 아래는 리버스 프록시(LB)에서 TLS를 종료하는 구성 예시입니다.
# conf/keycloak.conf (예시)
db=postgres
db-url=jdbc:postgresql://new-db.internal:5432/keycloak
db-username=keycloak
# db-password는 환경변수 KC_DB_PASSWORD 또는 시크릿으로 주입
# 호스트명: 구 서버와 동일하게 (hostname v2 방식, 전체 URL)
hostname=https://auth.example.com
# 관리 콘솔을 별도 내부 주소로 분리하는 경우
# hostname-admin=https://auth-admin.internal.example.com
# LB가 TLS 종료 + X-Forwarded-* 헤더 전달
proxy-headers=xforwarded
http-enabled=true
health-enabled=true
metrics-enabled=true
# Dockerfile 예시: 구 서버와 같은 버전 태그로 고정
FROM quay.io/keycloak/keycloak:26.8.1 AS builder
ENV KC_DB=postgres KC_HEALTH_ENABLED=true KC_METRICS_ENABLED=true
COPY providers/ /opt/keycloak/providers/
COPY themes/ /opt/keycloak/themes/
RUN /opt/keycloak/bin/kc.sh build
FROM quay.io/keycloak/keycloak:26.8.1
COPY --from=builder /opt/keycloak/ /opt/keycloak/
ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start", "--optimized"]
- hostname v1 옵션은 26에서 제거됐습니다. 구 서버가
hostname-strict-https,proxy=edge같은 옛 옵션을 쓰고 있다면 새 서버에서는 v2 옵션(hostname,proxy-headers)으로 바꿔야 합니다. - LB는
X-Forwarded-For/Proto/Host를 정확히 넘겨야 합니다. 틀리면 리다이렉트가 http로 가거나 "Invalid redirect uri" 오류가 납니다. - 여러 노드로 클러스터링한다면 노드 간 캐시 통신(포트·디스커버리)이 새 네트워크에서 열려 있는지 확인하세요.
- LDAP/AD, SMTP, 외부 IdP로 나가는 아웃바운드 방화벽과, 이들 쪽의 IP 허용 목록에 새 서버 IP를 미리 등록하세요.
5. 리허설: 운영 데이터 복사본으로 스테이징에서 먼저
새 서버 인프라에 운영 DB 백업을 복원해서 한 번 전체 절차를 돌려봅니다. 걸리는 시간이 실제 점검 시간의 기준이 됩니다. 새 서버 호스트명을 임시로 테스트하려면 테스트 PC의 /etc/hosts에서 운영 도메인을 새 서버 IP로 지정하는 방법이 간단합니다(같은 issuer로 테스트 가능).
6. 컷오버 당일 절차 (유형 A 기준)
D-2 ~ D-1: DNS TTL을 60~300초로 낮추고, 관리자 변경 작업 동결(realm·클라이언트 설정 수정 금지)을 공지합니다.
① 구 서버 중지 → ② DB 백업
# 모든 구 노드 중지 후 백업 (쓰기가 없어야 일관된 덤프)
systemctl stop keycloak # 또는 docker compose stop / kubectl scale --replicas=0
# PostgreSQL
pg_dump -Fc -h old-db -U keycloak -d keycloak -f keycloak-$(date +%Y%m%d%H%M).dump
# MySQL / MariaDB
mysqldump --single-transaction --routines -h old-db -u keycloak -p keycloak > keycloak.sql
③ 새 DB에 복원
# PostgreSQL: 빈 DB 생성 후 복원
createdb -h new-db -U postgres -O keycloak keycloak
pg_restore -h new-db -U keycloak -d keycloak --no-owner --no-privileges keycloak-*.dump
# 테이블 수·사용자 수가 구 DB와 같은지 비교
psql -h new-db -U keycloak -d keycloak -c "select count(*) from user_entity;"
④ 새 서버 기동 → 헬스체크
# 관리 포트(9000)의 readiness 확인
curl --head -fsS http://localhost:9000/health/ready
# issuer와 JWKS(서명 키)가 구 서버 값과 같은지 확인
curl -s https://auth.example.com/realms/myrealm/.well-known/openid-configuration | jq -r .issuer
curl -s https://auth.example.com/realms/myrealm/protocol/openid-connect/certs | jq -r '.keys[].kid'
⑤ DNS 또는 LB 대상 전환 → ⑥ 기능 검증 → ⑦ 모니터링
# DNS가 새 IP를 가리키는지
dig +short auth.example.com
# 서비스 계정으로 토큰 발급이 되는지 (client_credentials)
curl -s -X POST https://auth.example.com/realms/myrealm/protocol/openid-connect/token \
-d grant_type=client_credentials -d client_id=my-service -d client_secret=$SECRET | jq -r .access_token | cut -c1-40
7. 검증 체크리스트
| 영역 | 확인 항목 |
|---|---|
| 로그인 흐름 | 비밀번호 로그인, OTP/패스키, 회원가입, 비밀번호 재설정 메일, 로그아웃 |
| 토큰 | issuer 동일, kid 동일, 리프레시 토큰 갱신, 커스텀 클레임·매퍼 유지 |
| 앱 연동 | 주요 앱(SPA, 백엔드, 모바일) 로그인과 API 호출, 리소스 서버의 JWT 검증 |
| 외부 연동 | LDAP 동기화·로그인, 소셜/기업 IdP 로그인, SAML SP 로그인·로그아웃 |
| 관리 | 관리 콘솔 접속, Admin REST API, 이벤트 기록, 메트릭 수집 |
| 화면 | 커스텀 로그인 테마, 다국어 메시지, 이메일 템플릿 |
8. 호스트명이 바뀌는 경우 추가로 해야 할 일
토큰의 iss가 바뀌기 때문에 영향이 큽니다. 가능하면 기존 도메인을 새 서버로 돌리는 방식을 쓰고, 불가피하다면 아래를 모두 챙겨야 합니다.
- 모든 OIDC 클라이언트의 discovery/issuer URL, 리소스 서버의
issuer-uri·jwk-set-uri변경 - 클라이언트의 Valid Redirect URIs, Web Origins, Post Logout Redirect URIs 재점검
- 외부 IdP 콘솔(Google, Azure AD 등)에 등록된 브로커 콜백 주소
/realms/{realm}/broker/{alias}/endpoint변경 - SAML SP에 새 IdP 메타데이터 배포(Entity ID·SSO URL 변경)
- 기존 쿠키는 도메인이 달라 무효가 되므로 모든 사용자 재로그인 공지
- 구 도메인은 한동안 새 도메인으로 301 리다이렉트 유지
9. DB 엔진을 바꾸거나 일부 realm만 옮기는 경우 (export/import)
# 구 서버: 모든 노드 중지 후, realm별 디렉터리로 내보내기 (사용자 많으면 --dir 권장)
bin/kc.sh export --dir /backup/kc-export --users different_files --users-per-file 500
# 특정 realm만
bin/kc.sh export --dir /backup/kc-export --realm myrealm
# 새 서버: 기동 전 가져오기 (파일명 규칙 <realm>-realm.json, <realm>-users-N.json 유지)
bin/kc.sh import --dir /backup/kc-export --override false
- 사용자가 5만 명이 넘으면 단일 파일 대신 디렉터리로 내보내야 메모리 부족을 피할 수 있습니다.
- 세션·이벤트는 옮겨지지 않으므로 전원 재로그인, 감사 로그는 구 DB를 별도로 보관하세요.
- CLI export에는 realm 키도 포함되지만, 가져온 뒤
kid가 구 서버와 같은지 반드시 비교하세요.
10. 버전 업그레이드까지 하는 경우
- 지나치는 모든 버전의 Upgrading Guide "Migrating to" 항목을 읽습니다. 테마·SPI가 깨지는 경우가 가장 많습니다.
- 스키마는 새 버전이 처음 뜰 때 자동 마이그레이션되며, DB 변경은 되돌릴 수 없으므로 업그레이드 직전 백업이 곧 롤백 수단입니다.
- 데이터가 크면 기본 30분인 트랜잭션 타임아웃을 늘리고, DBA 검토가 필요하면 수동 마이그레이션으로 SQL을 뽑을 수 있습니다.
- 26.0 이전에서 올라오면 영구 사용자 세션(persistent user sessions)이 기본값이 되고, 이를 끄는 설정은 26.8에서 deprecated입니다.
# 롤링 업데이트 가능 여부 판단 (현재 버전에서 메타데이터 생성 → 새 버전에서 검사)
bin/kc.sh update-compatibility metadata --file=/tmp/kc-metadata.json
bin/kc.sh update-compatibility check --file=/tmp/kc-metadata.json; echo $? # 0=롤링 가능, 3=전체 재시작
# 대용량 DB 마이그레이션 타임아웃 늘리기
bin/kc.sh start --transaction-setup-timeout=60m
# DBA 검토용 SQL만 생성
bin/kc.sh start \
--spi-connections-jpa--quarkus--migration-strategy=manual \
--spi-connections-jpa--quarkus--migration-export=/tmp/keycloak-database-update.sql
11. 롤백 계획
- 구 서버와 구 DB는 지우지 말고 일정 기간 그대로 둡니다(중지 상태). 유형 A라면 DNS/LB만 되돌리면 바로 원복됩니다.
- 롤백 판단 기준(예: 30분 안에 로그인 오류 해결 안 되면 원복)과 결정권자를 미리 정해 둡니다.
- 새 서버에서 생긴 데이터(신규 가입, 비밀번호 변경)는 롤백 시 사라진다는 점을 공지 문구에 넣습니다.
- realm export는 DB 백업을 대신할 수 없습니다. 롤백용으로는 항상 DB 백업을 기준으로 삼으세요.
12. 일정별 요약
| 시점 | 할 일 |
|---|---|
| D-14 ~ D-7 | 인벤토리, 이관 유형 결정, 새 서버·DB 구성, 방화벽·IP 허용 목록 요청, 연동 앱 담당자 목록 확보 |
| D-7 ~ D-3 | 운영 DB 복사본으로 리허설, 소요 시간 측정, 검증 시나리오 확정, 롤백 기준 확정 |
| D-2 ~ D-1 | DNS TTL 낮추기, 점검 공지, 관리 설정 변경 동결 |
| D-day | 구 서버 중지 → DB 백업 → 복원 → 새 서버 기동 → issuer·kid 확인 → 전환 → 검증 |
| D+1 ~ D+14 | 로그·오류율·응답시간 모니터링, 백업 정책 재설정, 안정화 후 구 서버 폐기, DNS TTL 원복 |
참고 자료
· Keycloak 공식 문서: Importing and exporting realms (keycloak.org/server/importExport)
· Keycloak Upgrading Guide, Release Notes (26.8)
· Keycloak: Checking if rolling updates are possible (update-compatibility)
· Authgear, "Keycloak Upgrade Guide: What Breaks and How to Plan It"(2026.10.23)
※ 명령어와 설정은 예시이므로 환경(배포 방식, DB 종류, 프록시 구성)에 맞게 조정하고 반드시 스테이징에서 먼저 검증하세요.