개발 스토리

환경 변수 관리에 대한 고민 및 submoudule 적용(pre-push 활용)

타칸 2025. 3. 4. 18:27

배경

개발을 하다 보면 DB password, API key 등 중요한 값들을 안전하게 보관해야 하는 경우가 발생한다.

앗차를 개발하면서도 이러한 경우가 자주 발생했는데 Tmap, Kakao, 공공 데이터 등 여러 서비스의 API를 호출하기에 관리해야 하는 키 값들도 많고 기타 여러 변수들을 안전하게 보관해야 했다.

이러한 변수들을 Github에 직접 올리면 보안상 매우 위험하기 때문에 우선 IDEA에 환경 변수를 직접 등록해서 사용하는 방식을 채택했다.

위와 같이 환경변수를 직접 등록해 두고. 아래와 같이 환경 설정 파일에서 변수명을 가져와 넣어주었다.

하지만 이러한 방식에는 크게 2가지 단점이 있었다.

1. 팀원과 공유하기 힘든 환경 변수명

새로운 환경 변수가 생길 때마다, 팀원들에게 새롭게 생긴 변숫값을 알려줘야 했다.

만약 제대로 트레킹이 되지 않거나 누군가 새롭게 추가된 변숫값을 알려주지 않아 설정하지 않으면 서버가 동작하지 않는 경우가 다반사였다.

그래서 디스코드에 환경 변수를 공유하는 전용 채널을 만들어서 공유하는 방식으로 진행하고 있었는데 매번 변수를 업데이트해줘야 하는 귀찮음이 존재했다.

2. 새로운 실행마다 환경 변수를 설정해야 한다.

이게 가장 큰 단점이다. 새로운 기능을 추가하고 특정 테스트를 실행하면 환경 변수 설정이 전부 사라져 테스트가 실패하는 경우가 다반사였다.

특정 테스트만 실행하면 위와 같이 새롭게 Configurations가 생기면서 환경 변수들이 초기화된다.

그래서 매번 실행이 실패할 때마다 변수들을 다시 설정해 주거나, 이전 실행을 반복해서 실행해야 테스트가 실행하지 않았다.

작업을 하다 보면 특정 테스트만 실행하는 등 새로운 Configurations로 실행하는 경우가 매우 자주 일어나는데 이럴 때마다 환경 변수를 매번 다시 설정해 주는 것은 매우 큰 리소스였다.

따라서 이를 해결할 수 있는 방법을 찾고 개선해보려고 했다.

어떤 해결책이 있을까

어떻게 하면 해결할 수 있을지 알아보다가 크게 2가지 해결책이 있다는 것을 알았다.

  1. 환경 변수 파일을 만들어서 사용
  2. Sub module을 활용한 해결법

1. 환경 변수 파일을 만들어서 사용

노출되면 안 되는 환경 변수들을 모아 Github secrets에 등록해두고 CI / CD 과정에서 넣어주는 방법이다.

이 방법은 이전 프로젝트에서 사용했던 방식이다.

위와 같이 노출되면 안되는 환경 변수들을 관리할 yml 파일을 생성한다. 나는 secret-env라는 이름으로 yml 파일을 만들었다. 그리고 환경 변수들을 넣어준다.

그리고 위와 같이 application.yml 파일에 아까 생성한 yml 파일을 import 해서 사용하면 된다.

나는 secret이라는 변수 하위에 환경 변수들을 지정해 주었기 때문에 secret.SPRING_DATABASE_HOST 같이 사용했다.

추가로 내가 추가한 설정파일이 github에 올라가지 않도록 설정해야 한다.

따라서. gitignore에 위와 같이 추가한 파일의 경로를 설정했다.

추가로 CD과정에서도 환경 변수를 사용할 수 있도록 secret-env 파일을 Github secrets에 저장해 두고 넣어주는 작업이 있어야 한다.

이전 프로젝트에서도 위와 같이 사용했었다.

 

[장점]

위 방식은 쉽게 변수를 설정할 수 있다는 장점이 있다.

또한 이제 매번 Configurations에 환경 변수를 설정해 줄 필요 없이 간단하게 secret-env 파일에 환경 변수를 추가해서 사용하면 된다.

 

