[3화] 파이썬 배포 자동화: Config 설계 & 로더 구현(스키마/검증/기본값/환경변수)
[3화] 파이썬 배포 자동화: Config 설계 & 로더 구현(스키마/검증/기본값/환경변수)

이전 포스팅에서는 파이썬 코드에 대한 구조와 전체적인 아키텍처에 대해서 다루었습니다. 이어서 이번 포스팅에서는 실제 구현 파트로 넘어가, Config 설계와 로더 구현에 대해서 다루어 보겠습니다. Git의 사용을 위한 인증 절차 또한 함께 다룰 예정입니다.
[1화] 파이썬 배포 자동화: 전체 프로세스(내부/외부 형상 기반)
[2화] 파이썬 배포 자동화: 파이썬 코드 구조와 아키텍처
[3화] 파이썬 배포 자동화: Config 설계 & 로더 구현(스키마/검증/기본값/환경변수)
[4화] 파이썬 배포 자동화: 코어 파이프라인 구현(RepoSync → Select → Copy → Report) (추후 링크 업데이트)
[5화] 파이썬 배포 자동화: CLI/로그/리포트/에러처리 및 마무리 (추후 링크 업데이트)
1. Config 요구 사항과 구조
배포 자동화에 대해서 고민을 하면서 가장 중요한 부분이 바로 Config라고 생각합니다. 가장 먼저 정해야 할 것이 바로 파일 형태입니다. 가장 흔히 사용하는 것이 JSON과 YAML 형태입니다.
| 항목 | YAML | JSON |
| 가독성/편집 | 사람 친화, 긴 설정에 유리 | 기계 친화, 작성은 다소 번거로움 |
| 주석 | 가능 | 불가(표준) |
| 엄격성/안정성 | 유연하지만 해석/들여쓰기 실수 가능 | 문법이 단순·엄격해 예측 가능 |
| 검증/스키마 | 코드(Pydantic 등)로 보완 권장 | JSON Schema 등 생태계 강함 |
표 1. YAML과 JSON 비교
저의 경우 JSON 형태로 진행할 예정입니다. Python의 Dictionary 형태로 그대로 인지할 수 있기 때문에 파싱할 때에 크게 문제가 없기 때문입니다.
권장 Config 구조(JSON)
필수
- repos.internal.url
- repos.internal.target_branch
- repos.internal.source_path
- repos.internal.token_env
- repos.external.url
- repos.external.target_branch
- repos.external.target_path
- repos.external.token_env
- file_list (배포/복사/동기화 대상 파일 목록)
선택
- logging.enabled
- report.output_dir (없으면 ./out)
- build_file_list true면 repo 기준 규칙(예: manifest/패턴)으로 file_list를 자동 생성
위의 구조를 바탕으로 구성해보면 다음과 같은 형태가 될 것입니다.
{
"repos": {
"internal": { "url": "...", "source_path": "...", "target_branch": "...", "token_env": "..." },
"external": { "url": "...", "target_path": "...", "target_branch": "...", "token_env": "..." }
},
"file_list": ["..."],
"logging": { "enabled": true },
"report": { "output_dir": "./out" }
}
Token의 환경변수 사용
토큰의 경우 매우 민감한 정보입니다. 이 정보를 바탕으로 진행했을 때에, 별도의 환경 변수에 하기 이름으로 등록해서 불러올 수 있게 할 것입니다.
DEPLOY__INTERNAL__TOKEN=...
DEPLOY__EXTERNAL__TOKEN=...
* Windows(PowerShell)과 Linux/bash의 환경변수 설정 방식은 다를 수 있으며, 로더는 최종적으로 os.environ에서 조회합니다.
2. Config 로더의 범위 및 workflow
2.1. Config 로더의 범위
Config 로더를 구현할 때에 범위와 로더의 산출물에 대해서 고민을 했습니다. Config 로더는 설정 값을 로드하고(환경변수/기본값 포함) 검증한 뒤 최종 Config 객체로 변환하는 역할만 담당합니다. 4화에서 다룰 코어 파이프라인에 동작에 필요한 정보들을 가공하는 역할입니다. Config 로더의 범위를 설정하지 않는다면, 간단한 헬퍼등을 추가할 수도 있습니다. 당장 코드 구현에는 용이하나, 향후 유지보수 관점에서 문제가 발생할 수 있습니다.
2.2. Config 로더의 workflow
Config 로더의 workflow는 다음과 같습니다.

