2025-09-09 01:12:14 +09:00

13 KiB

Auth 서비스 데이터베이스 설계서

1. 설계 개요

1.1 설계 목적

Auth 서비스의 사용자 인증 및 인가 기능 구현을 위한 독립적인 데이터베이스 설계

1.2 설계 원칙

  • 서비스 독립성: Auth 서비스 전용 데이터베이스 구성
  • 마이크로서비스 패턴: 다른 서비스와 직접적인 FK 관계 없음
  • 캐시 우선 전략: 타 서비스 데이터는 Redis 캐시로만 참조
  • 보안 강화: 민감 정보 암호화 저장
  • 감사 추적: 모든 인증/인가 활동 이력 관리

1.3 주요 기능 요구사항

  • UFR-AUTH-010: 사용자 로그인 (ID/Password 인증, 계정 잠금)
  • UFR-AUTH-020: 사용자 인가 (서비스별 접근 권한 확인)

2. 데이터베이스 아키텍처

2.1 데이터베이스 정보

  • DB 이름: phonebill_auth
  • DBMS: PostgreSQL 15
  • 문자셋: UTF-8
  • 타임존: Asia/Seoul

2.2 서비스 독립성 전략

  • 직접 데이터 공유 금지: 다른 서비스 DB와 직접 연결하지 않음
  • 캐시 기반 참조: 필요한 외부 데이터는 Redis 캐시를 통해서만 접근
  • 이벤트 기반 동기화: 필요 시 메시징을 통한 데이터 동기화

3. 테이블 설계

3.1 사용자 계정 관리

auth_users (사용자 계정)

-- 사용자 기본 정보 및 인증 정보
CREATE TABLE auth_users (
    user_id VARCHAR(50) PRIMARY KEY,           -- 사용자 ID (로그인 ID)
    password_hash VARCHAR(255) NOT NULL,       -- 암호화된 비밀번호 (BCrypt)
    password_salt VARCHAR(100) NOT NULL,       -- 비밀번호 솔트
    customer_id VARCHAR(50) NOT NULL,          -- 고객 식별자 (외부 참조용)
    line_number VARCHAR(20),                   -- 회선번호 (캐시에서 조회)
    account_status VARCHAR(20) DEFAULT 'ACTIVE', -- ACTIVE, LOCKED, SUSPENDED, INACTIVE
    failed_login_count INTEGER DEFAULT 0,      -- 로그인 실패 횟수
    last_failed_login_at TIMESTAMP,           -- 마지막 실패 시간
    account_locked_until TIMESTAMP,           -- 계정 잠금 해제 시간
    last_login_at TIMESTAMP,                  -- 마지막 로그인 시간
    last_password_changed_at TIMESTAMP,       -- 비밀번호 마지막 변경 시간
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(customer_id)
);

auth_user_sessions (사용자 세션)

-- 사용자 세션 관리
CREATE TABLE auth_user_sessions (
    session_id VARCHAR(100) PRIMARY KEY,       -- 세션 ID (UUID)
    user_id VARCHAR(50) NOT NULL,             -- 사용자 ID
    session_token VARCHAR(500) NOT NULL,       -- JWT 토큰
    refresh_token VARCHAR(500),                -- 리프레시 토큰
    client_ip VARCHAR(45),                     -- 클라이언트 IP (IPv6 지원)
    user_agent TEXT,                           -- User-Agent 정보
    auto_login_enabled BOOLEAN DEFAULT FALSE,  -- 자동 로그인 여부
    expires_at TIMESTAMP NOT NULL,            -- 세션 만료 시간
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    last_accessed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES auth_users(user_id) ON DELETE CASCADE
);

3.2 권한 관리

auth_services (서비스 정의)

