Movatterモバイル変換


[0]ホーム

URL:


콘텐츠로 이동
Join theFastAPI Cloud waiting list 🚀
Follow@fastapi onX (Twitter) to stay updated
FollowFastAPI onLinkedIn to stay updated
Subscribe to theFastAPI and friends newsletter 🎉
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor

설정과 환경 변수

🌐 AI와 사람이 함께한 번역

이 번역은 사람의 안내를 받아 AI가 만들었습니다. 🤝

원문의 의미를 오해하거나 부자연스러워 보이는 등 오류가 있을 수 있습니다. 🤖

AI LLM을 더 잘 안내하는 데 도움을 주세요.

영문 버전

많은 경우 애플리케이션에는 외부 설정이나 구성(예: secret key, 데이터베이스 자격 증명, 이메일 서비스 자격 증명 등)이 필요할 수 있습니다.

이러한 설정 대부분은 데이터베이스 URL처럼 변동 가능(변경될 수 있음)합니다. 그리고 많은 설정은 secret처럼 민감할 수 있습니다.

이 때문에 보통 애플리케이션이 읽어들이는 환경 변수로 이를 제공하는 것이 일반적입니다.

환경 변수를 이해하려면환경 변수를 읽어보세요.

타입과 검증

이 환경 변수들은 Python 외부에 있으며 다른 프로그램 및 시스템의 나머지 부분(그리고 Linux, Windows, macOS 같은 서로 다른 운영체제와도)과 호환되어야 하므로, 텍스트 문자열만 다룰 수 있습니다.

즉, Python에서 환경 변수로부터 읽어온 어떤 값이든str이 되며, 다른 타입으로의 변환이나 검증은 코드에서 수행해야 합니다.

PydanticSettings

다행히 Pydantic은Pydantic: Settings management를 통해 환경 변수에서 오는 이러한 설정을 처리할 수 있는 훌륭한 유틸리티를 제공합니다.

pydantic-settings 설치하기

먼저가상 환경을 만들고 활성화한 다음,pydantic-settings 패키지를 설치하세요:

$pipinstallpydantic-settings---> 100%

또는 다음처럼all extras를 설치하면 함께 포함됩니다:

$pipinstall"fastapi[all]"---> 100%

Settings 객체 만들기

Pydantic에서BaseSettings를 import하고, Pydantic 모델과 매우 비슷하게 서브클래스를 만드세요.

Pydantic 모델과 같은 방식으로, 타입 어노테이션(그리고 필요하다면 기본값)과 함께 클래스 속성을 선언합니다.

다양한 데이터 타입,Field()로 추가 검증 등 Pydantic 모델에서 사용하는 동일한 검증 기능과 도구를 모두 사용할 수 있습니다.

fromfastapiimportFastAPIfrompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50settings=Settings()app=FastAPI()@app.get("/info")asyncdefinfo():return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}

빠르게 복사/붙여넣기할 예시가 필요하다면, 이 예시는 사용하지 말고 아래의 마지막 예시를 사용하세요.

그 다음, 해당Settings 클래스의 인스턴스(여기서는settings 객체)를 생성하면 Pydantic이 대소문자를 구분하지 않고 환경 변수를 읽습니다. 따라서 대문자 변수APP_NAMEapp_name 속성에 대해 읽힙니다.

이후 데이터를 변환하고 검증합니다. 그래서 그settings 객체를 사용할 때는 선언한 타입의 데이터를 갖게 됩니다(예:items_per_userint가 됩니다).

settings 사용하기

이제 애플리케이션에서 새settings 객체를 사용할 수 있습니다:

fromfastapiimportFastAPIfrompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50settings=Settings()app=FastAPI()@app.get("/info")asyncdefinfo():return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}

서버 실행하기

다음으로 환경 변수를 통해 구성을 전달하면서 서버를 실행합니다. 예를 들어 다음처럼ADMIN_EMAILAPP_NAME을 설정할 수 있습니다:

$ADMIN_EMAIL="deadpool@example.com"APP_NAME="ChimichangApp"fastapirunmain.py<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

하나의 명령에 여러 env var를 설정하려면 공백으로 구분하고, 모두 명령 앞에 두세요.

그러면admin_email 설정은"deadpool@example.com"으로 설정됩니다.

app_name"ChimichangApp"이 됩니다.

그리고items_per_user는 기본값50을 유지합니다.

다른 모듈의 설정

Bigger Applications - Multiple Files에서 본 것처럼, 설정을 다른 모듈 파일에 넣을 수도 있습니다.

예를 들어config.py 파일을 다음처럼 만들 수 있습니다:

frompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50settings=Settings()

