Flyway에서 운영 환경 SQL 파일과 Test 환경 SQL을 분리하는 법 - FlywayException: Found more than one migration

Syntax error in SQL statement "ALTER TABLE goals\000a    ADD COLUMN group_id UUID[*],\000a    ADD CONSTRAINT fk_goal_group\000a        FOREIGN KEY (group_id)\000a            REFERENCES groups(id)"; SQL statement:
ALTER TABLE goals
    ADD COLUMN group_id UUID,
    ADD CONSTRAINT fk_goal_group
        FOREIGN KEY (group_id)
            REFERENCES groups(id) [42000-232]

 

운영 환경에서는 PostgreSQL, 테스트 환경에서는 H2를 사용합니다.

테스트 코드 작성 시 flyway 마이그레이션 파일이 실행되는데, 위와 같은 오류가 났습니다. 이는 ALTER문을 함께 사용하는 구문이 지원되지 않아 발생하는 오류였습니다.

 

일반적으로 생각해볼때 그러면 사용 불가한 구문만 수정하면 되는 거 아니야,싶겠지만 flyway에서는 그게 쉽지가 않죠.

 

특히 저 구문은 이미 배포 환경에 반영되어 있는 상황이었습니다.

 

크게는 세 가지 방법이 있습니다.

- 배포 환경의 db 삭제하기....

- 해당 버전을 수정하고, flyway table에서 v8 Row 삭제 + 이미 반영된 해당 버전 sql 롤백

- 테스트 환경 SQL 분리하기

 

1번은 현실적이지 않으니 차치하고, 2번과 3번 중에 골라야 합니다.

하지만 2번도 상당히 위험합니다.

flyway Row만 삭제하는 것 뿐만 아니라,롤백 SQL까지 날려야하며, 해당 버전 이후에 추가된 버전들이 있다면 위험성이 증가됩니다.

예를 들어 테스트 코드에서 v8 버전의 SQL이 동작하지 않는 상황인데, 이미 버전이 v13까지 추가되어있다면 v8부터 v13까지의 SQL을 롤백해줘야 합니다. (flyway에서는 실행하려고 하는 SQL이 이미 실행되어있다면 오류가 나기 때문)

 

그래서 저는 테스트 환경의 Flyway 마이그레이션 파일을 분리하는 방법을 선택하였습니다.

이유는 아래와 같습니다.

1. 다른 방안 사용 시 '테스트 코드'의 정상 동작을 위해 운영 환경에 너무 많은 위험성이 추가된다.

2. db를 다르게 사용한다면 앞으로도 위와 같은 일이 발생할 확률이 높다.

 

다만 이렇게 되면 SQL문을 중복 관리해줘야 하고, 테스트 코드와 운영 환경의 100% 동일한 환경을 보장하게 되지 못하게 됩니다.

 

Test 환경 Flyway Migration File 분리 방법

1. test 폴더에 resorce/test-db/migration을 추가해줍니다.

test-db의 폴더명은 메인과 중복되어선 안됩니다. (그래서 test를 붙여주었습니다.)

현재 src/main/resources/db/migration에 메인의 migration 파일이 들어있는데, test code의 경우도 resources/db/migration과 동일한 경로에 두개 되면 읽어올 때 둘 다 읽어오게 되어서 Caused by: org.flywaydb.core.api.FlywayException: Found more than one migration with version 8 에러를 내게 됩니다.

 

2. src에 있던 migration 파일을 복사 붙여넣기 합니다. 위처럼 테스트코드에서 동작 안 하는 경우의 코드만 수정해줍니다.

 

3. resorce 폴더에 application-test.yml을 추가합니다.

spring:
  flyway:
    locations: classpath:test-db/migration
  jpa:
    properties:
      hibernate:
        auto_quote_keyword: true

logging:
  level:
    org.flywaydb: DEBUG
    org.springframework.boot.autoconfigure.flyway: DEBUG

classpath는 위에서 말했다시피 main과 동일하게 사용되지 않도록 주의해줍니다.

저는 auto_quote_keyword도 추가해주었습니다. 

 

4. 최종 경로

 

마무리하며

혹시 피드백 주실 게 있다면 댓글로 부탁드립니다. 감사합니다.