-- 시스템 내 서비스 정의
CREATE TABLE auth_services (
    service_code VARCHAR(30) PRIMARY KEY,      -- 서비스 코드
    service_name VARCHAR(100) NOT NULL,        -- 서비스 이름
    service_description TEXT,                  -- 서비스 설명
    is_active BOOLEAN DEFAULT TRUE,            -- 서비스 활성화 여부
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

auth_permissions (권한 정의)

-- 권한 정의 테이블
CREATE TABLE auth_permissions (
    permission_id SERIAL PRIMARY KEY,          -- 권한 ID
    service_code VARCHAR(30) NOT NULL,         -- 서비스 코드
    permission_code VARCHAR(50) NOT NULL,      -- 권한 코드
    permission_name VARCHAR(100) NOT NULL,     -- 권한 이름
    permission_description TEXT,               -- 권한 설명
    is_active BOOLEAN DEFAULT TRUE,            -- 권한 활성화 여부
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (service_code) REFERENCES auth_services(service_code),
    UNIQUE(service_code, permission_code)
);

auth_user_permissions (사용자 권한)

-- 사용자별 권한 할당
CREATE TABLE auth_user_permissions (
    user_permission_id SERIAL PRIMARY KEY,     -- 사용자권한 ID
    user_id VARCHAR(50) NOT NULL,             -- 사용자 ID
    permission_id INTEGER NOT NULL,           -- 권한 ID
    granted_by VARCHAR(50),                   -- 권한 부여자
    granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP,                     -- 권한 만료일 (NULL = 무기한)
    is_active BOOLEAN DEFAULT TRUE,           -- 권한 활성화 여부
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES auth_users(user_id) ON DELETE CASCADE,
    FOREIGN KEY (permission_id) REFERENCES auth_permissions(permission_id),
    UNIQUE(user_id, permission_id)
);

3.3 보안 및 감사

auth_login_history (로그인 이력)

-- 로그인 시도 이력
CREATE TABLE auth_login_history (
    history_id SERIAL PRIMARY KEY,             -- 이력 ID
    user_id VARCHAR(50),                       -- 사용자 ID (실패 시 NULL 가능)
    login_type VARCHAR(20) NOT NULL,           -- LOGIN, LOGOUT, AUTO_LOGIN
    login_status VARCHAR(20) NOT NULL,         -- SUCCESS, FAILURE, LOCKED
    client_ip VARCHAR(45),                     -- 클라이언트 IP
    user_agent TEXT,                           -- User-Agent 정보
    failure_reason VARCHAR(100),               -- 실패 사유
    session_id VARCHAR(100),                   -- 세션 ID (성공 시)
    attempted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES auth_users(user_id) ON DELETE SET NULL
);

auth_permission_access_log (권한 접근 로그)

-- 권한 기반 접근 로그
CREATE TABLE auth_permission_access_log (
    log_id SERIAL PRIMARY KEY,                 -- 로그 ID
    user_id VARCHAR(50) NOT NULL,             -- 사용자 ID
    service_code VARCHAR(30) NOT NULL,         -- 접근한 서비스
    permission_code VARCHAR(50) NOT NULL,      -- 확인된 권한
    access_status VARCHAR(20) NOT NULL,        -- GRANTED, DENIED
    client_ip VARCHAR(45),                     -- 클라이언트 IP
    session_id VARCHAR(100),                   -- 세션 ID
    requested_resource VARCHAR(200),           -- 요청 리소스
    denial_reason VARCHAR(100),                -- 거부 사유
    accessed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES auth_users(user_id) ON DELETE CASCADE
);

4. 인덱스 설계

4.1 성능 최적화 인덱스

-- 사용자 조회 최적화
CREATE INDEX idx_auth_users_customer_id ON auth_users(customer_id);
CREATE INDEX idx_auth_users_account_status ON auth_users(account_status);
CREATE INDEX idx_auth_users_last_login ON auth_users(last_login_at);

-- 세션 관리 최적화
CREATE INDEX idx_auth_sessions_user_id ON auth_user_sessions(user_id);
CREATE INDEX idx_auth_sessions_expires_at ON auth_user_sessions(expires_at);
CREATE INDEX idx_auth_sessions_token ON auth_user_sessions(session_token);

-- 권한 조회 최적화
CREATE INDEX idx_auth_user_permissions_user_id ON auth_user_permissions(user_id);
CREATE INDEX idx_auth_user_permissions_active ON auth_user_permissions(user_id, is_active);
CREATE INDEX idx_auth_permissions_service ON auth_permissions(service_code, is_active);

-- 로그 조회 최적화
CREATE INDEX idx_auth_login_history_user_id ON auth_login_history(user_id);
CREATE INDEX idx_auth_login_history_attempted_at ON auth_login_history(attempted_at);
CREATE INDEX idx_auth_permission_log_user_id ON auth_permission_access_log(user_id);
CREATE INDEX idx_auth_permission_log_accessed_at ON auth_permission_access_log(accessed_at);

4.2 보안 관련 인덱스

-- 계정 잠금 관련 조회 최적화
CREATE INDEX idx_auth_users_failed_login ON auth_users(failed_login_count, last_failed_login_at);
CREATE INDEX idx_auth_users_locked_until ON auth_users(account_locked_until) WHERE account_locked_until IS NOT NULL;

-- IP 기반 보안 모니터링
CREATE INDEX idx_auth_login_history_ip_status ON auth_login_history(client_ip, login_status, attempted_at);

5. 제약조건 및 트리거

5.1 데이터 무결성 제약조건

-- 계정 상태 체크 제약조건
ALTER TABLE auth_users ADD CONSTRAINT chk_account_status 
    CHECK (account_status IN ('ACTIVE', 'LOCKED', 'SUSPENDED', 'INACTIVE'));

-- 로그인 상태 체크 제약조건
ALTER TABLE auth_login_history ADD CONSTRAINT chk_login_status 
    CHECK (login_status IN ('SUCCESS', 'FAILURE', 'LOCKED'));

-- 로그인 타입 체크 제약조건
ALTER TABLE auth_login_history ADD CONSTRAINT chk_login_type 
    CHECK (login_type IN ('LOGIN', 'LOGOUT', 'AUTO_LOGIN'));

-- 접근 상태 체크 제약조건
ALTER TABLE auth_permission_access_log ADD CONSTRAINT chk_access_status 
    CHECK (access_status IN ('GRANTED', 'DENIED'));

5.2 자동 업데이트 트리거

-- updated_at 자동 갱신 함수
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 각 테이블에 updated_at 트리거 적용
CREATE TRIGGER update_auth_users_updated_at BEFORE UPDATE ON auth_users 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_auth_services_updated_at BEFORE UPDATE ON auth_services 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_auth_permissions_updated_at BEFORE UPDATE ON auth_permissions 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_auth_user_permissions_updated_at BEFORE UPDATE ON auth_user_permissions 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

6. 보안 설계

6.1 암호화 전략

  • 비밀번호: BCrypt 해시 + 개별 솔트
  • 토큰: JWT 기반 인증 토큰
  • 세션: 안전한 세션 ID 생성 (UUID)
  • 개인정보: 필요 시 AES-256 암호화

6.2 계정 보안 정책

  • 계정 잠금: 5회 연속 실패 시 30분 잠금
  • 세션 타임아웃: 30분 비활성 시 자동 만료
  • 토큰 갱신: 리프레시 토큰을 통한 안전한 토큰 갱신

7. 캐시 전략

7.1 Redis 캐시 설계

Cache Key Pattern: auth:{category}:{identifier}
- auth:user:{user_id} -> 사용자 기본 정보 (TTL: 30분)
- auth:permissions:{user_id} -> 사용자 권한 목록 (TTL: 1시간)
- auth:session:{session_id} -> 세션 정보 (TTL: 세션 만료시간)
- auth:failed_attempts:{user_id} -> 실패 횟수 (TTL: 30분)

7.2 캐시 무효화 전략

  • 권한 변경 시: 해당 사용자 권한 캐시 삭제
  • 계정 잠금/해제 시: 사용자 정보 캐시 삭제
  • 로그아웃 시: 세션 캐시 삭제

8. 데이터 관계도 요약

8.1 핵심 관계

  • auth_users (1) : (N) auth_user_sessions
  • auth_users (1) : (N) auth_user_permissions
  • auth_services (1) : (N) auth_permissions
  • auth_permissions (1) : (N) auth_user_permissions
  • auth_users (1) : (N) auth_login_history
  • auth_users (1) : (N) auth_permission_access_log

8.2 외부 서비스 연동

  • 고객 정보: Bill-Inquiry 서비스의 고객 데이터를 캐시로만 참조
  • 회선 정보: Product-Change 서비스의 회선 데이터를 캐시로만 참조
  • 서비스 메타데이터: 각 서비스의 메뉴/기능 정보를 캐시로 관리

9. 성능 고려사항

9.1 예상 데이터 볼륨

  • 사용자 수: 10만 명 (초기), 100만 명 (목표)
  • 일일 로그인: 10만 회
  • 세션 동시 접속: 1만 개
  • 로그 보관 기간: 1년 (압축 보관)

9.2 성능 최적화

  • 커넥션 풀: 20개 커넥션 (초기)
  • 읽기 전용 복제본: 조회 성능 향상
  • 파티셔닝: 로그 테이블 월별 파티셔닝
  • 아카이빙: 1년 이상 로그 별도 보관

10. 관련 문서