S3Client 문제인 줄 알았지만 submodule 문제였던 건에 대하여

새로운 기술을 사용하기 전에 기술문서를 먼저 읽자

echo
Dong-gle
6 min readOct 1, 2023

--

지난번 S3 사용법을 작성할때 마지막에 S3Client를 사용하면서 발생했던 문제에 대해 다뤄본다고 했었다. 하지만 사실 알고보니 S3Client의 문제가 아니라 S3Client에서 사용하던 bucket Name과 key를 application.yml로 관리중이였는데 이 yml이 submodule이여서 발생했던 문제였다. 이에 대해 좀 더 자세히 다뤄볼까 한다.

동글에서 겪었던 문제는 아래와 같았다.

  1. Github Actions로 빌드 후 배포하면 S3 Client에서 Access Denied 예외가 발생했다. 이외에 다른 서버 문제는 발생하지 않았다.
  2. 하지만 로컬에서 빌드 후 배포하면 문제가 없었다.

로컬에서 빌드할때 차이는 서브모듈을 업데이트했다는 것이었다. 이때까지는 서브모듈에 익숙하지 않아 서브모듈이 정확히 어떤 방식으로 작동하는지 몰랐고 actions에서 checkout을 할때 submodules:true 설정만 켜놓으면 최신 서브모듈 커밋을 읽어오는줄 알았다. 왜냐하면 서버에서 과거 서브모듈을 사용했다면 분명히 특정 값이 없어서 서버 자체가 실행되지 않았어야했기 때문이다. 하지만 서버는 정상적으로 작동했고, S3에서만 문제를 일으켰기 때문에 서브모듈을 업데이트가 되지 않았다는 생각을 하지 못했다.

git submodule도 git이다.

기존 동글 프로젝트의 시크릿 키들과 기타 변수들은 github secrets로 관리되고 있었고, actions로 해당 값들을 주입하였다. 하지만 변수들이 늘어남에 따라 값을 관리하고 기억하기 어려워졌고 변수가 늘어날때마다 actions를 수정해야하는 번거로움이 있어서 깃 서브모듈을 도입해 환경변수들을 관리하였다.

그러면 Github Actions는 서브모듈의 어떤 커밋을 기준으로 가져올까?

Image

위의 사진에서 config@60b644d 폴더가 있는데 해당 폴더가 동글에서 추가한 서브모듈이다.

위의 명령어로 서브모듈을 추가하면 PATH 경로에 서브모듈이 추가된다.

동글에서는 config로 경로를 지정하여서 서브모듈이 추가된 것이다. config 옆에 @60b644d는 커밋 해시 값이다. 이 해시 값은 어떤 값일까?

Image

만약 메인 프로젝트에서 git submodule add로 서브모듈을 추가할 경우 최신 커밋을 기준으로 서브모듈을 추가한다.

Image

만약 이 상황에서 서브모듈의 리모트에 새로운 커밋이 추가되면 어떻게 될까? 변경사항이 생겼으니 git push를 하거나 다른 브랜치로 체크아웃을 하면 오류가 뜨지 않을까?라고 생각될 수 있다. 하지만 리모트가 변경되었을 뿐이고 서브모듈 내부에서 git pull이나 git submodule update --remote 명령어를 입력하지 않는 이상 변경사항이 반영되지 않는다.

실제로 서브모듈의 업데이트를 반영해주면 아래와 같을 것이다.

Image

이제 git status를 입력하면 아래와 같이 서브모듈에 변경사항이 생긴 것을 알 수 있다.

이렇게 변경사항이 생겼으니 커밋을 하고 메인 프로젝트 리모트로 push 해주면 서브모듈도 최신 커밋을 바라보는 상태로 업데이트가 된다.

Intellij에서는 서브모듈 변경사항이 Commit 창에서도 잘 뜨지 않는다. 따라서 서브모듈을 업데이트 한 경우 cli나 다른 git gui툴로 변경사항을 커밋해야한다.

결론은 서브모듈 자체도 깃이기 때문에 변경사항을 반영해서 push 해줘야한다는 것이다.

그렇다면 S3 Client 문제는 뭐였나?

문제는 서브모듈도 업데이트해서 메인 프로젝트에 커밋하지 않아 과거 서브모듈이 사용되었다는 것이였다. 그렇지만 과거 서브모듈이 사용되었다면 어떻게 서버는 정상적으로 동작했을까?

답은 역시나 공식 문서에 있었다..

Spring Boot Profile Specific Files

application.yml을 기본적으로 읽고 특정 application-{profile}.yml이 있고 해당 profile로 실행될때 값을 오버라이드한다.

Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones.

따라서 과거 application-dev.yml을 읽었을때 특정 값이 비어있더라도 application.yml에 값이 있다면 읽어올 수 있었던 것이었다.

예를 들어, dev, prod 프로파일 두개가 설정되었다면 기본적으로 application.yml 값을 읽은 다음 application-dev를 먼저 오버라이드 하고 application-prod를 마지막으로 오버라이드를 하는 순서로 작동된다.

결론

새로운 기술을 사용할때 대충 이럴 것이다 생각해서 추측하지 말고 미리 공식문서를 조금 읽어두자. 문제가 생겼을때는 추측으로 인해 문제 발생 부분을 찾아내기 쉽지 않다.

--

--