Frame Work/FastAPI

makefile 사용 시 환경변수 로딩 주의하기

j4ko 2024. 10. 27. 04:43
728x90
반응형

목차

     

    개요 

    Python으로 Project 진행 시 makefile을 Root Directory에 위치시켜둔다. 이 makefile 은 Project에 관한 명령어를 모아둔 것으로 주로 Project에서 어떤 명령어들을 사용하는지를 나열해놓는 용도로만 사용하고 있다.

     

    사용해야될 명령어들을 미리 정의해둠으로써 많은 편의를 누리고 있는데 최근 makefile을 사용하면서 사소한 문제를 겪었다. makefile은 별 문제가 없는 이상 계속 사용하게 될 것이라. 겪었던 문제를 기록해두려고한다.

     


     

    1. 무엇이 문제인가?

    문제의 현상은 환경변수에 올라간 값이 dotenv를 통해 불러와 Python 변수에 할당하고 난 후 두 값이 불일치되는 것이었다.

     

    환경변수의 올라간 값은 DataBase의 Password 이기에 여러 특수문자를 포함하고 있다는게 특징이다. 즉 현상은 환경변수와 Python 변수값의 불일치지만 이 현상으로 인해 DataBase에 접속할 수 없다는 문제가 생긴다.


    2. makefile 에서 .env 사용과 Python에서 .env 사용하기

    ".env"는 외부 시스템에 의존하는 여러 값들이 존재한다. 데이터베이스 뿐만 아니라 Third Party API Key 값도 포함된다. 이는 Project가 외부에 의존하는 영역이 많을수록 ".env"의 파일의 내용은 커진다는 점을 의미한다.

     

    그렇기 때문에 makefile에서 ".env" 값을 그대로 사용하는 것이 편리하겠다는 생각을 해볼 수 있다. 이를테면 다음과 같은 스크립트를 사용하면 ".env" 내용을 "makefile"에서 사용할 수 있다.

    # makefile
    ifneq (,$(wildcard .env))
        include .env
        export $(shell sed 's/=.*//' .env)
    endif
    
    app.local:
    	uvicorn src.main:application --reload    
         
     orm.model:
    	sqlacodegen --outfile ./model.py $(DRIVER)://$(USER):$(PASSWORD)@$(HOST):$(PORT)/$(DATABASE)

     

    Python에서는 "python-dotenv" 라는 라이브러리가 ".env"의 내용을 편리하기 사용할 수 있도록 도와준다. 필자는 "python-dotenv"에서 "load_dotenv"를 자주 사용하는 편이다.

    from dotenv import load_dotenv

     

    load_dotenv()는 "os" 모듈을 통해 환경변수에 접근이 가능하다. 

    import os
    
    driver = os.environ['DRIVER']

     

    이 경우 시스템에 할당된 환경변수의 값을 그대로 읽어들인다. 여기서 필자가 겪었던 문제가 있다. makefile의 다음 라인이 환경변수를 로드하지만 Shell에 의해 해석된 문자들이 환경변수에 바인딩 된다는 점이다.

    # makefile
    ifneq (,$(wildcard .env))
        include .env
        export $(shell sed 's/=.*//' .env)
    endif

     

     

    만약 "$" 와 같이 특수문자가 값에 포함되어있다면 해당 문자열은 제외되고 환경변수에 바인딩 될 것이다. 예를 들어 다음과 같이 설정하고 makefile "execute.script"를 통해 python 을 실행해보자 PASSWORD라는 값은 출력되지 않을 것이다.

    # .env
    PASSWORD=$a
    
    # dotenv_test.py
    
    import os
    from dotenv import load_dotenv
    
    load_dotenv()
    
    print(os.environ['PASSWORD'])
    
    # makefile
    
    ifneq (,$(wildcard .env))
        include .env
        export $(shell sed 's/=.*//' .env)
    endif
    
    execute.script:
    	python dotenv_test.py

     

     


    3. 해결방법은 ?

    단적으로 압축해보자면 이 문제의 원인은 makefile을 통해서 Project를 실행한다거나 *.py를 실행하면서 발생한다는 점이다. makefile을 사용하지 않으면 쉽게 해결될 듯 하지만 개인적으로는 이미 makefile이 편리해서 많이 사용을 해야되는 상황이다. 

     

    "dotenv" 에는 환경변수를 불러오는 다른 함수가 존재한다 "dotenv_values" 라는 것인데 이는 ".env"의 내용을 바로 Python의 변수에 바인딩 해준다는 점이 특징이다.

    from dotenv import dotenv_values
    
    config = dotenv_values()

     

    특수문자가 포함된 비밀번호를 변경하는 것도 좋은 해결이 될 수 있지만 그렇지 못한 상황도 있을 수 있으니 유념해두자.


     

    마치며

    dotenv의 load_dotenv는 그 동안 많이 사용해왔고 별 문제가 없었다. 그러나 문제를 겪고나니 한 우물만 팠던 걸 조금은 돌아보게된다. 다양한 상황에 대비하려면 해당 라이브러리를 문서를 한 번쯤은 들여다보는 것도 좋을 듯 싶다.

    728x90
    반응형