DB 테이블 관리를 한다면, pgAdmin을 켜서 수동으로 쿼리를 실행하면 되긴 하다. 하지만 단점으로는 컬럼을 추가할 때마다 또 다시 pgAdmin을 켜서 수동으로 쿼리를 실행해야한다. 또한 만약 다른 팀원이 있다면 그 사람도 추가된 컬럼을 추가하기 위해 똑같이 수동으로 쿼리를 실행해야한다. 마지막으로는 실수하기가 쉽고, 버전 관리가 안된다는 점이다.
그래서 나온 대안이 Flyway를 통해서 자동으로 DB를 관리하는 방법이다.
첫번째, 이렇게 하면 DB 변경 이력을 코드처럼 관리하게 된다.
두번째, 우리가 만든 DDL 스크립트를 따로 보관하지 않아도 되고, SQL파일로 저장해서 프로젝트 안에 들어있게 된다.
세번째, Spring Boot가 실행될 때, Flyway가 자동으로 이 SQL 파일을 읽어서 DB에 적용해준다.
네번째, 나중에 컬럼을 추가할 땐, 버전 업된 SQL파일을 새로 만들면 된다.
결과로 Git에 코드만 받아도, Spring Boot를 실행하는 즉시 모든 팀원의 DB가 최신 상태로 똑같이 맞춰진다.
이전에 팀프로젝트를 할 때, 매번 달라지는 DB에 버전을 맞춘다고 매번 SQL을 공유해서 맞췄던 기억이 있는데, Flyway를 알았더라면 이 추가적인 작업이 없었어도 되었다는 생각에 아쉬운 마음이 든다.
지금이라도 알았으니 다행인가?
어쨌든 그런 귀찮은 작업과 바이바이하기 위해 이번에 Flyway를 사용하게 되었다.
이번엔 진짜 DB를 연결해서 쓸거라, h2database는 의존성에서 빼버리고 새로운 의존성을 build.gradle에 추가했다.
// 1. Flyway Core 라이브러리 추가
implementation 'org.flywaydb:flyway-core'
// 2. PostgreSQL 드라이버 (JPA를 쓴다면 이미 있어야 합니다)
runtimeOnly 'org.postgresql:postgresql'
그리고 application.properties에도 아래와 같이 추가하여 Flyway를 설정해준다.
# 1. DB 접속 정보 (JPA와 Flyway가 공용으로 사용)
spring.datasource.url=jdbc:postgresql://localhost:5432/dreamshow_db
spring.datasource.username=dreamshow_user
spring.datasource.password=0000
spring.datasource.driver-class-name=org.postgresql.Driver
# 2. JPA(Hibernate) 설정
# Flyway가 DDL을 담당하므로 Hibernate의 자동 생성/수정 기능을 끈다.
spring.jpa.hibernate.ddl-auto=none
# (개발 중 쿼리 확인을 위한 선택 사항)
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
# 3. Flyway 설정
spring.flyway.enabled=true
spring.flyway.baseline-on-migrate=true
spring.flyway.locations=classpath:db/migration
이렇게 의존성을 추가하고, DDL 스크립트 파일을 src/main/resources/db/migration에 V1__Create_Initial_Tables.sql이라는 이름으로 만들어주었다. 파일 이름에도 의미가 있는데,
이런 의미이다.
스크립트 파일에 테이블들을 생성하는 DDL을 다 작성해 넣은 후, Spring Boot 애플리케이션을 실행해보면 아래 순서로 실행이 된다.
이제 다시 실행하면, Flyway가 9번 단계에서 "V1은 이미 실행됐음"을 확인하고 다음 버전을 찾기 때문에 테이블 생성 스크립트가 중복 실행되지 않는다.
그럼 이제 나중에 테이블을 수정하게 된다면 db/migration 폴더에 새로운 버전의 파일(예: V2__Add_User_Nickname.sql)을 만들고 해당 파일에 테이블을 수정하는 DDL을 써넣는다. 그러고 Spring Boot를 실행하면 Flyway가 V1은 그대로 놔두고 V2.sql만 실행해준다.
실제로 실행해보니, 경고문이 하나 떴다.
2025-10-24T14:43:43.551+09:00 WARN 6472 --- [ main ] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
의미는 "데이터베이스 연결을 뷰(View)가 렌더링 될 때까지 열어둔다"라는 뜻이다.
이렇게 열려있으면 나중에 API를 만들 때 DTO를 쓰지 않고 Entity를 실수로 그대로 반환하면, 불필요한 DB 쿼리가 마구 날아가(N+1 문제) 성능이 심각하게 저하될 수 있다. 또한 DB 커넥션을 너무 오래 잡고 있게 되어, 사용자가 몰리면 커넥션 풀이 고갈될 수도 있다.
이번 프로젝트에서는 Next.js가 뷰를 담당하는 API 서버라서, 이 옵션은 꺼야한다.
그래서 해결 방법은 application.properties 파일에
# OSIV(Open Session In View) 기능 끄기 (성능 최적화)
spring.jpa.open-in-view=false
이렇게 설정하여 기능을 끌 수 있다.
이렇게 설정하면 DB 작업은 반드시 @Service 계층 안에서 DTO로 변환하여 끝내도록 강제할 수 있어, 더 깔끔하고 성능 좋은 코드를 작성하게 된다.