ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot / FastAPI] 프로젝트 환경 분리
    프로젝트/뉴스타 2024. 6. 30. 22:34

    프로젝트 환경 분리 왜 궁금했을까❓

    프로젝트를 할 때, Dev와 Prod 환경 설정들을 분리하지 않고 사용하다 보니 지속적으로 Config를 수정해야 한다는 문제점이 있었다. 이러한 부분에서 팀의 생산성을 향상시키고자 Dev와 Prod 환경을 분리하려고 한다. 또한, 분리를 통해 운영 서버의 데이터를 조작할 수 없게 하여 안전성을 향상시키고자 한다.

     

    1. 기존의 환경 변수 관리법

    기존에는 각 어플리케이션의 환경 변수를 하나의 YAML 파일에 넣고 GitLab에 PUSH하여 팀원끼리 공유하는 식으로 진행이 되었다.
    • 위와 같은 방식으로 운영하다보니 환경 변수가 prod와 dev가 섞이게 되어 운영 서버에 데이터가 들어가거나 개발 서버의 환경 변수로 인해 작동이 안하는 장애가 발생했다.
    • 각 팀원들이 pull을 할 때마다 각 환경 변수들이 개발 서버에 맞게 되어 있는 지, 안되어 있다면 변경하는 작업이 지속적으로 이뤄져야 해서 비 효율적이였다.
    • GitLab에 비밀키와 같은 민감한 정보들이 GitLab에 PUSH되어 보안에 심각한 문제를 일으키고 있었다.

    위와 같은 문제점들을 해결하고자 개선된 환경 변수 관리 방법을 적용하고 팀의 생산성과 보안성을 향상시키고자 한다.

     

    2. 개선된 환경 변수 관리법

    • Private한 (Notion) 공간에 env 파일을 두고 각 팀원들과 공유하여 서비스 전체적의 환경 변수를 관리
    • 각 어플리케이션에서는 prod와 dev 파일로 yaml을 분리하여 각 환경에 맞는 설정을 주입할 수 있도록 설정
    • dev에서 개발할 때, 어플리케이션에 dev.yaml을 활용하겠다고 설정하면 dev 환경에 맞는 설정들이 주입
    • prod에서 개발할 때, 어플리케이션에 prod.yaml을 활용하겠다고 설정하면 prod 환경에 맞는 설정들이 주입
    이로써 어플리케이션을 실행할 때 어떠한 환경 파일을 사용할지 입력만 한다면 자동으로 주입되어 보다 편하고 장애없이 관리할 수 있다.

     

    3. 프로젝트 적용

    3.1. Spring Boot

    • yaml 설정 파일을 개발 / 배포 / 공용으로 나눠서 관리를 했다.

    application.yml

    spring:
      profiles:
        default: dev
    
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/newstar?serverTimezone=Asia/Seoul
        username: ${MYSQL_USER_DEV_ID}
        password: ${MYSQL_USER_DEV_PASSWORD}
    
      data:
        redis:
          host: localhost
          port: 6379
    
      jpa:
        properties:
          hibernate:
            dialect: org.hibernate.dialect.MySQL8Dialect
            # show_sql: true # sysout 단계에서 쿼리문 show
            format_sql: true
            default_batch_fetch_size: 1000 # select 배치 조회 크기
    
    server:
      servlet:
        context-path: '/api'
      port: 8080
    
    logging:
      level:
        org.hibernate.SQL: debug
        org.hibernate.type: trace # log 단계에서 쿼리문 show
    
    management:
      endpoints:
        web:
          exposure:
            include: health

    application-dev.yml

    spring:
      config:
        activate:
          on-profile: dev
    
      jpa:
        hibernate:
          ddl-auto: none

    application-prod.yml

    spring:
      config:
        activate:
          on-profile: prod
      datasource:
        url: jdbc:mysql://mysql:3306/newstar?serverTimezone=Asia/Seoul
        username: ${MYSQL_USER_PROD_ID}
        password: ${MYSQL_USER_PROD_PASSWORD}
      jpa:
        hibernate:
          ddl-auto: none
      data:
        redis:
          host: redis

     

     

    3.2. FastAPI

    • 하나의 yml 파일에 dev, prod를 나눠서 각 환경 설정을 관리했다.

    application.yml

    dev:
        DB:
            user: 'newstar'
            password: 'newstar'
            host: 'localhost'
            port: 3306
            database: 'newstar'
        ES:
            host: 'localhost:9200'
        TEST:
            member_pw: 'feb91399-aaf3-40ef-856d-35e6ddf8befb'
    prod:
        DB:
            host: 'mysql'
            port: 3306
            database: 'newstar'
        ES:
            host: 'elastic:9200'

    config.py

    import os
    import yaml
    
    with open(os.path.dirname(os.path.abspath(__file__)) + '/application.yml', 'r') as yaml_conf:
        conf = yaml.safe_load(yaml_conf)[os.environ.get('APP_ENV', 'dev')]
        
    class Config:
        DB = conf['DB']
        if os.getenv("APP_ENV") == 'prod':
            DB['user'] = os.getenv("MYSQL_USER_PROD_ID")
            DB['password'] = os.getenv("MYSQL_USER_PROD_PASSWORD")
        ES = conf['ES']

     

    3.3. Docker-Compose

    • 각 어플리케이션 컨테이너 실행 시 환경 변수가 주입될 수 있도록 설정했다.
    version: '3'
    
    services:
        spring:
            container_name: spring-blue
            image: newstar_back
            ports:
              - 8080:8080
            restart: always
            env_file:
              - /env/.env
            environment:
              TZ: Asia/Seoul
        react:
            container_name: react-blue
            image: newstar_front
            ports:
              - 3000:3000
        fastapi:
            container_name: fastapi-blue
            image: fastapi_back
            ports:
              - 8000:8000
            restart: always
            env_file:
              - /env/.env
            environment:
              TZ: Asia/Seoul
    networks:
      default:
        name: app-net
        external: true
Designed by Tistory.