Skip to main content

Codex를 조직에 들여오는 순간부터 질문이 바뀝니다. "어떻게 더 잘 쓰지?"보다 먼저 "어디로 데이터가 나가고, 누가 무엇을 할 수 있으며, 비용은 어떻게 통제하지?"가 앞에 옵니다. Azure AI Foundry(이하 Foundry)에서 Codex를 운영하면, Codex의 에이전트 워크플로(비동기 작업, CLI/VS Code/GitHub Actions 연동, PR 생성, 테스트 작성)를 유지하면서도 요청과 응답이 조직의 Azure 경계 안에서 처리되도록 구성할 수 있습니다.

이 챕터에서는 다음을 목표로 합니다.

  • Foundry에서 어떤 모델(배포)을 선택할지 기준을 세운다.

  • config.toml에 Azure provider를 정확히 설정해 CLI/VS Code에서 동일하게 쓴다.

  • Windows 개발자가 가장 많이 부딪히는 WSL + VS Code 환경 변수/연동 문제를 빠르게 해결한다.


데이터 경계를 지키면서 'Codex 방식'은 그대로 가져오는 설계

Foundry 기반 운영의 핵심은 "도구를 바꾸는 것"이 아니라 "백엔드(모델 제공자)를 바꾸는 것"입니다. Codex CLI/확장은 그대로 쓰되, 모델 호출이 OpenAI 공용 엔드포인트가 아니라 Azure OpenAI 배포 엔드포인트로 향하도록 설정합니다. 그러면 조직은 다음과 같은 운영상의 이점을 얻습니다.

  • 접근 제어: 프로젝트/배포 단위 권한(RBAC)으로 "누가 어느 배포를 쓸 수 있는지"를 제어할 수 있습니다.

  • 네트워크 경계: 사내 네트워크 정책(프라이빗 네트워킹 등)과 함께 설계할 여지가 생깁니다.

  • 비용 관리: 팀/프로젝트별 배포를 분리하고, 예산·쿼터·모니터링을 Azure 운영 모델에 맞게 가져갈 수 있습니다.

Codex 사용 방식(승인, 샌드박스, 세션 재개, PR 워크플로)은 유지되므로, 개발자는 기존 습관을 거의 버리지 않고도 엔터프라이즈 요구사항을 만족시키는 쪽으로 이동할 수 있습니다.


Foundry에서 배포 모델 선택: "모델 이름"이 아니라 "배포 이름"을 고른다

Foundry에서 Codex를 쓰려면 먼저 모델을 '배포(Deployment)'해야 합니다. 여기서 가장 많이 헷갈리는 부분은, Codex CLI 설정의 model = "..."이 모델 제품명이 아니라 내가 만든 배포 이름이라는 점입니다.

예를 들어 Foundry 모델 카탈로그에서 gpt-5.1-codex-mini를 배포하면서 배포 이름을 team-codex-dev로 지었다면, Codex 설정의 model에는 team-codex-dev가 들어가야 합니다.

어떤 모델을 선택할까: 속도·비용·추론의 균형

팀에 "표준 배포"를 하나 만든다고 가정하면, 대개 아래의 의사결정이 반복됩니다.

  • 대화/짧은 수정이 많고, 터미널 상호작용이 잦다면: 빠르고 가벼운 Codex 계열(예: codex-mini, gpt-5.x-codex-mini)을 우선 고려합니다.

  • 리팩터링·마이그레이션·버그 원인 추적처럼 계획/추론이 중요한 작업이 많다면: 상위 reasoning 모델(예: gpt-5.x-codex, gpt-5.x-codex-max)을 표준으로 두고, 비용이 부담되면 프로파일로 하위 모델도 함께 둡니다.

  • CI에서 자동으로 문서 갱신, 릴리즈 노트 생성 같은 반복 작업이 많다면: 충분히 작은 모델(예: gpt-5-mini, gpt-5-nano)을 CI 전용 배포로 분리해 비용을 예측 가능하게 만듭니다.

