PLATFORM

국내 대형 온라인 서점의 전자도서관을 다시 만들고 있습니다.

2025년 6월 착수. 회원, 도서, 대출, 발주, 정산, 알림, 인증, 콘텐츠 처리, DRM, 뷰어를 각각의 서비스로 다시 세우고 한 클러스터에서 운영합니다. 아래는 하늘랩이 설계하고 구현 중인 구조입니다.

시스템 지도

사용자 웹 백오피스 워크벤치 뷰어 SDK iOS · Android · Web BFF (프론트별) · 세션과 토큰은 여기서만 인증 서버 OAuth2 Code + PKCE · OIDC 연동 M2M Client Credentials 서명 JWT · 4단계 RBAC 업무 API · 여러 도메인을 조합해 화면의 흐름을 만든다 도메인 API · 자기 데이터만 소유한다 (22개) 회원 도서 대출 발주 정산 알림 DRM 이미지 소비 관계형 DB 읽기 · 쓰기 분리 분산 캐시 2단 캐시 L2 객체 저장소 · 키 관리 메시지 큐 콘텐츠 파이프라인 정규화 → DRM → 암호화 → 발행 AWS 관리형 Kubernetes · 계층별 격리 · 환경별 오버레이 · 외부 비밀값 저장소 · 분산 추적
저장소 79개, API 서버 52개(도메인 API 22개), 공통 모듈 14종으로 구성됩니다. 내부 서비스명, 주소, 제품 버전은 생략했습니다. 작은 화면에서는 지도를 좌우로 스크롤할 수 있습니다.

CORE CONCEPTS

적용한 핵심 개념

각 항목은 요약과 키워드만 먼저 보여줍니다. 구조와 근거가 궁금하면 펼쳐서 읽을 수 있습니다.

01 · SERVICE BOUNDARY

Domain API · Business API · BFF 3계층 분리

데이터는 도메인 서비스만 만지고, 화면의 흐름은 업무 API가 조합하며, 브라우저는 BFF 하나만 봅니다.

  • Domain-owned data
  • BFF per frontend
  • M2M Client Credentials
  • Circuit Breaker · Retry
  • Trace ID propagation
  • Standard response envelope
  • Per-service OpenAPI contract
구조와 근거 보기

데이터를 소유하는 도메인 API는 자기 테이블만 다루고, 업무 API는 여러 도메인을 조합해 화면이 필요로 하는 흐름을 만듭니다. 프론트마다 BFF를 두어 브라우저는 BFF만 알고, 세션과 토큰은 BFF 안에서만 다룹니다. 서비스 간 호출은 공통 HTTP 클라이언트 하나로 통일했습니다. 서킷브레이커와 재시도, 추적 ID 전파, M2M 토큰 발급이 내장되어 있어 서비스가 각자 구현하지 않습니다.

  • 모든 응답은 같은 봉투를 씁니다. 추적 ID, 업무 코드, 페이지네이션이 한 형식입니다.
  • 오류 계약은 프레임워크 독립 모듈(Problem Details 모델, 오류 코드 레지스트리)로 분리해 모든 서비스가 같은 코드 체계를 공유합니다.
  • 서비스별 OpenAPI 계약을 저장소 안에 배포해, 개발자는 자기 서비스 문서만 보고 구현합니다.
02 · CLEAN ARCHITECTURE

4모듈 Clean Architecture, 의존 방향은 둘뿐

52개 서버가 같은 구조를 유지하도록 규칙을 문서가 아니라 린터로 강제합니다.

  • domain / usecase / data / api
  • Dependency Rule
  • runtimeOnly composition root
  • Value Object · no primitive obsession
  • CQRS Read / Write repository
  • 1 UseCase = 1 transaction boundary
  • Architecture linter · 101 rules
  • Starter generator
구조와 근거 보기

모든 API 서버는 domain, usecase, data, api 네 모듈로 나뉩니다. 의존은 api → usecase → domain, data → domain 두 방향만 허용하고, api는 data를 런타임에만 조립합니다. 도메인 모듈에는 프레임워크와 DB 드라이버 의존을 두지 않습니다. 식별자는 raw 타입 대신 값 객체로 다루고, 읽기와 쓰기 저장소를 분리하며, 트랜잭션 경계는 유스케이스 하나에 하나입니다. Handler는 HTTP 경계만, UseCase는 단일 Command 입력과 Model 출력, 비동기는 Kotlin Coroutines와 Flow로 통일합니다.

  • 자체 린터가 101개 규칙으로 계층 의존, DI 위치, 응답 봉투, ID 누수를 정적으로 판정합니다. 결과는 FAIL / NEEDS_REVIEW / SOURCE_CONFLICT로 구분합니다.
  • 신규 서버는 스타터 생성기 한 명령으로 4모듈 구조와 컨벤션 테스트를 갖고 시작합니다.
  • 기준 저장소 16개의 커밋 해시를 고정한 참조 매니페스트로 "표준이 실제 코드와 일치하는지"를 추적합니다.
03 · AUTH & AUTHZ

OAuth2 · OIDC · M2M을 한 인증 서버에서

사용자, 직원, 서비스의 로그인을 각각 다른 흐름으로 처리하고, 권한은 계약에 명시합니다.

  • Authorization Code + PKCE
  • OIDC federation
  • Client Credentials (M2M)
  • Asymmetric-signed JWT
  • Public-key 2-tier cache
  • Refresh token family rotation
  • Reuse detection
  • 4-level RBAC
  • Multi-tenancy
  • Audit log · PII masking
