본문으로 건너뛰기

인프라

백엔드는 여러 플랫폼 서비스를 의존하지만, 여전히 하나의 Spring Boot 애플리케이션으로 실행됩니다. 이 페이지는 코드 동작을 형성하는 백엔드 관점의 런타임 계약을 다룹니다. 클러스터 운영이나 day-2 runbook은 의도적으로 다루지 않습니다.

이 페이지는 레퍼런스 문서입니다.

소스 경로

경로역할
app/src/main/resources/application.yaml데이터 소스, Flyway, Redis, RabbitMQ, MinIO, 워커 URL, CORS, rate limit, OpenAPI, actuator를 포함한 주 런타임 설정
app/src/main/resources/application-dev.yml쿠키 SameSite 같은 dev 전용 재정의
app/src/main/java/com/lumie/app/config/RoutingDataSourceConfig.javaprimary/readonly Hikari pool과 Flyway migrator data source
app/src/main/java/com/lumie/app/config/RuntimeDbRoleGuard.javaRLS를 우회할 수 있는 DB role을 막는 startup guard
app/src/main/java/com/lumie/app/config/ShedLockConfig.java분산 scheduler locking
app/src/main/java/com/lumie/app/config/CorsConfig.javaCORS 계약
app/src/main/java/com/lumie/app/config/ratelimit/RateLimitFilter.java프로세스 내부 rate limiting
modules/exam/src/main/java/com/lumie/exam/adapter/out/config/*exam 모듈이 소유하는 RabbitMQ, RestClient, MinIO 인프라
modules/auth/src/main/java/com/lumie/auth/adapter/out/persistence/RedisTokenRepository.javaauth의 Redis persistence 계약
modules/file/src/main/java/com/lumie/file/adapter/out/storage/MinioStorageAdapter.javafile-service object storage 계약
modules/billing/src/main/java/com/lumie/billing/adapter/out/external/*billing의 외부 제공자 adapter

런타임 토폴로지

의존성 계약

의존성구성 인터페이스주요 백엔드 소유자계약 메모
PostgreSQLapp.datasource.*, spring.flyway.*모든 모듈shared-schema RLS, Modulith outbox, ShedLock, primary/readonly pool
RabbitMQspring.rabbitmq.*주로 examqueue 기반 grading 및 report 워크플로
Redisspring.data.redis.*주로 authrefresh 토큰, blacklist, 세션 index
MinIOminio.*exam, file, tenantOMR object, presigned upload, 파일 메타데이터, 테넌트 logo
grading-svclumie.services.grading.urlexam직접 HTTP grading과 queue 콜백 생태계
report-svclumie.services.report.urlexam직접 HTTP report 생성과 queue 콜백 생태계
chatbot-svclumie.services.chatbot.urlai외부로는 HTTP streaming proxy, 내부로는 HMAC 콜백 인터페이스
Toss Paymentsbilling config와 제공자 secretbilling실제 구현된 HTTP integration
Popbill tax invoice pathbilling config와 제공자 secretbilling현재 코드는 완전한 실서비스 연동이 아니라 stub adapter

데이터베이스 및 마이그레이션 인프라

읽기/쓰기 분리

RoutingDataSourceConfig는 다음을 선언합니다.

  • app.datasource.primary.*
  • app.datasource.readonly.*
  • LazyConnectionDataSourceProxy로 감싼 RoutingDataSource

라우팅 규칙:

  • @Transactional(readOnly = true) -> readonly pool
  • write transaction 또는 비트랜잭션 접근 -> primary pool

Flyway는 별도 자격 증명으로 실행됨

Flyway는 런타임 애플리케이션 pool credential을 사용하지 않습니다. 백엔드는 primary URL과 spring.flyway.user/password로 전용 @FlywayDataSource를 만들기 때문에, DDL은 table 소유 권한으로 실행하고 런타임 트래픽은 제한된 lumie_app role에 머무를 수 있습니다.

런타임 DB 역할 가드

RuntimeDbRoleGuard는 활성 런타임 role이 다음 중 하나면 startup을 실패시킵니다.

  • SUPERUSER
  • BYPASSRLS

이것은 운영 취향이 아니라 백엔드 안전 불변식입니다.

비동기 및 스케줄러 인프라

  • Spring Modulith는 public.event_publication에 outbox row를 저장
  • spring.modulith.events.completion-mode=delete
  • spring.modulith.events.republish-outstanding-events-on-restart=true
  • ShedLock은 public.shedlock 사용
  • @EnableAsync가 애플리케이션에 켜져 있고, Spring이 관리하는 async 실행은 테넌트-aware task decorator를 받음

중요한 경계 세부사항:

  • Spring이 관리하는 async 작업은 컨텍스트 전파를 자동으로 받음
  • AI 모듈의 전용 chat executor 같은 custom executor는 context를 수동으로 다시 세팅해야 함

오브젝트 스토리지와 외부 HTTP

MinIO

  • exam은 두 개의 MinIO client를 사용합니다. 하나는 internal 엔드포인트용, 다른 하나는 minio.external-endpoint를 쓰는 presign 클라이언트입니다.
  • file은 업로드, 다운로드, presigned URL에 MinIO를 사용합니다.
  • tenant는 logo object에 MinIO를 사용합니다.
  • FileServiceAdapter는 database 커밋 이후에만 MinIO object를 삭제합니다.

워커 및 제공자 HTTP

  • exam은 외부 호출 로깅과 명시적 timeout이 있는 RestClient를 사용합니다.
  • OmrServiceClient는 읽기 타임아웃을 90s로 재정의합니다.
  • ai는 uvicorn 호환성을 위해 chatbot-svc 트래픽을 HTTP/1.1에 고정합니다.
  • billing 제공자 호출은 의도적으로 긴 트랜잭션 바깥에 둡니다.

HTTP 인터페이스와 백엔드 가드

application.yaml과 app config 기준:

  • OpenAPI: /v3/api-docs
  • Swagger UI: /swagger-ui.html
  • CORS origin: production, dev, 그리고 로컬 http://localhost:3000
  • multipart 제한: 파일당 5MB, 요청당 25MB
  • graceful shutdown timeout: 30s
  • actuator 노출: health, info, prometheus, metrics
  • 선택된 POST route에 대한 per-IP 프로세스 내부 rate limiting

RequestContextFilter는 또한 다음을 제공합니다.

  • 생성되거나 전달된 X-Request-Id
  • request ID, 테넌트, user, 선택적 trace ID에 대한 MDC 채움

현재 드리프트와 유의사항

  • billing 모듈에는 실제 Toss integration이 있지만, PopbillTaxInvoiceClient는 여전히 synthetic success 응답을 반환하고 warning을 남기는 stub입니다.
  • RabbitMQ topology는 백엔드 Java config에서 선언되지 않습니다. 백엔드 코드는 queue와 policy가 이미 존재한다고 가정하고 application layer bean만 연결합니다.

검증 명령어

cd /Users/bluemayne/Projects/Lumie/lumie-backend
./gradlew :app:test
./gradlew :modules:exam:test
./gradlew :modules:auth:test
./gradlew integrationTest

가장 관련 있는 테스트:

  • app/src/test/java/com/lumie/app/config/RoutingDataSourceIntegrationTest.java
  • app/src/test/java/com/lumie/app/config/RuntimeDbRoleGuardTest.java
  • app/src/test/java/com/lumie/app/migration/MigrationsRlsIntegrationTest.java

관련 페이지