keycloak

[keycloak] 로그인 화면 꾸미기

몽게구름 2025. 12. 6. 17:33

환경 : Docker

커스텀 로그인 화면을 만들기 위해서

폴더를 생성한다.

messages_ko.properties : validation 이 영어로 나올때 한글로 변환 하기 위해

# encoding: UTF-8

invalidUserMessage=아이디 또는 비밀번호가 올바르지 않습니다.
invalidUsernameMessage=아이디 또는 비밀번호가 올바르지 않습니다.
invalidPasswordMessage=아이디 또는 비밀번호가 올바르지 않습니다.

username=아이디
password=비밀번호
doLogIn=로그인
doForgotPassword=비밀번호 찾기
doRegister=회원가입

style.css : 디자인 파일

/* 1) body – 이상한 height/overflow 제거 (여기가 원인) */
html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    background: #f5f6f7;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Apple SD Gothic Neo", "Noto Sans KR", sans-serif;
    overflow-x: hidden;   /* 🔹 가로 스크롤 강제 제거 */
}

/* 2) Keycloak 헤더 / realm 이름만 정확히 숨기기 */
#kc-header,
#kc-header-wrapper,
#kc-page-title,
.kc-header,
.kc-header-wrapper,
.login-pf-header,
.login-pf-page .login-pf-header,
.kc-login-header,
.masthead {
    display: none !important;
    height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
}

/* 3) 기본 배경만 우리 배경으로 맞추기 */
.login-pf,
.login-pf-page {
    margin: 0 !important;
    padding: 0 !important;
    background: #f5f6f7 !important;
    background-image: none !important;
}

/* 4) card 래퍼는 투명 처리 (남아 있어도 티 안 나게) */
.card-pf {
    box-shadow: none !important;
    background: transparent !important;
    border: none !important;
}

/* 페이지 전체 */
.mok-page {
    height: 100%;          /* 🔹 min-height 대신 height */
    width: 100%;
    padding: 90px 16px;       /* 위/아래 패딩 제거 → 세로 초과 줄이기 */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;  /* 세로 중앙 정렬 */
    box-sizing: border-box;
}

/* 로고 */

.mok-logo {
    height: 200px;
}

/* 카드 */
.mok-card {
    width: 100%;
    max-width: 420px;
    background: #fff;
    border-radius: 16px;
    border: 1px solid #e5e7eb;
    box-shadow: 0 4px 12px rgba(0,0,0,0.04);
    overflow: hidden;
}

/* (탭 안 쓰면 이 블록은 나중에 삭제해도 OK) */
.mok-tabs {
    display: flex;
    border-bottom: 1px solid #e3e5e8;
    background: #f8f9fb;
}
.mok-tab {
    flex: 1;
    text-align: center;
    padding: 12px 0;
    font-size: 14px;
    color: #7b858f;
}
.mok-tab.active {
    background: #fff;
    color: #222;
    font-weight: 600;
    border-bottom: 2px solid #03c75a;
}

.mok-body {
    padding: 24px 22px;
}

/* 에러 */
.mok-error {
    margin-bottom: 12px;
    padding: 10px 12px;
    background: #fee2e2;
    color: #b91c1c;
    border-radius: 8px;
    font-size: 13px;
}

/* 입력창 */
.mok-field {
    margin-bottom: 10px;
}
.mok-field input {
    width: 100%;
    height: 48px;
    padding: 0 14px;
    border-radius: 8px;
    border: 1px solid #dadada;
    font-size: 14px;
    box-sizing: border-box;
}
.mok-field input::placeholder {
    color: #b0b8c1;
}
.mok-field input:focus {
    border-color: #03c75a;
    outline: none;
}

/* 옵션 */
.mok-suboptions {
    margin: 8px 2px 16px;
    font-size: 13px;
    color: #616a74;
}
.mok-checkbox {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* 로그인 버튼 */
.mok-btn {
    width: 100%;
    height: 52px;
    background: #34718F;
    color: #fff;
    border: none;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
}

/* 하단 링크 */
.mok-links {
    margin-top: 18px;
    font-size: 12px;
    color: #7b858f;
    display: flex;
    align-items: center;
    gap: 6px;
}
.mok-links a {
    text-decoration: none;
    color: #7b858f;
}
.mok-links a:hover {
    text-decoration: underline;
}

/* 모바일 최적화 */
@media (max-width: 480px) {
    .mok-card {
        border-radius: 12px;
    }
    .mok-body {
        padding: 20px 16px;
    }
    .mok-logo {
        height: 200px;
    }
}


/*  Keycloak 기본 배경 이미지 통째로 제거 */
#kc-page-background {
    display: none !important;
}

