티스토리 뷰
이전 글들에서 Keycloak이 IAM(Identity and Access Management) 솔루션으로서 제공하는 것에 대해 알아봤습니다.
Keycloak을 확장해 기존 기능을 사용자 요구에 맞게 변경하거나 신규 기능을 추가해 제한된 설정 이외의 작업을 수행할 수 있습니다. 또한 Keycloak 디자인에 대한 개요와 IAM을 자신의 생태계에 신속하게 배치하는 것뿐만 아니라 IAM을 사용자의 요구에 맞게 빠르게 적용하는 것이 왜 완벽한 선택인지 알아보겠습니다.
1. 서비스 공급자 인터페이스 이해하기
자바 언어에 이미 익숙하다면 서비스 제공자 인터페이스(SPI)를 알고 있을 것입니다. 그렇지 않은 경우 코드베이스를 변경하지 않고 확장 가능한 Java 애플리케이션의 기능을 추가하거나 변경하기 위한 플러그 가능한 매커니즘으로 생각할 수 있습니다.
Keycloak은 잘 정의된 인터페이스 집합을 통해 기능이 구현되는 확장성을 고려해 설계됐습니다. 다양한 인증 메커니즘을 통한 사용자 인증, 감사, ID 데이터를 가져오기 위해 레거시 시스템과의 통합, 클레임을 토큰과 매핑, 신규 사용자 등록 및 프로파일 업데이트 그리고 서드파티 ID 제공자 통합과 같은 기능들은 모두 서비스 인터페이스 집합 및 관련 서비스 제공자 인터페이스를 통해 수행됩니다. 캐싱, 스토리지 또는 Keycloak에서 지원하는 다양한 보안 프로토콜과 같은 핵심 기능 또한
동일한 내용이 적용됩니다.
Keycloak에서 기능은 3개의 주요 인터페이스를 기반으로 정의됩니다.
- Spi
- ProviderFactory
- Provider
자바 용어에 따르면 SPI는 기능의 다양한 구현을 로드하고 설명하기 위한 최상위 인터페이스입니다.
ProviderFactory는 서비스 팩토리 인터페이스이며, 이름에서 알 수 있듯이 특정 구현의 라이프 사이클을 관리하고 Provider 인스턴스를 생성하기 위한 계약을 정의합니다. 팩토리는 또한 다른 제공자 구현과 총돌이 발생하지 않도록 SPI의 범위에서 고유한 식별자를 정의해야합니다.
Provider는 기능을 구현하기 위해 실제 서비스 인터페이스입니다. 기존 기능을 사용자 정의하거나 신규 기능을 추가하기 위해 구현할 기본 인터페이스는 다음과 같습니다.

기능 또는 Spi의 여러 구현을 허용함으로써, Keycloak은 신규 기능을 추가하거나 동작을 변경해 사용자 고유의 구현을 생성하고 개선할 수 있습니다. SPI 및 해당 제공자의 목록을 참조해 이 방법이 실제로 어떻게 적용되는지 알아보겠습니다.
관리자 콘솔에 접속하고 우측 상단의 사용자 아이콘을 클릭합니다. 아이콘을 클릭하면 Realm Info 옵션이 포함된 서브 메뉴가 표시됩니다.

Realm Info 옵션을 클릭하면 서버런타임 정보와 Provider Info탭이 포함된 페이지가 표시됩니다. Provider Info 탭을 클릭합니다.

제공자 리스트를 보면 위에서 제시한 다이어그램의 구현을 명확하게 확인 할 수 있습니다. 예를 들어 리스트 상단 입력 필드에 social을 입력해 소셜 ID 제공자 통합과 관련된 결과만 필터링됩니다.

