이번 주 토요일, 팀 프로젝트를 배포하기 전에 개인적으로 배포 연습을 시작했어요. AWS의 Elastic Beanstalk와 같은 배포 환경에서 작업을 하다 보니, 환경별 설정 파일을 수동으로 수정해야 하는 과정에서 불편함을 겪게 되었습니다. 특히, YML 파일을 환경마다 수정하는 일이 번거롭고 실수할 가능성이 많다는 점이 문제였습니다.
배포 작업을 하면서, 각 환경(개발, 프로덕션 등)마다 환경 설정을 바꾸는 일이 빈번하게 발생했어요. 그때마다 수동으로 YML 파일을 수정하고 다시 배포를 해야 하는데, 이 과정에서 실수도 할 수 있고, 설정을 잊거나 잘못 적용할 위험도 있었습니다.
이 문제를 해결하기 위해, 멀티 환경 설정 방식을 도입하기로 했습니다. 이 방식은 각 환경(개발, 프로덕션 등)에 맞는 설정 파일을 나누어두고, 환경별로 자동 적용되도록 설정하는 방법입니다. 구체적으로는, 환경별 프로파일을 활용하거나, application-{profile}.yml 형식으로 파일을 나누어 관리할 수 있도록 했어요. 이렇게 하면, 각 환경에서 필요한 설정을 자동으로 적용할 수 있어 수동 수정의 불편함을 크게 줄일 수 있죠.
개인 프로젝트를 배포하는 과정에서, AWS 환경에 맞춰 배포 설정을 수정하는 데 불편함을 느꼈습니다. 특히, 각 환경에 맞는 설정을 수동으로 수정해야 하므로 번거롭고 실수할 가능성이 컸습니다. 이를 해결하고자 멀티 환경 설정 방식을 도입하여, 환경별로 설정을 자동으로 적용할 수 있는 방법을 모색하게 되었습니다.
application.yml 파일에 여러 환경 설정을 -- 구분자로 나누어 관리하는 방법장점:
단점:
예시:
yaml
복사편집
# 기본 설정
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/pinup
---
# test 프로파일
spring:
config:
activate:
on-profile: test
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
---
# prod 프로파일
spring:
config:
activate:
on-profile: prod
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://172.17.0.2:5432/pinup
장점:
단점:
예시:
application.yml (공통 설정)spring:
application:
name: pinup
profiles:
default: local
servlet:
multipart:
enabled: true
max-file-size: 10MB
max-request-size: 10MB
springdoc:
packages-to-scan: com.colabear754.springdoc_example.controllers
default-consumes-media-type: application/json;charset=UTF-8
default-produces-media-type: application/json;charset=UTF-8
swagger-ui:
path: /springdoc.html
disable-swagger-default-url: true
display-request-duration: true
operations-sorter: alpha
server:
servlet:
context-path: /
encoding:
enabled: true
charset: UTF-8
force: true
application-local.yml (개발 환경 설정)spring:
config:
activate:
on-profile: local
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/pinup
username:
password:
jpa:
hibernate:
ddl-auto: update
show-sql: true
database: postgresql
properties:
hibernate:
format_sql: true
security:
oauth2:
client:
registration:
naver:
client-id:
client-secret:
scope:
- name
- email
client-name: Naver
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/api/members/oauth/naver
google:
client-id:
client-secret:
scope:
- profile
- email
client-name: Google
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/api/members/oauth/google
kakao:
client-id: your-kakao-client-id
client-secret: your-kakao-client-secret
scope:
- profile
- email
client-name: Kakao
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/api/members/oauth/kakao
provider:
naver:
authorization-uri: https://nid.naver.com/oauth2.0/authorize
token-uri: https://nid.naver.com/oauth2.0/token
user-info-uri: https://openapi.naver.com/v1/nid/me
user-name-attribute: response
google:
authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
user-name-attribute: sub
kakao:
authorization-uri: https://kauth.kakao.com/oauth2/authorize
token-uri: https://kauth.kakao.com/oauth2/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-name-attribute: id
cloud:
aws:
s3:
bucket: pinup
endpoint: http://127.0.0.1:4566 # LocalStack의 S3 엔드포인트 주소
region.static: us-east-1
stack.auto: false
credentials:
accessKey: test
secretKey: test
application-prod.yml (프로덕션 환경 설정)spring:
config:
activate:
on-profile: prod
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://172.17.0.2:5432/pinup
username:
password:
jpa:
hibernate:
ddl-auto: create
show-sql: true
database: postgresql
properties:
hibernate:
format_sql: true
security:
oauth2:
client:
registration:
naver:
client-id:
client-secret:
scope:
- name
- email
client-name: Naver
authorization-grant-type: authorization_code
redirect-uri: http://43.201.64.159:8080/api/members/oauth/naver
google:
client-id:
client-secret:
scope:
- profile
- email
client-name: Google
authorization-grant-type: authorization_code
redirect-uri: http://43.201.64.159:8080/api/members/oauth/google
kakao:
client-id: your-kakao-client-id
client-secret: your-kakao-client-secret
scope:
- profile
- email
client-name: Kakao
authorization-grant-type: authorization_code
redirect-uri: http://43.201.64.159:8080/api/members/oauth/kakao
provider:
naver:
authorization-uri: https://nid.naver.com/oauth2.0/authorize
token-uri: https://nid.naver.com/oauth2.0/token
user-info-uri: https://openapi.naver.com/v1/nid/me
user-name-attribute: response
google:
authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
user-name-attribute: sub
kakao:
authorization-uri: https://kauth.kakao.com/oauth2/authorize
token-uri: https://kauth.kakao.com/oauth2/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-name-attribute: id
cloud:
aws:
s3:
bucket: bucket0127
region.static: ap-northeast-2
stack.auto: false
credentials:
accessKey: AKIA47GCAGT5K52CCLVA
secretKey: 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
application-test.yml (test설정)spring:
config:
activate:
on-profile: test
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
username: sa
jpa:
show-sql: true
output:
ansi:
enabled: always
security:
oauth2:
client:
registration:
naver:
client-id:
client-secret:
scope:
- name
- email
client-name: Naver
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/api/members/oauth/naver
google:
client-id:
client-secret:
scope:
- profile
- email
client-name: Google
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/api/members/oauth/google
kakao:
client-id: your-kakao-client-id
client-secret: your-kakao-client-secret
scope:
- profile
- email
client-name: Kakao
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8080/api/members/oauth/kakao
provider:
naver:
authorization-uri: https://nid.naver.com/oauth2.0/authorize
token-uri: https://nid.naver.com/oauth2.0/token
user-info-uri: https://openapi.naver.com/v1/nid/me
user-name-attribute: response
google:
authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
token-uri: https://oauth2.googleapis.com/token
user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo
user-name-attribute: sub
kakao:
authorization-uri: https://kauth.kakao.com/oauth2/authorize
token-uri: https://kauth.kakao.com/oauth2/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-name-attribute: id
cloud:
aws:
s3:
bucket: pinup
endpoint: http://127.0.0.1:4566
region.static: us-east-1
stack.auto: false
credentials:
accessKey: test
secretKey: test
위 두 가지 방식 중에서 나는 각 프로파일별로 파일을 나누는 방식을 선택했습니다. 이 방식은 각 환경 설정을 독립적으로 관리할 수 있어 충돌을 방지하고, 설정 변경이 발생했을 때 각 환경에 맞는 파일만 수정하면 되므로 유지보수가 용이하다고 판단했습니다.
./gradlew build -x test -Dspring.profiles.active=prod
java -jar -Dspring.profiles.active=prod build/libs/your-app.jar