본문으로 건너뛰기

인프라

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

이 페이지는 reference 문서입니다.

소스 경로

Path역할
app/src/main/resources/application.yaml데이터 소스, Flyway, Redis, RabbitMQ, MinIO, worker URL, CORS, rate limit, OpenAPI, actuator를 포함한 주 런타임 설정
app/src/main/resources/application-dev.ymlcookie SameSite 같은 dev 전용 override
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의 외부 provider adapter

런타임 토폴로지

의존성 계약

DependencyConfig surface주요 백엔드 소유자계약 메모
PostgreSQLapp.datasource.*, spring.flyway.*모든 모듈shared-schema RLS, Modulith outbox, ShedLock, primary/readonly pool
RabbitMQspring.rabbitmq.*주로 examqueue 기반 grading 및 report workflow
Redisspring.data.redis.*주로 authrefresh token, blacklist, session index, OAuth2 nonce 저장
MinIOminio.*exam, file, tenantOMR object, presigned upload, 파일 메타데이터, tenant logo
grading-svclumie.services.grading.urlexam직접 HTTP grading과 queue callback 생태계
report-svclumie.services.report.urlexam직접 HTTP report 생성과 queue callback 생태계
chatbot-svclumie.services.chatbot.urlai외부로는 HTTP streaming proxy, 내부로는 HMAC callback surface
OAuth provideroauth2.*authGoogle, Kakao, Naver 로그인 흐름
Toss Paymentsbilling config와 provider secretbilling실제 구현된 HTTP integration
Popbill tax invoice pathbilling config와 provider 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 실행은 tenant-aware task decorator를 받음

중요한 경계 세부사항:

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

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

MinIO

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

Worker 및 제공자 HTTP

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

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, tenant, 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

관련 페이지