그리고main.py 파일에서 이를 사용합니다:

fromfastapiimportFastAPIfrom.configimportsettingsapp=FastAPI()@app.get("/info")asyncdefinfo():return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}

Bigger Applications - Multiple Files에서 본 것처럼__init__.py 파일도 필요합니다.

의존성에서 설정 사용하기

어떤 경우에는 어디서나 사용되는 전역settings 객체를 두는 대신, 의존성에서 설정을 제공하는 것이 유용할 수 있습니다.

이는 특히 테스트 중에 유용할 수 있는데, 사용자 정의 설정으로 의존성을 override하기가 매우 쉽기 때문입니다.

config 파일

이전 예시에서 이어서,config.py 파일은 다음과 같을 수 있습니다:

frompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50
🤓 Other versions and variants

Tip

Prefer to use theAnnotated version if possible.

frompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50

이제는 기본 인스턴스settings = Settings()를 생성하지 않는다는 점에 유의하세요.

메인 앱 파일

이제 새로운config.Settings()를 반환하는 의존성을 생성합니다.

fromfunctoolsimportlru_cachefromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Annotated[Settings,Depends(get_settings)]):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}
🤓 Other versions and variants

Tip

Prefer to use theAnnotated version if possible.

fromfunctoolsimportlru_cachefromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Settings=Depends(get_settings)):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}

@lru_cache는 조금 뒤에 다룹니다.

지금은get_settings()가 일반 함수라고 가정해도 됩니다.

그 다음경로 처리 함수에서 이를 의존성으로 요구하고, 필요한 어디서든 사용할 수 있습니다.

fromfunctoolsimportlru_cachefromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Annotated[Settings,Depends(get_settings)]):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}
🤓 Other versions and variants

Tip

Prefer to use theAnnotated version if possible.

fromfunctoolsimportlru_cachefromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Settings=Depends(get_settings)):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}

설정과 테스트

그 다음,get_settings에 대한 의존성 override를 만들어 테스트 중에 다른 설정 객체를 제공하기가 매우 쉬워집니다:

fromfastapi.testclientimportTestClientfrom.configimportSettingsfrom.mainimportapp,get_settingsclient=TestClient(app)defget_settings_override():returnSettings(admin_email="testing_admin@example.com")app.dependency_overrides[get_settings]=get_settings_overridedeftest_app():response=client.get("/info")data=response.json()assertdata=={"app_name":"Awesome API","admin_email":"testing_admin@example.com","items_per_user":50,}
🤓 Other versions and variants

Tip

Prefer to use theAnnotated version if possible.

fromfastapi.testclientimportTestClientfrom.configimportSettingsfrom.mainimportapp,get_settingsclient=TestClient(app)defget_settings_override():returnSettings(admin_email="testing_admin@example.com")app.dependency_overrides[get_settings]=get_settings_overridedeftest_app():response=client.get("/info")data=response.json()assertdata=={"app_name":"Awesome API","admin_email":"testing_admin@example.com","items_per_user":50,}

의존성 override에서는 새Settings 객체를 생성할 때admin_email의 새 값을 설정하고, 그 새 객체를 반환합니다.

그 다음 그것이 사용되는지 테스트할 수 있습니다.

.env 파일 읽기

많이 바뀔 수 있는 설정이 많고, 서로 다른 환경에서 사용한다면, 이를 파일에 넣어 환경 변수인 것처럼 읽는 것이 유용할 수 있습니다.

이 관행은 충분히 흔해서 이름도 있는데, 이러한 환경 변수들은 보통.env 파일에 두며, 그 파일을 "dotenv"라고 부릅니다.

점(.)으로 시작하는 파일은 Linux, macOS 같은 Unix 계열 시스템에서 숨김 파일입니다.

하지만 dotenv 파일이 꼭 그 정확한 파일명을 가져야 하는 것은 아닙니다.

Pydantic은 외부 라이브러리를 사용해 이런 유형의 파일에서 읽는 기능을 지원합니다. 자세한 내용은Pydantic Settings: Dotenv (.env) support를 참고하세요.

이를 사용하려면pip install python-dotenv가 필요합니다.

.env 파일

다음과 같은.env 파일을 둘 수 있습니다:

ADMIN_EMAIL="deadpool@example.com"APP_NAME="ChimichangApp"

.env에서 설정 읽기

그리고config.py를 다음처럼 업데이트합니다:

frompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50model_config=SettingsConfigDict(env_file=".env")
🤓 Other versions and variants

Tip

Prefer to use theAnnotated version if possible.

frompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50model_config=SettingsConfigDict(env_file=".env")