/* 혹시 몰라서 한 번 더 회색으로 덮어쓰기 */
html, body,
.login-pf,
.login-pf-page,
#kc-content,
#kc-content-wrapper {
    background-color: #f5f6f7 !important;
    background-image: none !important;
}

/* Keycloak 기본 전체 너비 에러 배너 숨기기 */
.alert-error,
.alert.alert-error,
.kc-feedback-text,
#kc-feedback-wrapper {
    display: none !important;
}

img : 이미지

deprecated theme.js : 다크/라이트 모드 사용하려고 만들었는데 미사용

login.ftl : 로그인 화면

<#import "template.ftl" as layout>

<@layout.registrationLayout displayInfo=false; section>

<#-- header 섹션은 비워둠 (위에서 CSS로 숨김) -->
    <#if section = "header">
    </#if>

<#-- 로그인 폼 섹션 -->
    <#if section = "form">
        <div class="mok-page">

            <!-- 상단 로고 -->
            <div class="mok-logo-wrap">
                <img src="${url.resourcesPath}/img/mockio-logo.png"
                     class="mok-logo" alt="mockio"/>
            </div>

            <!-- 로그인 카드 (탭 없이) -->
            <div class="mok-card">

                <div class="mok-body">

                    <form id="kc-form-login" action="${url.loginAction}" method="post">

                        <div class="mok-field">
                            <input id="username"
                                   name="username"
                                   type="text"
                                   placeholder="아이디"
                                   value="${(login.username!'')}"
                                   autofocus />
                        </div>

                        <div class="mok-field">
                            <input id="password"
                                   name="password"
                                   type="password"
                                   placeholder="비밀번호" />
                        </div>

                        <#-- 🔻 에러를 버튼 바로 위에 표시 -->
                        <#if message?has_content>
                            <div class="mok-error">
                                ${kcSanitize(message.summary)?no_esc}
                            </div>
                        </#if>

                        <button type="submit" class="mok-btn">로그인</button>
                    </form>

                </div>
            </div>

            <!-- 하단 링크 (원하면 이 부분은 나중에 지워도 됨) -->
            <div class="mok-links">
                <a href="${url.loginResetCredentialsUrl}">비밀번호 찾기</a>
                <span>|</span>
                <a href="#">아이디 찾기</a>
                <#if realm.registrationAllowed>
                    <span>|</span>
                    <a href="${url.registrationUrl}">회원가입</a>
                </#if>
            </div>
        </div>
    </#if>

<#-- info 섹션은 사용 안 함 -->
    <#if section = "info">
    </#if>

</@layout.registrationLayout>

theme.properties : import 파일

 

 

 

docker run -d --name keycloak -p 8084:8080   -e KEYCLOAK_ADMIN=test   -e KEYCLOAK_ADMIN_PASSWORD=test   -v C:/project/mockio/keycloak-themes/mockio-theme:/opt/keycloak/themes/mockio-theme   quay.io/keycloak/keycloak:24.0  start-dev

으로 keycloak을 실행 후 

localhost:8084로 admin으로 들어간다.

 

 

오른쪽 드랍박스 클릭 후 Create realm 으로 realm을 생성한다.

 

 

그 후 자신이 만든 realm으로 변경 하고

왼쪽 Realm settings 을 클릭 -> Themes -> Login theme를 자신이 만든 테마로 변경 한다.

그리고 영어로 나오는 유효성을 한글로 변경하기 위해서는

Realm settings 을 클릭 -> Localzation -> Internationalization Enabled 활성화 ->

Supported locales korean입력

Default locale을 Korean으로 변경한다.

 

※ theme.properties에 locales 에 ko를 설정하지 않으면 입력을 해도 나오지 않으니 꼭 추가를 해야 된다.

 

 

 

그리고 왼쪽 Clients  로 들어가 url을 클릭하여 확인을 하면 된다.

 

 

 

이렇게 수정한 화면이 나오고 유효성도 처음에는 영어 였지만 수정을 하여 한글로 변경 되었다.

'keycloak' 카테고리의 다른 글

keycloak 구글/네이버 로그인  (0) 2025.12.07
keycloak - 커스텀 회원가입  (0) 2025.12.06