5.3 KiB
5.3 KiB
title, source_type, status, branch, related_projects, tags, created, updated
| title | source_type | status | branch | related_projects | tags | created | updated | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| interview / spring-jpa-flyway-initialization-lifecycle-circular-dependency | interview-prep | raw | feature-build-release-supply-chain-contract |
|
|
2026-06-23 | 2026-06-23 |
Spring Boot에서 Flyway와 JPA(EntityManagerFactory) 초기화 순환 참조 및 해결 전략
Parent
- Parent branch note: raw/branch-notes/feature-build-release-supply-chain-contract
면접 질문 및 핵심 답변
Q1. Spring Boot 애플리케이션 기동 시, Flyway 마이그레이션과 JPA(Hibernate) 초기화 중 어느 것이 먼저 실행되어야 하며 그 이유는 무엇입니까?
답변:
- 실행 순서: Flyway 마이그레이션이 항상 JPA 초기화보다 먼저 실행되어야 합니다.
- 이유: JPA의
EntityManagerFactory가 초기화되는 과정에서 엔티티 매핑 정보를 바탕으로 데이터베이스 스키마 검증(Hibernateddl-auto: validate또는update)을 수행하거나, 영속성 컨텍스트를 구성하기 때문입니다. 만약 최신 테이블 정의나 변경 사항(DDL)이 데이터베이스에 먼저 반영되어 있지 않다면, JPA 초기화 단계에서 테이블/컬럼 부재로 인해SchemaManagementException등의 예외를 던지며 애플리케이션 기동이 실패하게 됩니다. - Spring Boot의 처리: Spring Boot는 이를 보장하기 위해
flywayInitializer빈을entityManagerFactory빈보다 먼저 생성하도록 자동 구성(DependsOn)합니다.
Q2. JPA 설정 클래스(@Configuration) 내에서 일반(인스턴스) @Bean 메서드로 FlywayConfigurationCustomizer를 정의했을 때 순환 참조(Circular Dependency) 에러가 발생하는 메커니즘을 설명하고, 이를 해결하기 위한 static @Bean 적용 원리를 설명해 주세요.
답변:
-
순환 참조 발생 메커니즘:
- Spring Boot가 스키마 마이그레이션을 수행하기 위해
flywayInitializer빈 생성을 시작합니다. - 이 과정에서 커스텀 Flyway 설정을 반영하고자 컨테이너에 등록된 모든
FlywayConfigurationCustomizer빈들을 찾습니다. - 만약 이 Customizer 빈이 설정 클래스(
@Configuration) 내에 일반@Bean메서드로 선언되어 있다면, Spring은 이 메서드를 호출하기 위해 먼저 부모 설정 클래스의 인스턴스를 생성해야 합니다. - 부모 설정 클래스 인스턴스화 과정에서 내부에 선언된 영속성 필드(
@PersistenceContext EntityManager)나 JPA 관련 종속성 빈 주입을 시도합니다. - 이를 주입하려면
entityManagerFactory빈이 먼저 완성되어 있어야 하므로 JPA 초기화를 트리거합니다. - 하지만
entityManagerFactory는 스키마 보장을 위해flywayInitializer가 끝날 때까지 대기(DependsOn)하므로,flywayInitializer->Customizer->Configuration->EntityManagerFactory->flywayInitializer로 이어지는 데드락성 순환 참조가 발생합니다.
- Spring Boot가 스키마 마이그레이션을 수행하기 위해
-
static @Bean을 통한 해결 원리:- Spring 프레임워크는
@Configuration클래스 내에 선언된static @Bean메서드를 로드할 때, 부모 클래스의 인스턴스 생성 없이 클래스 정의 자체에서 직접 정적 메서드를 호출하여 빈을 등록합니다. - 따라서,
FlywayConfigurationCustomizer가static으로 정의되면 부모 설정 클래스의 인스턴스화 및 그에 딸린@PersistenceContext EntityManager주입 처리가 뒤로 지연(Defer)됩니다. - 이 덕분에 Flyway 초기화가 아무런 JPA 간섭 없이 완료되고, 그 이후에 비로소 설정 클래스 인스턴스화 및
entityManagerFactory구성이 순차적으로 완료되면서 순환 참조 고리가 완벽히 해소됩니다.
- Spring 프레임워크는
Q3. PostgreSQL 환경에서 엔티티의 대용량 텍스트 필드를 매핑할 때, @Lob 어노테이션을 쓰면 발생하는 문제와 클린 아키텍처 관점에서의 대안은 무엇입니까?
답변:
- 문제점:
- Hibernate는 PostgreSQL 환경에서
@Lob어노테이션이 붙은String필드를 일반text컬럼이 아니라oid(Large Object 식별자인 숫자형) 타입으로 매핑하려고 시도합니다. - 이로 인해 Flyway 스크립트에서 선언한 실제 데이터 타입인
text와 불일치가 발생합니다. - 개발 환경에서
ddl-auto: update가 켜져 있으면 Hibernate가 기존text컬럼을oid타입으로 변환하려고alter table alter column ... set data type oid쿼리를 던지고, PostgreSQL이 이 묵시적 캐스팅을 거부해column cannot be cast automatically to type oid에러를 유발하며 실행이 중단됩니다.
- Hibernate는 PostgreSQL 환경에서
- 대안:
@JdbcTypeCode(SqlTypes.LONGVARCHAR)사용:- 특정 데이터베이스 벤더에 종속적인
@Column(columnDefinition = "text")기술은 클린 아키텍처의 DB 이식성 원칙(ArchUnit 제약 조건)을 위반합니다. - 반면
@JdbcTypeCode(SqlTypes.LONGVARCHAR)는 JDBC 표준 레벨의 대용량 가변 길이 문자열 힌트를 주어, PostgreSQL 환경에서는 안전하게text컬럼에 매핑되면서도 다른 DB(Oracle, H2 등)로 전환했을 때 벤더 종속성 없이 포터블한 DDL 매핑을 유지해 줍니다.