위 목록에서 볼 수 있듯이 social SPI에는 소셜 ID 제공자에 대해 서로 다른 제공자를 가집니다. required-action, protocol-mapper 등과 같은 다른 SPI에도 동일한 내용이 적용됩니다.
2. 사용자 정의 제공자 패키징
Keycloak은 JAR(Java Archive)로 패키지된 사용자 정의 제공자를 사용합니다. 해당 클래스(ProviderFactory 및 Provider 구현) 외에도 Keycloak이 런타임에 사용자 정의 제공자를 검색하고 초기화할수 있도록 서비스 서술자(Service descriptor) 파일도 포함해야합니다.
서비스 서술자는 JAR파일 내의 META-INF/services 디렉터리에 있는 일반 파일이며 파일 이름은 구현중인 ProviderFactory 유형의 완전한 이름입니다.
가상의 com.acme.MyProvierFactory 팩토리를 예를 들면, 이전 절의 다이어그램 JAR파일은 다음과 같습니다.
: mycustomprovider.jar
META-INF/services/com.acme.MyProviderFactory
MyFirstProviderFactory.class
MyFirstProvider.class
META-INF/services/com.acme.MyProviderFactory 파일에는 com.acme.MyProviderFactory 구현에 대한 참조가 포함돼야 합니다.
3. 사용자 정의 제공자 설치
사용자 정의 제공자를 구현하는 경우 마지막 단계는 Keycloak에 사용자 제공자를 설치하는 것입니다. 해당 작업을 수행하기 위해 다양한 접근 방법을 사용할 수 있습니다.
- JAR 배포
- WildFly 모듈 생성
- JEE(Java Enterprise Edition) EJB(Enterprise JavaBeans) JAR로 배포하기
JAR파일을 서버에 직접 배포하는 것이 사용자 정의 제공자를 설치하는 가장 일반적이고 간단한 방법입니다. JAR파일을 $KC_HOME/standalone/deployments 디렉터리에 복사하면 됩니다.
해당 접근 방식을 사용하는 경우 Keycloak은 공급자를 적절하게 배포하는데 필요한 런타임 종속성을 자동으로 구성합니다.
서버에 모듈을 추가해 사용자 정의 제공자를 배포할 수도 있습니다. 모듈 개념을 잘 모르는 경우 Keycloak은 WildFly 애플리케이션 서버를 사용합니다. 해당 서버는 런타임 종속성을 정의하고, 로드하기 위해 JBoss 모듈을 기반으로 합니다. 해당 모듈은 $KC_HOME/modules 디렉터리에 포함돼 있습니다.
해당 접근 방법을 적용하고자 하는 경우 고려사항은 다음과 같습니다.
- 공통 종속성 집합을 공유하는 여러 제공자를 배포해야 할 때 매우 편리하다. 이 경우 각 종속성에 대한 모듈을 생성해 다른 모듈에서 참조할 수도 있다.
- 프로덕션 환경에서는 잠재적인 보안상의 이유로 배포 스캐너를 사용하지 않도록 설정해 런타임에 예기치 않은 변경을 방지할 수 있다.
- 제공자 클래스 로더 및 해당 종속성에 대한 더 많은 격리 및 제어를 제공한다.
마지막으로 Keycloak에서 제공자를 EJB로 설치할 수 있습니다. 이 방법을 통해 WildFly 및 JEE에서 제공하는 몇몇 주요 기능들을 활용할 수 있습니다. 대부분 Keycloak API 및 SPI에만 사용하는 일반 Java 유형으로 구현되기 떄문에 일반적으로 제공자를 구현하거나 배포하기 위해 해당 방법을 사용하지 않습니다. 하지만 상황에 따라 JPA(Java Persistence API)를 사용해 기존 데이터베이스를 활용하거나 제공자의 JMS(Java Message Service)를 사용할 수 있는데, 이러한 상황이 Keycloak에서 해당 옵션을 지원하는 주요 이유 중 하나입니다.
4. KeycloakSessionFactory 및 KeycloakSession 컴포넌트 이해
Keycloak은 제공자를 관리하기 위해 KeycloakSessionFactory와 KeycloakSession을 사용합니다.
KeycloakSessionFactory는 서버에 설치된 모든 제공자의 레지스트리 역할을 하며 생명 주기 관리를 담당합니다. Keycloak을 실행하면 KeycloakSessionFactory가 생성돼 서버에 설치된 제공자 팩토리를 초기화하고 등록합니다. 반대의 경우도 적용됩니다. Keycloak이 정상적으로 종료 절차를 진행하는 경우 KeycloakSessionFactory는 초기화 단계에서 생성된 리소스를 회수할 수 있는 마지막 기회를 팩토리에 제공합니다.
한편 Keycloak이 실행되고 요청을 처리하는 경우 Keycloak 세션이 생성돼 각 요청에 바인딩됩니다. KeycloakSession은 KeycloakSessionFactory를 기반으로 생성되며 realm,사용자 ,클라이언트, 세션을 관리하고 현재 realm 및 요청에 대한 컨텍스트 정보에 접근하고 제공자 인스턴스를 획득하기 위한 진입점 역할을 합니다.
세션으로부터 획득한 제공자 인스턴스는 한번만 생성되며, KeycloakSesion의 생명주기 동안 캐시됩니다. KeycloakSession은 제공자 개발자가 제공자를 구현할 떄 가장많이 사용하는 구성요소입니다.
5. 제공자의 생명주기 이해
제공자는 초기화(initialization) 및 초기화 해제(Deinitialization)를 수행하기 위해 잘 정의된 생명주기를 갖습니다.
제공자를 설치하는 동안 Keycloak은 기화를 수행하기 위해 ProviderFactory구현의 특정 메서드를 호출합니다. 초기화 단계에서 생성된 리소스를 해제하기 위해 매서드 호출이 수행되는 서버가 정상적으로 종료될때도 마찬가지입니다. ProviderFactory의 생명 주기는 KeycloakSessionFactory가 초기화 또는 초기화 해제 수행될 때 초기화 및 초기화 해제가 한번만 수행되는 서버 생명주기에 바인딩됩니다.
해당 작업에 대한 유일한 예외는 런타임에 제공자를 재배포할때 입니다. 이 경우 초기화 및 초기화 해제가 여러번 발생할 수 있습니다.
다음 단계는 제공자 초기화 단계에서 수행됩니다.
1) Keycloak은 각 SPI의 사용 가능한 모든 팩토리를 로드합니다.
2) 각 팩토리에서 제공자 설정과 함께 init 메서드를 호출합니다.
3) 모든 팩토리가 초기화되고 등록되면각 팩토리에서 postinit 매서드가 호출돼 keycloakSessionFactory를 기반으로 추가 초기화 단계를 추행합니다.
init 메서드는 $KC_HOME/standalone/configuration/standalone.xml파일의 특정 제공자로 설정된 구성을 기반으로 초기화하기 위해 팩토리 과정을 진행하는 과정 초기에 호출됩니다. 팩토리가 다른 팩토리나 KeycloakSession에 사용하지 않고 자체 초기화를 수행하는 경우 이 단계는 팩토리를 초기화 하기에 충분합니다.
하지만 postInit 메서드는 모든 팩토리가 등록된 후에만 호출되며, 초기화 중에 팩토리가 다른 제공자와 KeycloakSession 자체를 사용해 추가 단계를 수행할 수 있습니다.
또한 제공자의 생명주기는 요청에 바인딩됩니다. 제공자는 해당 ProviderFactory에서 생성되며 요청 생명주기 동안 한 번만 발생합니다. 초기화 해제와 관련해 제공자의 close 메서드는 요청의 마지막에 호출됩니다.
6. 인터페이스 변경
사용자들이 가장 많이 사용하는 주요 사용자 정의 후크 중 하나는 Keycloak 기본 제공 테마를 브랜딩에 맞게 UI 및 UX 요구사항을 반영하기 위해 변경하는 것입니다.
Keycloak은 테마를 변경할 수 있는 매우 간단한 환경을 제공하며, 사용자 페이지에서 관리 콘솔에 이르기까지 대부분의 UI를 변경할 수 있습니다.
7. 테마 이해
Keycloak의 다른 기능과 마찬가지로 테마는 자체 SPI를 통해 지원됩니다. 하지만 테마를 변경하기 위해 자바 코드를 구현해야 하는 대신, Keycloak은 단순한 CSS 클래스, 자바스크립트 그리고 HTML 구조를 간단하고 우아한 방법을 제공합니다. 실제로 필요에 따라 테마를 변경하는 것은 새로운 CSS 스타일시트를 정의하는 것에 불과합니다.
테마의 또 다른 중요한 측면은 국제화(Internationalization입니다. 전 세계적인 프로젝트로서 Keycloak은 다양한 언어를 지원하는데 기여하고 있으며, 사용자의 추가 노력없이 해당 국가의 사용자가 이미 모국어로 된 Keycloak 을 사용하고 있을 가능성이 높습니다.
Keycloak에서 제공하는 기본 테마는 theme 디렉터리에 배포의 일부로 포함돼 있습니다.
$ cd $KC_HOME\themes
$ ls
base
keycloak
keycloak-preview
keycloak.v2
자세한 내용은 https://www.keycloak.org/docs/latest/server_development/index.html#_themes 를 참고합니다.
Base 테마는 테마가 아니라 페이지 템플릿, 국제화를 위한 메시지 번들 및 공동 리소스가 포함돼 다른 테마에서 사용될 수 있는 구조를 제공합니다. Keycloak 테마와 같은 다른 테마는 base 테마를 확장해 특정 CSS 스타일시트, 자바스크립트, 이미지 등을 사용해 레이아웃을 정의합니다
각 theme 디렉터리에는 사용자가 정의가 가능한 Keycloak의 다양한 UI 집합에 대한 하위 디렉터리가 존재합니다. 해당 하위 디렉터리는 테마유형을 나타냅니다.
themes/mytheme
├── account
├── admin
├── common
├── email
├── login
├── welcome
- account : 계정 콘솔에 대한 UI 정의
- admin : 관리자 콘솔에 대한 UI 정의
- common : 테마 유형에서 사용되는 공통 리소스
- email : 이메일에 대한 UI 정의
- login : 프로파일 업데이트, 패스워드 리셋 등을 포함한 로그인 관련 페이지에 대한 UI 정의
- welcome : 웰컴 페이지에 대한 UI 정의
각 테마 유형에는 theme.properties 라는 필수 파일이 존재하며 해당 파일에 테마 유형의 설정을 정의합니다. 예시는 다음과 같습니다.
- 다른 테마에서 설정 상속
- 다른 테마에서 리소스 가져오기
- CSS 스타일
- 자바스크립트 리소스
- CSS 스타일을 Keycloak 컴포넌트(입력 상자 및 버튼)에 매핑
테마 설정의 한가지 중요한 측면은 테마 유형을 사용자 정의하는 경우 처음부터 모든걸 설정하지 않고 다른 테마의 구성을 활용해 필요한 부분만 변경할 수 있다는 점입니다. 기존 테마를 적절하게 변경하고 싶을 때 매우 편리합니다.
realm에 테마 설정하는 방법에 대해 알아보겠습니다.
Keycloak 테마를 만들려면 themes 디렉터리 안에 원하는 테마 이름으로 새 폴더를 생성합니다. 예를 들어 mytheme이라는 테마를 만들고 싶다면 아래의 코드를 실행합니다.
mkdir -p themes/mytheme
테마에 지원할 유형별로 하위 디렉터리를 생성합니다. 예를 들어 로그인 테마를 추가하겠습니다.
mkdir -p themes/mytheme/login
각 테마 유형 폴더안에 theme.properties 파일을 생성하고 테마 설정을 지정합니다.
$ vi themes/mytheme/login/theme.propertie
parent=base
import=common/keycloak
- parent=base : 기본 테마(base)를 확장합니다.
- import=common/keycloak : common/keycloak의 공통 리소스를 가져옵니다.
디렉터리에 CSS 스타일 시트, 자바스크립트 라이브러리 및 메시지 번들과 같은 필요한 정적 리소스를 추가합니다.
├── theme/mytheme/
│ ├── login/
│ │ ├── theme.properties
│ │ ├── login.ftl
│ │ ├── resources/
│ │ │ ├── css/styles.css
│ │ │ ├── img/image.png
│ │ ├── messages/
│ │ │ ├── messages_en.properties
테마 유형을 정의하는 경우. 다음과 같은 표준 디렉터리 구조를 가집니다.
- resources 디렉터리는 Keycloak이 테마에서 사용하는 정적 리소스가 위치합니다.
- message 디렉터리는 메시지 번들을 가져오는 디렉터리입니다.
이제 로그인 페이지 테마가 생성되었습니다.
Keycloak을 실행하여 Keycloak Admin Console에 로그인합니다. 테마를 적용할 Realm을 선택합니다.
좌측 메뉴에서 Realm Settings 클릭 > Themes 탭을 선택합니다. Login theme에서 mytheme을 선택한 후 Save 버튼을 클릭합니다.

Keycloak에서 로그인 관련 페이지를 개별 클라이언트 기반으로 정의할 수 있습니다. 해당 설정을 통해 인증 대상 클라이언트에 따라 사용자 정의된 최종 사용자 환경을 제공할 수 있습니다.
클라이언트의 login 테마를 정의하려면 클라이언트를 선택하고 클라이언트 상세 페이지의 Login Theme 설정에서 테마를 선택합니다.

8. 테마를 아카이브(JAR) 형태로 배포하기
테마를 배포할 때, META-INF/keycloak-themes.json 파일을 추가하여 사용할 수 있는 테마 목록과 제공하는 테마 유형을 정의해야 합니다.
예를 들어, mytheme이라는 테마를 배포하려면 mytheme.jar 파일을 다음과 같은 구조로 생성해야 합니다.
mytheme.jar
├── META-INF/
│ ├── keycloak-themes.json
├── theme/mytheme/
│ ├── login/
│ │ ├── theme.properties
│ │ ├── login.ftl
│ │ ├── resources/
│ │ │ ├── css/styles.css
│ │ │ ├── img/image.png
│ │ ├── messages/
│ │ │ ├── messages_en.properties
│ ├── email/
│ │ ├── messages/
│ │ │ ├── messages_en.properties
아카이브에는 META-INF/keycloak-themes.json 파일이 포함되어야 합니다. 이 파일에는 테마 정보가 JSON 형식으로 정의됩니다.
{
"themes": [
{
"name": "mytheme",
"types": ["login", "email"]
}
]
}
- "name": "mytheme" → 테마의 이름
- "types": ["login", "email"] → 이 테마가 지원하는 유형(로그인 페이지 및 이메일 템플릿)
테마의 동작을 설정하는 파일로, theme/mytheme/login/theme.properties에 다음 내용을 추가합니다.
parent=base
import=common/keycloak
theme/mytheme/login/login.ftl 파일을 만들어 사용자 정의 로그인 페이지를 디자인할 수 있습니다.
(참고 : https://freemarker.apache.org/)
What is Apache FreeMarker™?
Apache FreeMarker™ is a template engine: a Java library to generate text output (HTML web pages, e-mails, configuration files, source code, etc.) based on templates and changing data. Templates are written in the FreeMarker Template Language (FTL), which
freemarker.apache.org
<#import "template.ftl" as layout>
<@layout.registrationLayout displayMessage=true>
<h1>Welcome to My Custom Theme!</h1>
</@layout.registrationLayout>
테마의 CSS 및 이미지 파일을 resources 폴더에 추가합니다.
- theme/mytheme/login/resources/css/styles.css
- theme/mytheme/login/resources/img/image.png
다국어 메시지 파일을 messages 폴더에 추가합니다.
- 로그인 메시지: theme/mytheme/login/messages/messages_en.properties
- 이메일 메시지: theme/mytheme/email/messages/messages_en.properties
이제 JAR 파일을 생성합니다.
jar cf mytheme.jar -C theme/mytheme/ . -C META-INF/ .
또는 zip을 사용하여 생성할 수도 있습니다.
zip -r mytheme.jar META-INF theme
생성한 mytheme.jar 파일을 Keycloak의 providers 디렉터리에 복사합니다.
cp mytheme.jar $KEYCLOAK_HOME/providers/
그런 다음 Keycloak을 다시 시작하면 테마가 적용됩니다.
bin/kc.sh build
bin/kc.sh start
Keycloak을 실행하여 Keycloak Admin Console에 로그인합니다. 테마를 적용할 Realm을 선택합니다.
좌측 메뉴에서 Realm Settings 클릭 > Themes 탭을 선택합니다. Login theme에서 mytheme을 선택한 후 Save 버튼을 클릭합니다.
10. 템플릿 확장
때때로 CSS 스타일만 사용해 테마를 확장하는 것만으로 충분하지 않고 base 테마의 페이지 템플릿 컴포넌트 처리를 변경해야 하는 경우도 있습니다. Keycloak은 잘 알려져 있고 널리 사용되는 템플릿 엔진인 아파치 프리마커를 사용해 템플릿을 기반으로 페이지를 렌더링합니다.
이 상태에서 base 테마의 테마 유형 중 하나에서 템플릿을 복사해 사용자 정의 테마 유형에 포함시키면 됩니다.
하지만 이러한 유연성은 Keycloak이 릴리스될 때마다 기본 제공 템플릿에 대한 변경사항을 사용자 정의 템플릿에 수동으로 적용해야 하는 번거로움이 발생합니다. 테마에 사용자 정의를 적용하는 방법은 매우 편리하지만 Kecloak이 해당 템플릿을 정의하는 방법에 대한 추가적인 지식이 요구됩니다.
'WEB' 카테고리의 다른 글
Keycloak 시작하기 10 (0) | 2025.02.21 |
---|---|
Keycloak 시작하기 8 (0) | 2025.02.19 |
Keycloak 시작하기 7 (0) | 2025.02.18 |
Keycloak 시작하기 6 (0) | 2025.02.11 |
Keycloak 시작하기 5 (0) | 2025.02.11 |
- Total
- Today
- Yesterday