Healthcare / MSA
KoNECT 국가 임상시험관리 시스템 구축
- Java 17
- Spring Boot 3.1
- Spring Security
- Spring Cloud Gateway
- Eureka
- OpenFeign
- MyBatis
- PostgreSQL
- RabbitMQ
- Docker
- K3s
- Jenkins
Overview
병원 내 임상시험의 계획부터 수행, 문서화까지 전 과정을 디지털화한 임상시험 관리 시스템을 신규 구축했습니다. 병원별 필요한 모듈만 선택적으로 배포하는 요구사항으로 서비스 단위 분리가 설계의 전제 조건이었으며, 백엔드 단독으로 13개 마이크로서비스 설계, DDD + 헥사고날 아키텍처 기반 비즈니스 모듈 구현, SaaS와 온프레미스 두 가지 배포 환경 대응이 핵심 과제였습니다.
Problem
- 병원별 모듈 선택 배포 요구사항으로 서비스 단위 분리가 필요했습니다.
- SaaS와 온프레미스 두 가지 배포 환경을 모두 지원해야 했고, 폐쇄망 병원 환경에서는 단순 독립 배포가 필요했습니다.
- 마이크로서비스 간 인증, 이벤트 통신, 감사 추적, 도메인 모듈 경계를 동시에 설계해야 했습니다.
My Ownership
- 프로젝트 리드로 인프라 구축, 13개 MSA 설계, 전 도메인 백엔드 개발을 담당했습니다.
- API Gateway와 서비스별 경량 필터를 조합한 이중 JWT 인증 구조를 설계했습니다.
- RabbitMQ 비동기 이벤트, 이벤트 스토어, DDD + 헥사고날 기반 비즈니스 모듈을 구현했습니다.
Key Decisions
병원별 모듈 선택 배포와 SaaS 환경의 구성 차별화를 위해 운영 복잡도 증가를 감수하고 서비스 단위 분리를 선택했습니다.
Gateway에서 1차 차단하고, 독립 실행되는 서비스도 자체 토큰 검증으로 인증 주체를 보장하도록 구성했습니다.
SaaS는 경량 오케스트레이션으로 운영하고, 폐쇄망 병원은 docker save/load 기반 독립 배포가 가능하도록 했습니다.
소규모 분산 시스템에서 Kafka 대비 운영 복잡도가 낮고 서비스 간 비동기 이벤트 통신 수단으로 적합했습니다. 감사·이벤트 추적은 별도 이벤트 스토어 모듈에서 전담했습니다.
복잡한 조회 요구사항과 팀 규모를 고려하면 DB 분리의 관리 복잡도가 더 컸습니다. 서비스 수가 적어 커넥션 풀 고갈 리스크는 낮다고 판단했고, 확장 시 PgBouncer 도입을 고려했습니다.
Implementation
MSA 인프라
사내 프라이빗 Docker 레지스트리, Spring Cloud Eureka, API Gateway, Jenkins + Jib 기반 이미지 빌드·배포 파이프라인을 구축했습니다.
RabbitMQ 이벤트 처리
역직렬화, 검증, 실행 흐름을 공통 처리 클래스로 추상화하고 실패 유형에 따라 IGNORE, NACK, DLQ 라우팅 기준을 분리했습니다.
도메인 모듈
연구, 디자인·스케줄, 연구대상자, 연구자, 파일, 사용자·권한, 알림, 통계, 스케줄러 모듈을 DDD + 헥사고날 구조로 구현했습니다.
Detailed Notes
MSA 인프라와 CI/CD
- 사내 프라이빗 Docker 레지스트리를 구축해 외부 퍼블릭 레지스트리 의존 없이 사내 이미지를 관리했습니다.
- Spring Cloud Eureka 서비스 디스커버리와 API Gateway로 단일 진입점 및 인증 처리 통합을 제공했습니다.
- Jenkins + Jib 기반으로 코드 푸시 → 이미지 빌드 → 레지스트리 푸시 → 배포 파이프라인을 구성했습니다.
| SaaS 환경 (K3s) | 온프레미스 환경 (Docker Compose) |
|---|---|
| K8s 대비 경량화해 운영 복잡도를 줄이고 멀티 노드 확장이 가능하도록 구성했습니다. | 폐쇄망 병원 환경에서 오케스트레이션 없이 단순 구성하고, docker save/load로 이미지를 전달해 7개 병원 독립 배포를 지원했습니다. |
API Gateway + 서비스 경량 필터 이중 JWT 인증
- API Gateway에서 모든 인바운드 요청의 JWT 토큰을 일괄 검증해 인증 실패 요청을 즉시 차단했습니다.
- 회원가입과 토큰 발급/재발급 같은 공개 경로는 화이트리스트로 관리했습니다.
- 인증 모듈에는 Spring Security를 적용해 토큰 검증 후 인증 주체를 Security Context에 저장했습니다.
- 일반 비즈니스 모듈에는 Servlet Filter 경량화 필터를 적용하고, 사용자 정보를 ThreadLocal에 저장해 동일 요청 스레드 내 어느 레이어에서든 인증 주체를 참조할 수 있게 했습니다.
- 필터 소멸 시점에 명시적으로 remove()를 호출해 메모리 누수를 방지했습니다.
RabbitMQ 이벤트 처리와 이벤트 스토어
- AMQP 기반 RabbitMQ 메시지 브로커로 서비스 간 비동기 이벤트 통신을 구현했습니다.
- 역직렬화 → 검증 → 실행 흐름을 공통 처리 클래스로 추상화했습니다.
- 역직렬화 실패와 유효성 검증 실패는 재처리 의미가 없어 IGNORE 처리했습니다.
- 처리 중 예외는 NACK(requeue=true)로 재처리하고 한도 초과 시 DLQ로 라우팅했습니다.
- RabbitMQ 메시지의 휘발성 문제를 보완하기 위해 이벤트 ID, 타입, 발행자, 발행시간, 페이로드를 DB에 영구 적재하는 이벤트 스토어 모듈을 설계했습니다.
DDD + 헥사고날 기반 비즈니스 모듈
| 모듈 | 핵심 구현 |
|---|---|
| 연구 | 애그리거트 내부 도메인 규칙 검증, 단계별 잠금/해제, JSONB 저장, 도메인 이벤트 발행 |
| 연구 디자인 & 스케줄 | Visit·Cycle 전략 패턴, 기준 방문일 변경 시 이후 일정 자동 재계산, 방문 윈도우 관리 |
| 연구대상자 | 선별 → 등록 → 추적관찰 → 탈락 상태 전이, ITT·PP 분석 구분, 멱등성 처리 |
| 연구자 | PI·CRC·세부 연구자 구분 관리, 연구별 배정 및 이력 추적 |
| 파일 스토어 | 단건/벌크 업로드, 엔티티 연결, ZIP 다운로드, 이미지 처리 |
| 사용자 & 권한 | RBAC, 그룹·개별 권한 통합 적용, 도메인 객체 내부 계정 잠금, AES-256 개인정보 암호화 |
| 알림 | 전략 패턴으로 이메일·SMS 분리, AWS SES + Nurigo, 건별 독립 처리 |
| 통계 | JSONB 분해 집계 쿼리, 윈도우 함수로 모집률·최근 7일 현황 산출 |
| 스케줄러 · 설정 | 예약 알림·통계 자동 발송, 병원별 공통 코드 및 기준 데이터 관리 |
Result / Impact
- 백엔드 단독으로 13개 마이크로서비스를 설계하고 전 도메인을 개발했습니다.
- 전국 7개 병원 온프레미스 독립 배포와 SaaS 배포 환경을 모두 지원했습니다.
- 이벤트 스토어 기반 감사·추적 체계를 구축하고 도메인 중심 테스트 커버리지를 강화했습니다.