실무 팁은 단순합니다. "팀의 평균 작업"을 기준으로 기본 배포 하나를 정하고, 나머지는 프로파일(Profiles)로 분기해 선택권을 주되, 비용이 새지 않게 디폴트는 보수적으로 가져갑니다.


~/.codex/config.toml: Azure provider를 정확히 잡는 최소 설정

Foundry/Azure로 연결하는 구성은 생각보다 단순합니다.

  1. model_provider = "azure"

  2. [model_providers.azure] 블록에 base_url, env_key, wire_api 설정

  3. API 키는 반드시 환경 변수로 제공

권장: v1 Responses API 구성(/openai/v1 포함)

Microsoft Learn 가이드의 v1 구성에서는 base_url 경로에 /openai/v1를 포함합니다. 이 경우(문서 기준) api-version을 별도로 넘기지 않습니다.1

# ~/.codex/config.toml
model = "TEAM_CODEX_DEV"           # <-- Foundry에서 만든 '배포 이름'
model_provider = "azure"
model_reasoning_effort = "medium"  # minimal|low|medium|high

[model_providers.azure]
name = "Azure OpenAI"
base_url = "https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1"
env_key = "AZURE_OPENAI_API_KEY"
wire_api = "responses"

그리고 셸에서 키를 주입합니다.

# macOS / Linux / WSL
export AZURE_OPENAI_API_KEY="<your-api-key>"

참고: 레거시/호환 구성(api-version이 필요한 경우)

조직 내 프록시/게이트웨이 또는 구버전 API 흐름을 쓰는 경우, api-version을 쿼리 파라미터로 요구하는 설정을 보게 될 수 있습니다. 이때는 공식 설정 레퍼런스를 기준으로 query_params를 추가하는 방식이 사용됩니다.2

팀 표준을 만들 때는 "우리가 v1(/openai/v1)을 쓰는지, 레거시(쿼리 api-version)를 쓰는지"를 먼저 확정하세요. 두 패턴을 섞으면 404/401로 이어지기 쉽습니다.

자주 나는 실수 3가지

첫째, v1 구성을 쓰면서 base_url에서 /openai/v1를 빼먹는 경우가 많습니다. 문서 기준으로 v1에서는 경로가 정확해야 합니다.1

둘째, env_key = "<실제키문자열>"처럼 키를 문자열로 직접 쓰면 안 됩니다. env_key는 "환경 변수 이름"이어야 합니다.1

셋째, model을 모델 제품명으로 착각합니다. Codex CLI 입장에서는 Azure가 제공하는 "배포 이름"으로 호출해야 하므로, 배포 이름을 넣어야 합니다.1

~/.codex/config.toml

model = "TEAM_CODEX_DEV" # <-- Foundry에서 만든 '배포 이름' model_provider = "azure" model_reasoning_effort = "medium" # minimal|low|medium|high

[model_providers.azure] name = "Azure OpenAI" base_url = "https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1" env_key = "AZURE_OPENAI_API_KEY" wire_api = "responses"


그리고 셸에서 키를 주입합니다.

