database.yml, .env
업데이트 되었으니 이 파일로 갈아끼워 사용 해 주세요!
라는 카톡을 보내본 적이 있는가?
github actions에서 빌드를 위해 파일이 바뀔 때 마다 base64 인코딩 이후 secrets에 넣어본 경험이 있는가?
나는 굉장히 잦다.. 민감한 파일은 .gitignore 시켜야하고, 버전관리를 할 수 없으니 매번 메신저로 파일을 주고받았다. 그러다보면 멸종되는 파일도 생기고, 귀찮은게 이만 저만이 아니다.
그냥 스토리지에 올리면 되는거 아닌가?
라는 생각이 들었다. 이를 위해 S3등의 서비스를 쓸 수도 있겠지만, 나는 WebDAV를 도입해봤다.
WebDAV(Web Distributed Authoring and Versioning)는 웹 사이트를 편집할 수 있는 인터넷 기반 프로토콜입니다. 하이퍼텍스트 전송 프로토콜(HTTP)의 확장으로, HTTPS를 통해 데이터를 업로드하고 다운로드할 수 있습니다.
쉽게 말해, HTTP 프로토콜을 지원하는 웹기반 저장소다. POST 하면 저장, GET 하면 조회, DELETE하면 삭제.. 등등 익숙한 인터페이스다.
WebDAV는 HTTP를 지원한다. 따라서, curl같은 커맨드로 아주 단순히 파일 연산을 할 수 있다.
curl -X GET https://my-webdav-url/server/database.yml -o database.yml
이 한 줄 만으로 바로 데이터를 가져올 수 있다!
WebDAV는 apache 또는 nginx를 띄워 구축할 수도 있고, 방법은 다양하다.
나는 Docker를 이용해 아주 간편하게 구축해봤다.
나는 1M+의 다운로드가 기록된 ugeek/webdav를 사용했다. 내부적으로는 nginx를 이용해 webdav를 구축해놨다.
webdav:
image: ugeek/webdav:arm # ARM용 이미지
container_name: webdav-container
restart: always
expose:
- "80" # 컨테이너가 내부적으로 80 포트 사용
volumes:
- $HOME/docker/webdav:/media # WebDAV 데이터 저장 경로
environment:
- USERNAME=!WEBDAV_USERNAME_SECRET!
- PASSWORD=!WEBDAV_PASSWORD_SECRET!
- UID=1000
- GID=1000
- TZ=Asia/Seoul
docker-compose에 위와 같은 구문을 추가했다. 내 webdav 서버는 M4 실리콘 맥 위에서 돌기에, arm 이미지를 가져왔다.
volumes
에는 webdav의 데이터가 저장될 경로를 설정해주면 되고, env에서 username과 password를 잘 설정해주자. 저 Credential을 가지고 접근 권한을 설정해 줄 것이다.
컨테이너를 띄우면 로그인 화면이 뜨고, 위처럼 접속됨을 알 수 있다.
우선 위에서 Username, password를 설정해준 값은 항상 들어가야한다.
예시 몇 가지를 첨부하겠다.
조회
curl -X GET https://my-webdav-url/server/database.yml -o database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
추가
curl -T ./database.yml https://my-webdav-url/server/database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
수정(덮어쓰기)
curl -T PUT ./database.yml https://my-webdav-url/server/database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
삭제
curl -X DELETE https://my-webdav-url/server/database.yml -u WEBDAV_USERNAME_SECRET:WEBDAV_PASSWORD_SECRET
이게 기본적으로 cURL을 이용해 연산하는 방법이다.
그렇다면 이제 개발 환경에서는 처음 제시한 문제들이 해결되었을까?
먼저, 개발자들에게 개발 환경 세팅으로 환경 변수를 설정하게 했다.
~/.zshrc
에 다음과 같이 두개의 환경 변수를 설정한다.
CREDENTIAL_NAME은 위에서 설정한 username, CREDENTIAL_PW는 password로 하면 된다.
#!/bin/bash
set -e
webdav_url="https://my-webdav-url/server"
resources_path="./src/main/resources"
# 환경 변수 읽기
is_empty_or_null() {
[ -z "$1" ] || [ "$1" = "null" ]
}
if is_empty_or_null "$CREDENTIAL_NAME" || is_empty_or_null "$CREDENTIAL_PW"; then
echo "필요한 환경변수(CREDENTIAL_NAME, CREDENTIAL_PW) 중 하나 이상이 설정되어 있지 않거나 null입니다."
exit 1
fi
download_yml() {
local file_name=$1
echo "Downloading ${file_name}"
curl -Ss -f -X GET "${webdav_url}/${file_name}" --user "${CREDENTIAL_NAME}:${CREDENTIAL_PW}" -o "${resources_path}/${file_name}" &
}
download_yml "aws-dev.yml"
download_yml "aws-prod.yml"
download_yml "jwt.yml"
download_yml "mysql-dev.yml"
download_yml "mysql-prod.yml"
download_yml "webhook.yml"
download_yml "github.yml"
wait
그 다음, 위와 같은 sh 스크립트를 만들었다.
download_yml이라는 함수를 선언해두고, 호출해가며 yml을 서버에서 동적으로 받아온다.
저 스크립트는 빌드 또는 실행 이전에 무조건 실행되어야 파일의 최신 상태를 보장한다.
이에 대해 세팅해보자.
먼저, build.gradle에서
tasks.register("preScript", Exec) {
environment "CREDENTIAL_NAME", System.getenv("CREDENTIAL_NAME")
environment "CREDENTIAL_PW", System.getenv("CREDENTIAL_PW")
if (System.getProperty('os.name').toLowerCase().contains('win')) {
// For windows
commandLine 'C:\\Program Files\\Git\\bin\\bash.exe', '-c', './prepare-build.sh'
} else {
commandLine "sh", "prepare-build.sh"
}
}
tasks.named("processResources") {
dependsOn("preScript")
}
tasks.named("bootRun"){
dependsOn("preScript")
}
tasks.named("build") {
dependsOn("preScript")
}
tasks.named('test') {
useJUnitPlatform()
dependsOn("preScript")
}
위처럼 태스크를 등록해준다. 우리 서버 개발자중에 윈도우 환경이 있어서, git bash로 실행되도록 라인이 추가되어 있다.
다만 IntelliJ를 쓴다면, gradle을 거쳐 실행하지 않는다.
따라서 추가로 세팅해줘야 한다.
"구성 편집"을 선택한 뒤
1. 프로젝트 파일로 저장을 체크한다. 이 실행 구성을 git으로 버전관리해, 모든 개발자가 공유할 수 있도록 하는 설정이다.
2. Gradle 작업 실행을 선택한다.
그리고 작업에서 위에서 만든 preScript를 선택해주면 완료된다.
이를 통해 더이상 카톡으로 하나하나 민감 파일을 공유하지 않을 수 있게 되었다 :)