PatternsP4 본문

Login

패턴 정본 1호 — WDS 컴포넌트를 조합한 적응형 로그인. 단일 화면·식별자 우선 흐름과 비밀번호·패스키·SSO 방식을 한 표면에서 다루는 인증 패턴 패밀리.

마지막 업데이트 2026-06-13

데모#

상단 컨트롤로 두 축을 전환하며 살펴봅니다 — 흐름(식별자 우선 ↔ 단일 화면)과 상태(라이브 · 로딩 · 인증 실패 · 계정 잠금). 라이브에서 빈 값 제출은 인라인 필드 오류, 유효 제출은 완료로 진행하며 비밀번호 표시 토글·패스키·조직 SSO가 모두 동작합니다. 실제 인증은 없습니다(UI Reference).

적응형 로그인 — 패널을 좁히면 브랜드 split이 폼 단독으로 접힙니다

언제 로그인을 요구하나#

로그인 화면을 어떻게 만드느냐보다 언제 요구하느냐가 먼저입니다(Apple HIG — Managing accounts).

  • 게스트 우선 — 로그인을 가능한 한 늦춥니다. 둘러보기·열람으로 가치를 먼저 경험하게 하고, 계정이 꼭 필요한 동작(저장·공유·결제)에서만 요구합니다.
  • 가치 교환 — "가치를 주는 대가로만" 로그인을 요청합니다. 진입 즉시 벽을 세우지 않습니다.
  • 계정 최소화 — 핵심 기능이 계정을 요구하지 않으면 계정 생성을 강제하지 않습니다.
  • 삭제 진입점 의무 — 계정 생성을 돕는다면 삭제(비활성화 아님) 경로도 앱 안에서 제공해야 합니다.
  • provider 동등성 — 서드파티 로그인(Google 등)만으로 계정을 만드는 진입은 동급의 대안(Sign in with Apple·자체 계정)을 함께 둡니다.

이 패턴은 "로그인 표면"의 정본일 뿐, 로그인을 띄울지 말지는 제품이 위 정책으로 결정합니다.

구성#

로그인 화면은 두 영역으로 나뉩니다.

영역역할구성 요소
브랜드 패널제품 맥락·신뢰 형성WIZ 심볼 · 워드마크 · 헤드라인 · 핵심 가치 3종 · 보안 고지
폼 패널인증 입력·방식 선택이메일 · 비밀번호(표시 토글) · 로그인 유지 · 비밀번호 찾기 · 1차 CTA · 패스키 · 조직 SSO · 가입 안내

브랜드 패널 배경은 color.primary 파생 그라데이션과 심볼 색을 흩뿌린 저투명 블러로 깊이를 만듭니다 — 별도 이미지 자산 없이 양 테마에서 일관됩니다.

적응형 동작#

패턴은 컨테이너 쿼리로 자기 폭에 반응합니다(뷰포트가 아니라 배치된 영역 기준).

컨테이너 폭레이아웃
≥ 600px좌 브랜드 패널 + 우 폼의 2열 split (1.05 : 0.95)
< 600px브랜드는 심볼·워드마크 슬림 헤더로 축약, 폼이 단독 stack

좁은 폭에서 헤드라인·가치 목록은 숨겨 세로 길이를 줄이고, 입력·CTA의 터치 타깃은 유지합니다. 동일 패턴을 모달·사이드 패널·전체 화면 어디에 배치해도 깨지지 않습니다.

흐름#

로그인은 단일 화면이 아니라 인증 방식 패밀리로 설계합니다. 식별자(이메일)를 먼저 받고 사용 가능한 방식으로 분기하면 SSO·패스키 라우팅과 비밀번호 없는 인증을 한 표면에서 수용합니다.

흐름동작쓰는 곳
단일 화면이메일·비밀번호를 한 화면에 제시방식이 고정된 단순 진입
식별자 우선이메일 → "계속" → 방식(비밀번호·패스키·SSO) 분기조직 SSO 라우팅·패스키 발견이 필요한 엔터프라이즈
패스키식별자 필드 autocomplete="username webauthn" 조건부 자동완성 + "패스키로 로그인" 버튼비밀번호 없는 1차 방식(권장)
조직 SSO"조직 SSO로 계속하기" — IdP 위임도메인 페더레이션 사용자
서드파티Apple·Google 사인인(ProviderButton)소비자 제품의 소셜 로그인

식별자-우선에서 방식 단계로 넘어갈 때 포커스를 비밀번호로 이동하고, 다단계에서도 autocomplete="username" hidden 필드를 동반해 비밀번호 매니저 저장을 보존합니다.

매직 링크·OTP는 복구·온보딩용 보조 방식으로, 후속 단계에서 동일 패밀리에 편입합니다.

변형#

같은 인증 표면을 맥락에 따라 네 가지 레이아웃으로 배치합니다 — 컴포넌트·흐름·상태는 공유하고 만 바꿉니다.

변형형태쓰는 곳
split 브랜드 패널좌 브랜드 + 우 폼(기본 데모)전용 로그인 페이지·제품 첫인상
centered card폼 단독 중앙 카드(브랜드는 슬림 헤더)좁은 폭·미니멀 진입·임베드
modal / embedded오버레이·인라인 패널에 폼만작업 중 재인증·세션 만료 복귀
enterprise SSO landing식별자 우선 + SSO를 1차로 노출도메인 페더레이션 조직 진입

split ↔ centered는 위 적응형 동작으로 자동 전환됩니다(컨테이너 < 600px이면 centered로 접힘). modal·SSO landing은 같은 폼·흐름을 다른 셸에 끼워 재사용합니다 — 새 컴포넌트를 만들지 않습니다.

상태#