```bash
# macOS / Linux / WSL
export AZURE_OPENAI_API_KEY="<your-api-key>"

자주 나는 실수 3가지

첫째, base_url에 /v1을 빼먹는 경우가 많습니다. Responses API v1 구성에서는 경로가 정확해야 합니다.

둘째, env_key = "<실제키문자열>"처럼 키를 문자열로 직접 쓰면 안 됩니다. env_key는 "환경 변수 이름"이어야 합니다.

셋째, model을 모델 제품명으로 착각합니다. Codex CLI 입장에서는 Azure가 제공하는 "배포 이름"으로 호출해야 하므로, 배포 이름을 넣어야 합니다.


프로파일로 Dev/CI/High-Reasoning을 분리하기

엔터프라이즈에서 가장 좋은 운영 패턴은 "기본은 저비용·저권한, 필요할 때만 강하게"입니다. Codex의 프로파일은 이 전략을 설정 파일로 굳히기 좋습니다.

# ~/.codex/config.toml
profile = "dev"

[model_providers.azure]
name = "Azure OpenAI"
base_url = "https://YOUR_RESOURCE_NAME.openai.azure.com/openai/v1"
env_key = "AZURE_OPENAI_API_KEY"
wire_api = "responses"

[profiles.dev]
model = "team-codex-dev"
model_provider = "azure"
model_reasoning_effort = "medium"
approval_policy = "on-request"

[profiles.review]
model = "team-codex-review"
model_provider = "azure"
model_reasoning_effort = "high"
approval_policy = "untrusted"

[profiles.ci]
model = "team-codex-ci"
model_provider = "azure"
model_reasoning_effort = "low"
approval_policy = "never"

이렇게 두면 같은 레포에서도 상황에 따라 다음처럼 명확히 갈라 쓸 수 있습니다.

codex --profile dev
codex --profile review "이 PR의 변경을 리뷰하고 위험한 부분만 짚어줘"
codex --profile ci exec --full-auto "CHANGELOG 업데이트하고 릴리즈 노트 초안 생성"

키 관리(규정 준수 관점): "노출 경로"부터 닫는다

운영에서 사고가 나는 지점은 모델이 아니라 키입니다. 팀 규칙을 단순하게 가져가면 실수가 크게 줄어듭니다.

세 가지 원칙을 권합니다.

  • 키는 코드/설정 파일에 직접 쓰지 않는다. 항상 환경 변수 또는 OS/조직의 시크릿 스토어를 사용합니다.

  • 개발용 키와 CI 키를 분리한다. 유출되더라도 피해 범위를 좁히고, 사용량 추적도 쉬워집니다.

  • 배포(Deployment)도 용도별로 분리한다. "고성능 모델은 제한된 사용자만", "CI는 소형 모델만"처럼 정책을 배포 단위로 고정합니다.


WSL + VS Code 연동: '같은 설정, 다른 환경'을 이해해야 한다

Windows에서 Codex를 안정적으로 쓰는 현실적인 경로는 WSL2입니다. 문제는 여기서부터입니다.

  • Codex CLI는 WSL에서 잘 되는데,

  • VS Code 확장에서는 인증이 실패하는 경우가 흔합니다.

이 차이는 대부분 환경 변수의 '보이는 위치'가 달라서 생깁니다.

권장 실행 흐름

  1. WSL에서 키를 설정합니다.

# WSL
export AZURE_OPENAI_API_KEY="<your-api-key>"
  1. 같은 터미널 세션에서 VS Code를 실행합니다.

# WSL
cd /path/to/repo
code .
  1. VS Code에서는 원격(WSL) 창에서 작업합니다.

이 흐름을 따르면, VS Code 확장도 대개 동일한 환경 변수를 상속받아 문제 없이 동작합니다.

WSL인데도 VS Code 확장이 키를 못 읽는 경우

특히 확장이 Windows 호스트 쪽 환경 변수를 참고하는 경우가 있습니다. 이때는 Windows에도 동일한 환경 변수를 설정해 두는 것이 가장 빠른 완화책입니다.

  • Windows PowerShell:

setx AZURE_OPENAI_API_KEY "<your-api-key>"

설정 후에는 새 터미널/새 VS Code 프로세스로 다시 시작해야 반영됩니다.

추가로, 일부 환경에서는 확장이 OPENAI_API_KEY를 찾는 경우가 있어, 다음처럼 "동일 키를 이중으로" 제공하면 현장에서 바로 해결되는 일이 많습니다.

# WSL
export AZURE_OPENAI_API_KEY="<your-api-key>"
export OPENAI_API_KEY="$AZURE_OPENAI_API_KEY"

트러블슈팅: 증상별로 '한 줄'로 진단하는 표

운영 이슈는 길게 설명할수록 해결이 늦어집니다. 증상→원인→조치가 바로 연결되게 정리합니다.

401 Unauthorized / 403 Forbidden

가장 먼저 확인할 것은 "키가 맞나"가 아니라 키가 호출 권한을 가진 배포를 향하고 있나입니다.

  • AZURE_OPENAI_API_KEY가 현재 셸에 실제로 잡혀 있는지 확인합니다: printenv AZURE_OPENAI_API_KEY

  • config.toml에서 env_key가 환경 변수 이름과 정확히 일치하는지 확인합니다.

  • 배포 이름(model)이 실제 배포 이름인지 확인합니다.

ENOTFOUND / DNS 에러 / 404 Not Found

대부분 base_url 오타입니다.

  • 리소스 이름(서브도메인)이 정확한지

  • 도메인이 openai.azure.com인지

  • v1 구성을 쓴다면 /openai/v1 경로가 포함되어 있는지

를 체크합니다.

"CLI가 Azure 설정을 무시하는 것 같다"

  • model_provider = "azure"가 최상단에 있는지

  • [model_providers.azure] 블록이 존재하는지

  • wire_api = "responses"가 필요한 모델인데 누락되지 않았는지

를 확인합니다.

--provider 같은 플래그를 넣었더니 "unexpected argument"가 뜬다

Codex CLI는 버전에 따라 플래그가 다릅니다. "provider를 커맨드에서 고르기"가 아니라, 설정 파일에 provider를 정의하고 --profile로 선택하는 쪽이 가장 안전합니다.

  • 해결: ~/.codex/config.toml에 프로파일을 만들고 codex --profile <name>로 실행합니다.

디버그 로그로 확인하기

원인이 감지되지 않으면 로그를 켜고 "어느 URL로 요청하는지"를 봐야 합니다.

RUST_LOG=debug codex exec "say hello"

요청 URL, 헤더 구성, 어떤 프로파일이 로드되었는지가 드러나면 대개 설정 한 줄로 끝납니다.


엔터프라이즈 운영 체크포인트: '보안'과 '생산성'을 같이 만족시키는 법

Foundry로 옮겼다고 해서 자동으로 안전해지지는 않습니다. "안전한 자동화"는 정책과 습관으로 완성됩니다.

첫째, 승인(Approvals)과 샌드박스는 기본값을 보수적으로 두고, 팀의 성숙도에 맞춰 완화합니다. 특히 --full-auto나 확장의 "Full access"에 해당하는 모드는 사소한 실수도 즉시 영향이 커집니다.

둘째, 배포와 프로파일로 사용 목적을 분리합니다. 고성능 배포를 아무나 쓰게 두는 대신, 리뷰/마이그레이션 전용 프로파일로 좁혀두면 비용과 리스크가 동시에 내려갑니다.

셋째, WSL/VS Code 환경 변수 전달 방식을 팀 표준으로 문서화합니다. 개인의 PC에서만 터지는 인증 문제는 생산성을 조용히 갉아먹습니다. "WSL에서 code .로 실행" 같은 한 줄 규칙이 팀 전체 시간을 절약합니다.


요약: Azure로 옮겨도 Codex 워크플로는 바뀌지 않는다

Foundry에서 Codex를 운영할 때 핵심은 "새 도구를 배우는 것"이 아니라 "같은 도구가 바라보는 백엔드를 Azure로 바꾸는 것"입니다. 모델 배포(Deployment) 이름을 기준으로 config.toml을 정확히 잡고, 키를 환경 변수로 관리하며, WSL/VS Code의 실행 흐름만 표준화하면 됩니다.

이렇게 하면 데이터 경계를 지키면서도, 지금까지 만들어 온 Codex 에이전트 워크플로를 거의 그대로 조직 안으로 가져올 수 있습니다.


참고

1Codex with Azure OpenAI in Microsoft Foundry Models (Microsoft Learn)

2Configuration Reference (OpenAI Developers)

책 목록

OpenAI Codex 활용법: IDE·CLI·클라우드에서 코딩 에이전트로 일하기

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기