구조와 근거 보기

OAuth2 Authorization Code + PKCE로 사용자를, 외부 IdP와의 OIDC 연동으로 직원을, Client Credentials로 서비스 간 호출(M2M)을 인증합니다. JWT는 비대칭 키로 서명하고 공개키는 로컬(L1)과 분산(L2) 2단 캐시로 검증합니다. 리프레시 토큰은 패밀리 단위로 회전시켜 재사용이 감지되면 패밀리 전체를 폐기하고, 접속 환경이 급격히 바뀌면 이상 징후로 처리합니다.

  • 4단계 RBAC(최고 관리자, 운영사 관리자, 총판 관리자, 기관 관리자)를 OpenAPI 계약에 명시하고 scope와 audience를 토큰 검증에 포함합니다.
  • 멀티테넌시: 기관 식별자 없이는 저장소에 진입할 수 없습니다.
  • 모든 관리자 행동은 감사 로그에 남기고, 개인정보는 저장 전에 마스킹합니다.
04 · CONTENT PIPELINE & VIEWER

Normalize → DRM → Publish 파이프라인과 3종 뷰어

원본 파일 한 건이 암호화된 발행물이 되기까지를 하나의 작업으로 추적하고, 뷰어는 플랫폼별로 직접 만듭니다.

  • PDF / EPUB Normalizer
  • Readium LCP
  • Media packaging
  • Image encryption
  • Per-version data keys
  • Fan-out / Fan-in
  • DB-state orchestrator
  • claim / lease / attempt
  • Idempotent result upload
  • PDFium / PDFKit dual engine
  • Readium Kotlin toolkit
구조와 근거 보기

CMS에 올라온 PDF · EPUB은 정규화 도구가 챕터 단위로 분절하고 이미지 · 오디오 · 비디오를 추출합니다. 문서는 Readium LCP 기반 DRM으로, 미디어는 별도 패키징으로, 이미지는 자체 암호화로 각각 fan-out 처리한 뒤 객체 저장소에 발행하고 최종 메타데이터를 확정합니다. 상위 작업은 DB 상태 기반 오케스트레이터가 추적하고, 병목 구간에만 메시지 큐를 도입하는 2단계 전략을 택했습니다.

  • 키는 기관 · 콘텐츠 · 버전별로 키 관리 서비스에서 생성하며 외부 키 등록 API를 두지 않습니다. 암호화기는 평문 키를 일시 사용 후 폐기합니다.
  • 작업은 claim / lease / attempt 모델로 재시도와 멱등성을 보장합니다. 같은 결과를 다시 보내면 같은 응답이고, 다른 결과면 409로 거절합니다.
  • 뷰어는 iOS(PDFium / PDFKit 듀얼 엔진, SPM 패키지), Android(Readium Kotlin 기반), Web 세 플랫폼을 분절 문서 포맷에 맞춰 직접 구현합니다.
05 · INFRASTRUCTURE & OPERATIONS

관리형 Kubernetes + GitOps, 설정은 SSOT에서 생성

클러스터 작업은 스크립트로만 하고, 설정 파일은 한 곳에서 만들어 어긋나면 push를 막습니다.

  • Managed Kubernetes (AWS)
  • GitOps · environment overlays
  • Layer isolation
  • Externalized secrets
  • Distributed tracing
  • Config SSOT generation
  • pre-push gate
  • Plan · dry-run · rollback
  • Local parity stack
구조와 근거 보기

AWS 관리형 Kubernetes 위에 계층(프론트, API, 인증, 도메인)을 격리하고 환경별 오버레이로 설정을 관리합니다. 비밀값은 외부 비밀값 저장소에서 런타임에 주입하며 Git에 두지 않습니다. 환경변수는 SSOT 매트릭스 한 곳에서 38개 워크로드의 설정을 생성하고, 생성물과 손편집이 어긋나면 pre-push 게이트가 push를 거부합니다.

  • 배포는 계획 단계에서 배포본과 main 사이의 DB 변경 요구를 먼저 세고, dry-run 뒤에 실행합니다. 되돌리기와 이력 조회가 같은 스크립트에 있습니다.
  • 이미지 태그는 날짜와 커밋 해시로 고정하며 커밋 지정이 필수입니다.
  • 로컬에서도 같은 컨테이너 24개를 띄워 클러스터와 동일 경로로 검증합니다.

STACK

기술 스택

언어 · 런타임Kotlin (JVM)
프레임워크Spring Boot, Spring WebFlux, Kotlin Coroutines + Flow
데이터관계형 DB (읽기 · 쓰기 분리), 논블로킹 DB 접근 (R2DBC), 2단 캐시 (인메모리 + 분산)
메시징 · 저장메시지 큐, 객체 저장소, 키 관리 서비스 (AWS)
인증OAuth2 / OIDC, 비대칭 서명 JWT, M2M Client Credentials
콘텐츠 · DRMPDF / EPUB Normalizer, Readium LCP, 미디어 패키징, 이미지 암호화
프론트 · 뷰어React 기반 웹, Swift (iOS SDK), Kotlin (Android SDK), Web viewer
인프라AWS 관리형 Kubernetes, GitOps 오버레이, 외부 비밀값 저장소, 분산 추적
품질자체 아키텍처 린터, 계약 테스트, 컨테이너 기반 통합 테스트

같은 방식으로 기관의 플랫폼을 만들 수 있습니다.

프로젝트 문의