그러면 각 단계에 대해서 살펴보겠습니다.
config.json 읽기
설정 파일인 JSON파일을 파이썬으로 읽어오는 단계입니다. JSON 문법이 올바르면 읽어오고, 문법 오류/파일 접근 오류가 있으면 예외로 중단합니다.
기본값/환경변수 읽기
선택 항목이 config.json에 없으면 로더가 기본값을 채웁니다(예: report.output_dir 미설정 시 ./out). 또한 token_env에는 토큰 값이 아니라 ‘환경변수 이름’을 적고, 로더가 os.environ에서 실제 토큰을 조회해 repos.*.token으로 주입합니다.
검증
검증 단계에서는 필수 항목 누락/타입/빈 값 여부를 확인하고, 문제가 있으면 에러로 중단합니다. 문법은 맞지만 필수 값이 없으면, 원인을 명확한 메시지로 예외 처리하여 즉시 중단합니다.
(검증 예시)
- repos.internal.url, repos.external.url은 빈 문자열 금지
- repos.internal.target_branch, repos.external.target_branch는 빈 문자열 금지
- file_list는 빈 리스트 금지(또는 최소 1개 이상)
- token_env가 가리키는 환경변수가 없으면 에러(“DEPLOY__INTERNAL__TOKEN이 설정되지 않았습니다”)
- (선택) source_path/target_path 상대/절대 허용 정책을 프로젝트 규칙으로 추가
최종 config 반환
검증과정까지 문제없게 진행되었다면 config에서 내부에서 선언된 클래스를 바탕으로 반환하는 단계입니다. 최종 Config를 반환하기 전에, 로더 내부에서 경로를 한 번 정규화합니다. 예를 들어 report.output_dir은 실행 기준 절대경로로 변환하고, source_path/target_path의 슬래시/상대경로 표현을 통일합니다. 이후 단계는 ‘정규화된 최종 Config’만 사용합니다.
다음 Config 로더(load_config.py) 구현과 Git 인증 준비 모듈(auth_git.py) 구현 부분에 대한 전체적인 코드는 다음 Github링크를 참조해주세요
https://github.com/beomseokc84/pyAutoRelease
- 이 글에서 발췌한 코드는 아래 파일에서 확인
- src/config/load_config.py
- src/config/auth_git.py
- src/util/util_basic.py
3. Config 로더(load_config.py) 구현
앞에 언급한 내용을 바탕으로 Config 로더를 구현하겠습니다. 먼저, 전체적인 구현 부분에 대해서 Plant UML을 통해서 다음과 같은 구조로 동작을 합니다.

