코틀린 스프링으로 dotenv를 사용해서 중요비밀정보 분리하기
도커를 사용할때는,환경변수주입으로 값을 받아서 쓰는게 아무래도 편리하다
jar로 말때도 따로 뭐 신경쓰지않아도 되고
비밀정보도 어플리케이션이 가지고있을 필요도 없어지고
근데 로컬에서는 아무래도 환경변수를 사용하면 불편하다(물론 인텔리제이단에서 주입할수있긴하다)
그냥 config.properties를 쓴다고 하면
build.gradle에
bootJar {
exclude 'config.properties'
}
를 추가해서 jar로 말릴때 해당파일을 제거하고
application.yaml에
spring:
config:
import: optional:classpath:config.properties
로 해당파일이 존재할때만 읽어오게 한다음에 도커컨테이너 실행시나,도커파일로 말때 설정해도 된다
근데 build.gradle에 저런거 설정하기도 짜치고,만약 gradle에 커스텀으로 말때 까먹고 build.gradle에서 제외하는거 까먹으면 참사가 난다
그래서 사용되는게 dotenv다
이건 js에서 사용하는 dotenv와 거의 같다
프로젝트 루트에 .env파일을 만들고,프로젝트 루트니 jar파일을 생성할때 포함되지않으니 뭘 추가할필요도 없다
또한 같은 환경변수를 js에 가져가서 쓸수도있고 여러모로 좀 쓰기편하다
이걸 사용할때는
의존성으로 build.gradle에
implementation 'io.github.cdimascio:dotenv-kotlin:6.4.2'
추가하고,
프로젝트루트에 .env를 만들고
MYSQL_ID = id
MYSQL_KEY = pppaaassswwwoorrdd
MYSQL_URL = jdbc:mysql://localhost:3306/projectName?serverTimezone=Asia/Seoul
이런식으로 넣을값을 설정해준다음(이때 키=값 이라는거에 주의,키="값"이 아님)
spring:
config:
import: optional:file:.env[.properties] //이렇게 넣어서
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${MYSQL_URL} //이렇게 사용
username: ${MYSQL_ID}
password: ${MYSQL_KEY}
저렇게 넣어서 쓰면된다
즉 .env파일이 있는 로컬에서는 .env로 동작하고
.env파일이 없는 서버에서는 주입받은 환경변수로 동작하는 식이다
어플리케이션 내에서 사용은
class ApiConfig private constructor() {
companion object {
private val dotenv = Dotenv.configure().ignoreIfMissing().load()
fun getOpenApiKey(): String = dotenv.get("OPENAPI_KEY")
fun getGptKey(): String = dotenv.get("GPT_KEY")
}
}
이런식으로 dotenv를 생성하고 거기서 get을 사용하면된다
Dotenv.configure().ignoreIfMissing().load()
configure().ignoreIfMissing()이건, .env파일이 없을경우 무시하고 진행하라는거(외부 환경변수 주입받은거를 사용할때)
저게 없이 바로 Dotenv.load()할경우,.env파일이 없으면 예외가 발생함
즉 컨테이너 실행시 외부에서 환경변수를 주입하고싶으면 Dotenv.configure().ignoreIfMissing().load()
도커파일 빌드시 환경변수를 주입하고싶으면 Dotenv.load()를 사용하는게 좋음(없을경우 바로 예외던지니까 없다는걸 바로알수있음)
단 이때 System.getenv(...) 를 사용하면 안되는 이유는 (참고)
대충 자바에서 실행중인 프로세스에서는 환경변수를 설정할수없어서 System.getenv로 접근할수없다 이런거임
이러면 로컬에서 환경변수 설정은 됐으니 도커 컨테이너에서 환경변수를 주입받아주면 된다