YML 설정 관리 방식

minpractice_jhj·2025년 3월 24일

Operation

목록 보기
1/1

AWS 배포 환경에서의 수동 설정 수정의 불편함과 해결책

이번 주 토요일, 팀 프로젝트를 배포하기 전에 개인적으로 배포 연습을 시작했어요. AWS의 Elastic Beanstalk와 같은 배포 환경에서 작업을 하다 보니, 환경별 설정 파일을 수동으로 수정해야 하는 과정에서 불편함을 겪게 되었습니다. 특히, YML 파일을 환경마다 수정하는 일이 번거롭고 실수할 가능성이 많다는 점이 문제였습니다.

문제의 핵심: 수동 수정의 번거로움

배포 작업을 하면서, 각 환경(개발, 프로덕션 등)마다 환경 설정을 바꾸는 일이 빈번하게 발생했어요. 그때마다 수동으로 YML 파일을 수정하고 다시 배포를 해야 하는데, 이 과정에서 실수도 할 수 있고, 설정을 잊거나 잘못 적용할 위험도 있었습니다.

해결책: 멀티 환경 설정 도입

이 문제를 해결하기 위해, 멀티 환경 설정 방식을 도입하기로 했습니다. 이 방식은 각 환경(개발, 프로덕션 등)에 맞는 설정 파일을 나누어두고, 환경별로 자동 적용되도록 설정하는 방법입니다. 구체적으로는, 환경별 프로파일을 활용하거나, application-{profile}.yml 형식으로 파일을 나누어 관리할 수 있도록 했어요. 이렇게 하면, 각 환경에서 필요한 설정을 자동으로 적용할 수 있어 수동 수정의 불편함을 크게 줄일 수 있죠.


왜 이 방식을 택했는지

개인 프로젝트를 배포하는 과정에서, AWS 환경에 맞춰 배포 설정을 수정하는 데 불편함을 느꼈습니다. 특히, 각 환경에 맞는 설정을 수동으로 수정해야 하므로 번거롭고 실수할 가능성이 컸습니다. 이를 해결하고자 멀티 환경 설정 방식을 도입하여, 환경별로 설정을 자동으로 적용할 수 있는 방법을 모색하게 되었습니다.

멀티 환경 설정 방식

1. 하나의 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

2. 각 프로파일별로 파일을 나누어 관리하는 방법

장점:

  • 환경별 독립성: 각 환경 설정이 별도의 파일에 저장되므로 충돌이 없고, 설정이 독립적입니다.
  • 파일 크기 관리: 각 파일이 작고 단순하게 유지될 수 있어 관리가 쉬워집니다.
  • 환경 관리 명확성: 각 파일이 어떤 환경에 대응하는지 명확히 구분되어 있기 때문에 관리가 쉽습니다.

단점:

  • 설정 중복: 여러 환경에서 공통으로 사용하는 설정이 있을 경우, 각 파일을 수정해야 하는 중복이 발생할 수 있습니다.
  • 파일 관리 복잡성: 여러 개의 설정 파일을 관리해야 하므로 파일을 찾고 수정하는 과정에서 번거로움이 있을 수 있습니다.
  • 파일 추가 필요: 각 환경에 맞는 새로운 파일을 추가해야 하므로 파일 수가 많아질 수 있습니다.

예시:

  • 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

결론: 내가 선택한 방식

위 두 가지 방식 중에서 나는 각 프로파일별로 파일을 나누는 방식을 선택했습니다. 이 방식은 각 환경 설정을 독립적으로 관리할 수 있어 충돌을 방지하고, 설정 변경이 발생했을 때 각 환경에 맞는 파일만 수정하면 되므로 유지보수가 용이하다고 판단했습니다.

최종 결과

  • 환경별 독립성 보장: 각 환경에 맞는 설정이 독립적인 파일에 저장되므로, 설정 간 충돌이 발생할 위험이 적고, 각 환경의 설정을 명확히 구분할 수 있습니다.
  • 파일 크기 관리: 설정이 많아져도 각 파일이 작고 단순하게 유지되므로 관리가 용이합니다.
  • 환경 설정의 명확성: 각 파일이 어떤 환경에 대응하는지 명확히 알 수 있어, 어느 설정이 어느 환경에 적용되는지 쉽게 파악할 수 있습

1. Gradle 빌드 (테스트 제외 & prod 환경 적용)

./gradlew build -x test -Dspring.profiles.active=prod

2. JAR 실행 (prod 환경 적용)

java -jar -Dspring.profiles.active=prod build/libs/your-app.jar
profile
운동처럼 개발도 작은 실천이 성장의 힘이 된다고 믿는 개발자 minpractice_jhj 기록

0개의 댓글