로컬, 개발 서버, 배포서버의 각 설정이 모두 다르기 때문에 매 번 설정값을 바꿔주는 작업을 자동화 해줄 수 있다.
개발할 때는 IDE에서 그냥 실행하면 되고 개발하다가 바로 개발 서버 혹은 배포 서버로 옮기는 작업을 간단히 하기 위해 Profile을 설정한다.
Profile의 설정 흐름은 먼저 Spring Boot의 설정 값 파일은 application.properties를 여러 개로 나눈다고 생각하면 된다. 먼저 폴더 구조는 아래와 같다.
위와 같이 resource폴더를 3개로 만들어서 -local은 로컬 서버 설정, -prod는 릴리즈 서버 설정을 담고 두 설정이 겹치는 부분은 application.properties에 작성해준다.
이제 환경에 따라 resource 폴더안에 로그 설정, 캐시 설정, applicaiton.properties 등 원하는 설정 값을 넣어주면 된다.
만약 resource와 resource-??? 설정이 겹치는 기본적으로 ???의 설정이 된다.(중복되는 설정도 이 후에 gradle에서 방법을 지정해줄 수 있다.)
build.gradle에 아래와 같은 설정들을 추가해준다.
def profile = project.hasProperty("profile") ? project.property("profile").toString() : "local"
println "profile : $profile"
sourceSets {
main {
resources {
srcDirs("src/main/resources", "src/main/resources-$profile")
}
}
}
tasks {
processResources {
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE
}
}
코드를 설명하자면
def profile = project.hasProperty("profile") ? project.property("profile").toString() : "local"
println "profile : $profile"
이 부분은 먼저 빌드 커맨드에서 설정해준 profile 값을 읽어온다. 로깅을 위해 어떤 profile로 실행되는지 콘솔에 출력도 해준다.
sourceSets {
main {
resources {
srcDirs("src/main/resources", "src/main/resources-$profile")
}
}
}
이 부분은 어떤 리소스들을 사용할지 정해준다. 위에서 읽어온 profile
값을 통해 resoruce 폴더와 profile에 맞는 리소스 폴더 둘을 모두 사용하도록 해준다.
tasks {
processResources {
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.INCLUDE
}
}
이 부분은 위에서 언급했던 설정의 중복에 대한 처리이다. 일반적으로 INCLUDE를 사용하며 다양한 옵션이 있다.
그리고 빌드 커맨드에 프로파일에 대한 환경 변수 값을 아래와 같이 추가해준다.
./gradlew build -Pprofile=prod
이렇게 하면 로컬에서는 설정 파일 변경시에는 간단하게 application.properties의 spring.profiles.active 값만 변경해서 사용하면 되고 배포시에는 buildspec.yml에 등록된 옵션에 의해 자동으로 prod 설정으로 배포가 된다.
IDE에서 설정 파일을 바꾸는 방법도 중요하다. 결국 개발은 로컬에서 이루어지고 일반적으로 IDE의 RUN 버튼을 통해서 서버를 켰다 끄기 때문이다.
먼저 intellij 우측 상단의 실행 버튼 좌측에서 Edit Configurations을 선택한다.
그리고 위와 같이 Run command쪽에 -Pprofile을 설정하고 저장해준다. 이와 같이 각 profile에 맞는 RUN 버튼을 추가해주면 간단하게 설정을 변경하면서 개발할 수 있다.
폴더 구조는 Gradle과 똑같이 한다. 그리고 pom.xml에 아래와 같은 설정을 추가해준다.
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment>local</environment>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<filtering>true</filtering>
<directory>src/main/resources-${environment}</directory>
</resource>
</resources>
</build>
최초에 옵션에 따라 설정된 environment
로 읽을 리소스를 분기해준다.
mvn install -P local/prod
mvn spring-boot:run -P local/prod
이제 mvn 커맨드를 통해 -P 옵션으로 실행환경을 정해주고 실행하면 서로 다른 설정 파일을 사용할 수 있다.
인텔리제이에서 바로 실행을 하려면 우측 상단 edit configuration에 위와 같은 커맨드와 옵션을 넣어주면 간단하게 IDE에서 실행할 수 있다.
로컬과 운영 서버의 설정은 다를 수 밖에 없는데 하나의 설정 파일로 바꿔가며 하는 것은 굉장히 귀찮은 일이었고 만약 실수로 다른 설정 값으로 배포를 한다면 정말 큰 피해가 될 수 있다.
특히 JPA나 BATCH 설정의 ddl-auto 옵션은 정말 조심해야하고 실수로 운영서버에 create 옵션으로 주었다가 난리가 난 적이 있다는 개발자 유튜브에 영상을 보고 다시 한 번 profile 설정 값의 필요성을 느꼈다. 물론 ddl-auto는 운영이고 로컬이고 모두 none으로 주고 Entity와 DB Schema 둘 다 직접 하려고 한다.
복잡하거나 어렵진 않지만 귀찮아서 계속 미뤄왔던 profile 설정에 관련된 부분을 정리해보았다.(설정값 바꿔가는게 더 귀찮았을텐데...) IDE로 개발할 때는 적당히 설정 값 바꿔가며 실행시키고 배포 할 때는 됐다 싶으면 바로 푸시하면 운영 설정으로 배포된다는 사실이 너무 편하다.