폼은 다음 표시 상태를 가집니다. 데모의 상태 컨트롤로 로딩·인증 실패·계정 잠금을 강제 표시해 검수할 수 있습니다.

상태트리거표현
기본초기입력·CTA 노출, 오류 없음
로딩제출 직후1차 CTA loading(Spinner·aria-busy)·중복 제출 차단
인라인 오류빈·형식 오류 필드해당 FormField에 오류 텍스트 + aria-invalid 보더
인증 실패자격 증명 불일치CTA 위 FormMessage(error) role="alert"제너릭 메시지(계정 열거 방지)
계정 잠금연속 실패(레이트리밋)CTA 위 FormMessage(warning) + 모든 CTA 비활성
Caps Lock비밀번호 포커스 중 Caps Lock필드 하단 role="status" 라이브 경고
완료유효 제출 · 패스키 · SSO성공 마크 + 환영 메시지 + 다른 계정 전환

실제 인증 로직은 포함하지 않습니다 — 패턴은 UI Reference만 제공합니다(MASTER_PLAN Portal Boundary). 제품은 이 표면에 자사 인증 흐름을 연결합니다.

모션#

전환은 흐름을 보조할 뿐 주의를 끌지 않습니다 — spring 토큰을 그대로 소비합니다.

대상토큰동작
방식 단계 진입(식별자 → 비밀번호)spring.spatial.fast (256ms · ζ0.8)식별자 행이 약한 오버슈트로 슬라이드+페이드
폼 메시지 등장(인증 실패·계정 잠금)spring.effect.default (188ms · ζ1.0)오버슈트 없이 페이드 인

transform·opacity만 애니메이트해 레이아웃을 흔들지 않습니다(컴포지터 친화). prefers-reduced-motion: reduce면 모든 전환을 끄고 즉시 정적으로 표시합니다(WCAG 2.3.3).

콘텐츠·보안#

규칙근거
실패 메시지는 제너릭 — 어느 필드가 틀렸는지 노출 금지계정 열거 방지(OWASP Authentication)
메시지 배치는 범위(scope) 기준 — 필드 오류는 인풋 아래(Tier 1), 제출 실패·잠금은 CTA 위 FormMessage(Tier 2)메시지 위계
라벨은 지시 아닌 명사(이메일·비밀번호), placeholder는 라벨 대체 금지라벨 상시 가시성
1차 동사는 행동형(로그인·계속), 방식 버튼은 "패스키로 로그인"·"조직 SSO로 계속하기"동사 일관성
비밀번호는 붙여넣기·비밀번호 매니저 허용(차단 금지)WCAG 2.2 §3.3.8

접근성#

WCAG 2.2 AA를 기준으로, 로그인 특화 신규 기준(§3.3.8 Accessible Authentication)을 명시적으로 만족시킵니다.

계약구현
폼 영역section[aria-label="로그인"] 로 랜드마크화
라벨 연결FormFieldlabel–입력을 htmlFor/id로 배선, 오류 시 aria-describedby/aria-invalid 자동 주입
입력 목적 (1.3.5)식별자 autocomplete="username webauthn"·비밀번호 current-password·inputmode 지정
인증 접근성 (§3.3.8)붙여넣기·비밀번호 매니저 허용 + 비(非)인지 경로(패스키·SSO) 제공
중복 입력 (3.3.7)식별자-우선 2단계에서 이메일을 재입력 없이 이월
상태 메시지 (4.1.3)폼 오류 FormMessage(error)=role="alert", Caps Lock=role="status" 라이브 리전
포커스 관리방식 단계 진입 시 비밀번호로 포커스 이동, 포커스 링 상시 가시(2.4.7)·가림 없음(2.4.11)
비밀번호 토글aria-pressed + 상태별 aria-label(표시/숨기기), 기본 마스킹
대비브랜드 패널 흰 텍스트는 primary 위 AA 충족, 폼은 semantic 토큰

사용 컴포넌트#

Input(leadingIcon·trailingIcon·invalid) · FormField(error) · Button(primary·secondary·ghost·fullWidth·loading) · Checkbox · TextLink · FormMessage(error·warning, Tier 2) · SegmentedButton(데모 컨트롤). 전부 06 컴포넌트의 실물을 그대로 조합했습니다 — 패턴은 새 컴포넌트를 만들지 않습니다.

토큰#

패턴 전용 토큰은 두지 않고 semantic 토큰을 직접 소비합니다.

속성토큰
폼 표면color.surface-raised
브랜드 배경color.primary · color.primary-active 그라데이션
라운드/그림자radius.xl · shadow.lg
구분선/보더color.border-subtle
본문/보조 텍스트color.text · color.text-muted · color.text-subtle
완료 마크color.success

백엔드 연동 (P6)#

위 패턴 데모는 UI Reference라 실제 인증이 없습니다. P6 Backend Base의 core-api와 실제로 통신하는 데모는 아래에 있습니다 — 루트에서 make stack-up으로 로컬 풀스택을 먼저 띄워야 동작합니다(진입점 localhost:58080, Nginx 리버스 프록시).

core-api 실연동 — JWT 로그인 → Bearer /me 호출
흐름엔드포인트
로그인POST /api/v1/auth/login → access(15분) + refresh(14일, 회전)
내 정보GET /api/v1/auth/me (Bearer)
실패401 ProblemDetail · 연속 실패 시 429(레이트리밋)

시드 계정은 demo 프로파일이 만듭니다 — 이메일 admin@wiz-factory.com, 비밀번호는 infra/docker/.envWDS_DEMO_ADMIN_PASSWORD. 자세한 API 계약은 BACKEND_GUIDE(P6 문서)를 참고하세요.