핵심 코드를 보면 다음과 같습니다.
1) load_config() — 파이프라인(오케스트레이션)
def load_config(config_path: str) -> FinalConfig:
raw = load_json_file(config_path) # 1) 읽기
merged = apply_defaults(raw) # 2) 기본값 병합
apply_env_tokens(merged) # 3) env 해석(토큰 주입)
validate_config(merged) # 4) 검증(환경변수 값 존재 여부 포함)
base_dir = Path(config_path).parent
normalize_paths(merged, base_dir=base_dir) # 5) 정규화(최종 반환 직전 포함)
return build_final_config(merged) # 6) 최종 반환
2) apply_env_tokens()
def apply_env_tokens(cfg: Dict[str, Any]) -> None:
internal_env = validate_required_str(
cfg, "repos.internal.token_env", exc=ConfigValidationError
)
external_env = validate_required_str(
cfg, "repos.external.token_env", exc=ConfigValidationError
)
internal = require_dict(cfg, "repos.internal", exc=ConfigValidationError)
external = require_dict(cfg, "repos.external", exc=ConfigValidationError)
internal["token"] = resolve_token(internal_env)
external["token"] = resolve_token(external_env)
3) validate_config()
def validate_config(cfg: Dict[str, Any]) -> None:
internal_env = validate_required_str(cfg, "repos.internal.token_env", exc=ConfigValidationError)
external_env = validate_required_str(cfg, "repos.external.token_env", exc=ConfigValidationError)
# 환경변수 값 존재 여부 확인
if not os.environ.get(internal_env):
raise ConfigValidationError(f"환경변수 '{internal_env}'가 설정되지 않았습니다.")
if not os.environ.get(external_env):
raise ConfigValidationError(f"환경변수 '{external_env}'가 설정되지 않았습니다.")
# 토큰 주입 여부 확인(적용 누락 방지)
validate_required_str(cfg, "repos.internal.token", exc=ConfigValidationError)
validate_required_str(cfg, "repos.external.token", exc=ConfigValidationError)
# file_list, optional 타입(bool/str), dict 구조 검증 등은 생략(전체 코드는 GitHub)
4. Git 인증 준비 모듈(auth_git.py) 구현
실제 git clone/fetch 실행은 다음 화(Repo Sync)에서 다루고, 이번 화에서는 “인증 준비”만 분리해 둡니다.
이렇게 하면 로더/동기화/인증이 서로 섞이지 않아 유지보수가 쉬워집니다. 그러면 auth_git의 sequence diagram에 대해서 살펴보겠습니다.

def prepare_git_auth(repo_url: str, token: str, provider: Optional[str] = None) -> GitAuth:
"""auth_git.py의 핵심: 토큰을 이용해 '인증 준비'만 수행합니다.
실제 git clone/fetch/pull 실행은 sync_repo.py에서 담당합니다.
"""
auth_url, safe_url, provider_final = build_auth_url_https(repo_url, token, provider=provider)
env = build_git_env()
return GitAuth(
original_url=repo_url,
auth_url=auth_url,
safe_url=safe_url,
env=env,
provider=provider_final,
)
이번 화에서는 인증 ‘준비’만 분리해두고, 4화 RepoSync에서 실제 사용합니다.
이번 3화에서는 배포 자동화의 입력이 되는 Config를 JSON으로 설계하고, 이를 안정적으로 로드하기 위한 Config 로더를 구현해보았습니다. 핵심은 load_config()가 읽기 → 기본값 병합 → 환경변수 해석(token) → 검증 → 경로 정규화 → 최종 Config 반환의 순서를 고정해, 이후 파이프라인(4화)이 ‘검증 + 정규화된 설정’만을 전제로 단순하게 동작하도록 만드는 것입니다. 또한 토큰은 config.json에 저장하지 않고 token_env로 환경변수 이름만 전달받아, 로더가 os.environ에서 조회하도록 구성해 보안 리스크를 줄였습니다. 추가로 토큰은 로그에 직접 출력하지 않도록(마스킹/safe_url 사용) 처리하는 것을 기본 원칙으로 했습니다.
다음 4화에서는 이번 화에서 만든 FinalConfig와 GitAuth를 사용해, 내부/외부 Repo를 동기화(RepoSync)하고 파일 목록을 선택(Select)한 뒤 복사(Copy) 및 리포트(Report)까지 이어지는 코어 파이프라인을 구현해보겠습니다.
2026.01.03 - [Python/Python 응용] - [2화] 파이썬 배포 자동화: 파이썬 코드 구조와 아키텍처
[2화] 파이썬 배포 자동화: 파이썬 코드 구조와 아키텍처
[2화] 파이썬 배포 자동화: 파이썬 코드 구조와 아키텍처이전 포스팅에서는 파이썬 스크립트로 배포 자동화 환경을 구축하는 전체 흐름을 정리했습니다. 배포 자동화가 왜 필요한지와 함께, 실
appia.tistory.com