model_config 속성은 Pydantic 설정을 위한 것입니다. 자세한 내용은Pydantic: Concepts: Configuration를 참고하세요.

여기서는 PydanticSettings 클래스 안에 configenv_file을 정의하고, 사용하려는 dotenv 파일의 파일명을 값으로 설정합니다.

lru_cacheSettings를 한 번만 생성하기

디스크에서 파일을 읽는 것은 보통 비용이 큰(느린) 작업이므로, 각 요청마다 읽기보다는 한 번만 수행하고 동일한 settings 객체를 재사용하는 것이 좋습니다.

하지만 매번 다음을 수행하면:

Settings()

Settings 객체가 생성되고, 생성 시점에.env 파일을 다시 읽게 됩니다.

의존성 함수가 단순히 다음과 같다면:

defget_settings():returnSettings()

요청마다 객체를 생성하게 되고, 요청마다.env 파일을 읽게 됩니다. ⚠️

하지만 위에@lru_cache 데코레이터를 사용하고 있으므로,Settings 객체는 최초 호출 시 딱 한 번만 생성됩니다. ✔️

fromfunctoolsimportlru_cachefromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfrom.importconfigapp=FastAPI()@lru_cachedefget_settings():returnconfig.Settings()@app.get("/info")asyncdefinfo(settings:Annotated[config.Settings,Depends(get_settings)]):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}
🤓 Other versions and variants

Tip

Prefer to use theAnnotated version if possible.

fromfunctoolsimportlru_cachefromfastapiimportDepends,FastAPIfrom.importconfigapp=FastAPI()@lru_cachedefget_settings():returnconfig.Settings()@app.get("/info")asyncdefinfo(settings:config.Settings=Depends(get_settings)):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}

그 다음 요청들에서 의존성으로get_settings()가 다시 호출될 때마다,get_settings()의 내부 코드를 실행해서 새Settings 객체를 만드는 대신, 첫 호출에서 반환된 동일한 객체를 계속 반환합니다.

lru_cache 기술 세부사항

@lru_cache는 데코레이션한 함수가 매번 다시 계산하는 대신, 첫 번째에 반환된 동일한 값을 반환하도록 함수를 수정합니다(즉, 매번 함수 코드를 실행하지 않습니다).

따라서 아래의 함수는 인자 조합마다 한 번씩 실행됩니다. 그리고 각각의 인자 조합에 대해 반환된 값은, 함수가 정확히 같은 인자 조합으로 호출될 때마다 반복해서 사용됩니다.

예를 들어 다음 함수가 있다면:

@lru_cachedefsay_hi(name:str,salutation:str="Ms."):returnf"Hello{salutation}{name}"

프로그램은 다음과 같이 실행될 수 있습니다:

sequenceDiagramparticipant code as Codeparticipant function as say_hi()participant execute as Execute function    rect rgba(0, 255, 0, .1)        code ->> function: say_hi(name="Camila")        function ->> execute: execute function code        execute ->> code: return the result    end    rect rgba(0, 255, 255, .1)        code ->> function: say_hi(name="Camila")        function ->> code: return stored result    end    rect rgba(0, 255, 0, .1)        code ->> function: say_hi(name="Rick")        function ->> execute: execute function code        execute ->> code: return the result    end    rect rgba(0, 255, 0, .1)        code ->> function: say_hi(name="Rick", salutation="Mr.")        function ->> execute: execute function code        execute ->> code: return the result    end    rect rgba(0, 255, 255, .1)        code ->> function: say_hi(name="Rick")        function ->> code: return stored result    end    rect rgba(0, 255, 255, .1)        code ->> function: say_hi(name="Camila")        function ->> code: return stored result    end

우리의 의존성get_settings()의 경우, 함수가 어떤 인자도 받지 않으므로 항상 같은 값을 반환합니다.

이렇게 하면 거의 전역 변수처럼 동작합니다. 하지만 의존성 함수를 사용하므로 테스트를 위해 쉽게 override할 수 있습니다.

@lru_cache는 Python 표준 라이브러리의functools에 포함되어 있으며, 자세한 내용은@lru_cache에 대한 Python 문서에서 확인할 수 있습니다.

정리

Pydantic Settings를 사용하면 Pydantic 모델의 모든 강력한 기능을 활용해 애플리케이션의 설정 또는 구성을 처리할 수 있습니다.

  • 의존성을 사용하면 테스트를 단순화할 수 있습니다.
  • .env 파일을 사용할 수 있습니다.
  • @lru_cache를 사용하면 각 요청마다 dotenv 파일을 반복해서 읽는 것을 피하면서도, 테스트 중에는 이를 override할 수 있습니다.

[8]ページ先頭

©2009-2026 Movatter.jp