[단점]

단점은 환경 변수를 팀원들끼리 공유하기 불편하다는 점은 동일했다.

결국 환경 변수를 관리하는 파일을 Github에 직접 올리는 것이 아니기에 팀원끼리 어떤 변수가 추가되었고 사용하는지 매번 공유해야 했다.

또한 매번 새롭게 변수가 업데이트되었을 때 Github Secrets 값을 업데이트해야 하는데, Github Secrets는 수정은 안되고 오직 삭제랑 생성만 가능하기 때문에 만약 이전에 추가된 변수를 잘못해서 안 넣는 등 문제가 발생하면 CD 과정이 일어나기 전까지는 알아채지 못했다.

 

2. Sub module을 활용한 방법

설정 파일을 관리할 별도의 레포지토리를 private로 만들어두고 가져다가 사용하는 방법이다.

위와 같이 환경 변수를 관리할 별도의 레포지토리를 private으로 만들어둔다.

이러면 환경 변수를 github로 관리해도 private이기에 권한이 없는 사람은 확인할 수 없다.

그리고 메인 레포지토리에 서브 모듈로 방금 만든 환경 변수 레포지토리를 포함하는 것이다.

그림으로 그리면 이러한 느낌인 것이다.

서브 모듈은 하나의 작은 프로젝트이고 메인 프로젝트 안에 이 작은 프로젝트의 특정 버전을 포함시켜서 사용하는 것이다.

그리고 서브 모듈에서 환경 변수를 가져와서 resources 디렉토리에 추가해 주는 것이다.

이러면 환경 변수 레포에서 환경 변수들을 가져와서 사용할 수 있다.

주의할 점

메인 프로젝트에서 서브모듈을 가리키고 있기에 깃이 꼬일 가능성이 있다고 한다.

아직 경험해보지 않아서 그런지 어떻게 깃이 꼬이는지는 잘 모르겠다.(당하면 알겠지..?)

 

결론

submodule을 사용하도록 결정

이전에 github secrets를 활용해서 환경 변수를 관리했었는데 매번 팀원들과 환경 변수를 고려하는 작업이 여간 귀찮은 작업이 아니었다. 누가 실수로 업데이트를 안 해두거나 혹은 잘못해서 환경 변수를 지워두면 어떤 변경 사항이 일어났는지 확인이 불가능해서 곤란했던 적이 많았다.

그래서 변경 사항을 확인할 수 있는 submodule 방식에 매력을 느끼게 되었고 최종 채택하게 되었다.

pre-push 설정

submodule을 사용할 때 주의할 점은 깃이 꼬이지 않도록 잘 다뤄야 한다는 것이다.

깃이 꼬이지 않게 해 주기 위해서는 push 할 때 메인 프로젝트는 서브모듈의 최신 커밋의 해시값을 가리키고 있어야 하는 것 같았다.

submodule에 대해 잘 모르는 팀원들이 잘못해서 실수하지 않도록 항상 서브모듈의 최신 커밋을 바라보도록 자동화해 주는 장치의 필요성이 느껴졌다.

따라서 메인 프로젝트에서 push를 할 때 서브모듈을 update를 해주고 만약 최신 버전이 아니면 push가 fail을 하도록 설정해 주기로 했다.

[pre-push]

#!/bin/sh
# 서브모듈 업데이트 여부 확인
git submodule update --remote

# 변경 사항이 있다면 메인 프로젝트에 반영 여부 확인
if ! git diff --exit-code; then
    echo "서브모듈 업데이트 후 변경 사항이 있습니다. 커밋 후 다시 push 해주세요."
    exit 1
fi

간단하게 submodule을 update 해주고 변경 사항이 있으면 fail 하는 작업이다.

해당 훅을 메인 프로젝트의 .git/hooks/pre-push 로 위치시키면 push가 일어날 때마다 훅이 동작했다.

만약 서브모듈을 업데이트하지 않고 push 하는 경우에는 아래와 같이 에러가 발생하는 것을 볼 수 있다.

이제 잘못해서 깃이 꼬이는 일이 일어나지 않을 것이다.(그렇겠지..?)