
Linux에서 처음부터 만드는 Codex 중심의 AI 구동 개발 환경
요약
Linux 환경에서 OpenAI Codex CLI를 중심으로 에이전트가 자율적으로 판단하고 동작할 수 있는 최적화된 개발 환경 구축 방법을 소개합니다. OS 설정부터 MCP, 스킬, 개발 규약(AGENTS.md)에 이르기까지 계층별 구성 요소를 상세히 다룹니다.
핵심 포인트
- 단순 프롬프트 확장이 아닌 에이전트가 참조할 수 있는 개발 환경 구축의 중요성
- Linux 기반의 계층적 환경 구성(OS, Codex 설정, 개발 규약, MCP 등)
- 레거시 시스템에서도 적용 가능한 범용적인 에이전트 워크플로우
- 재현 가능한 명령어를 위한 도구 및 버전 관리 전략
코드 생성 AI를 도입한 직후에는 놀라울 정도로 빠르게 코드가 작성된다.
하지만 며칠 사용하다 보면 다른 문제가 보이기 시작한다.
테스트 명령어를 매번 알려줘야 하고, 건드리지 않았으면 하는 파일을 매번 전달해야 하며, 티켓 형식을 매번 수정해야 하게 된다.
부족했던 것은 더 긴 프롬프트가 아니었다.
에이전트가 판단할 때 참조할 수 있는, 개발 환경 그 자체였다.
이 기사에서는 내가 실제로 사용하고 있는 환경을, 아무것도 설치되지 않은 Linux로부터 재구축할 수 있는 순서대로 나열한다.
현재 사용 중인 구성은 AlmaLinux 9, Bash, Git, OpenAI Codex CLI를 중심으로, AGENTS.md, MCP, 스킬(Skill), 후크(Hook), 역할별 에이전트, Git worktree를 조합한 것이다.
PHP, JavaScript, Ruby가 혼재하는 레거시 성향의 업무 시스템에서도 사용하고 있기 때문에, 단일 언어의 신규 프로젝트만을 상정한 구성은 아니다.
2026년 7월 19일 시점의 실기(実機) 상태는 다음과 같다.
| 요소 | 실기의 버전 |
|---|---|
| OS | AlmaLinux 9.7 x86_64 |
| ... |
이것은 동작 확인이 완료된 스냅샷이며, 모든 사람이 동일한 버전을 설치해야 한다는 의미는 아니다.
신규 구축 시에는 각 도구의 안정 버전을 선택하고, 프로젝트가 지정하는 버전을 락 파일(Lock file)이나 버전 관리 파일로 고정한다.
먼저 완성된 형태를 파악하기
완성된 환경은 다음과 같은 계층(Layer)으로 나뉜다.
| 계층 | 배치 요소 | 해결하는 문제 |
|---|---|---|
| Linux | Git, Node.js, uv, 각 언어 처리계 | 명령어를 재현 가능하게 함 |
| Codex 설정 | ~/.codex/config.toml | 권한, 표시, 병렬 수의 기본값을 통일함 |
| 개발 규약 | AGENTS.md | 매번 전달하던 제약 사항을 영구화함 |
| 프로젝트 명령어 | Makefile 등 | 빌드와 검증의 입구를 단일화함 |
| MCP | 공식 문서, 코드 그래프, 브라우저, 과제 관리 | 리포지토리 외부의 사실과 구조로 연결함 |
| 스킬과 플러그인 | SKILL.md, 배포용 번들 | 반복되는 작업 절차를 재사용함 |
| 운영 가드 | 후크(Hook), 규칙, worktree | 위험한 조작과 작업의 혼선을 방지함 |
이 순서에는 이유가 있다.
아래 계층이 모호한 상태에서 위 계층을 늘리면, 에이전트는 많은 도구를 가지고 있으면서도 무엇을 언제 사용해야 할지 판단할 수 없게 된다.
Linux에 토대 만들기
나의 환경은 AlmaLinux 9에서 동작하고 있다.
RHEL 계열이라면, 가장 먼저 최소한의 개발 도구를 설치한다.
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y git curl ca-certificates jq ripgrep make zlib-devel
Ubuntu나 Debian에서는 대응하는 패키지를 apt로 설치한다.
sudo apt update
sudo apt install -y build-essential git curl ca-certificates jq ripgrep make zlib1g-dev
여기서 ripgrep을 설치하는 것은 단순한 취향이 아니다.
대규모 리포지토리에서 문자열이나 설정을 찾을 때, grep -R보다 빠르며 .gitignore도 자연스럽게 다룰 수 있기 때문이다.
다음으로 Node.js의 LTS 버전을 설치한다.
OS 패키지에 고정하면 MCP 서버가 요구하는 버전으로 추종하기 어렵기 때문에, 개인 환경에서는 nvm 등의 버전 관리 도구를 사용한다.
curl -o- \
https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.6/install.sh \
| bash
...
Python 기반의 MCP 서버를 격리하여 실행하기 위해, uv도 준비한다.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv --version
uvx --version
인터넷에서 취득한 스크립트를 직접 실행하는 것에 거부감이 있다면, 일단 저장하여 내용과 체크섬(Checksum)을 확인한 후 실행한다.
팀 단위로 재현성을 요구한다면, Node.js나 uv의 버전도 셋업 스크립트로 고정한다.
PHP, Composer, Ruby, Bundler, Docker 등은 담당하는 리포지토리(Repository)가 필요로 하는 것만 추가한다.
내 환경에는 이것들도 들어있지만, Codex를 사용하기 위한 필수 조건은 아니다.
로컬의 PHP가 8.4이더라도, 어떤 프로젝트의 composer.json이 PHP 7.4를 대상으로 하고 있는 경우가 있다.
에이전트(Agent)에게 CLI 버전을 추측하게 하지 말고, 언어별 설정 파일을 호환성의 기준으로 읽게 한다.
Codex CLI 설치하기
Codex CLI는 공식 인스톨러로 도입할 수 있다.
curl -fsSL https://chatgpt.com/codex/install.sh | sh
codex --version
codex login
...
Node.js 관리 방식에 맞추고 싶다면 npm 버전을 선택해도 좋다.
동일한 환경에서 여러 도입 방법을 섞으면, 업데이트된 실체와 실행되는 실체가 어긋나기 때문에 둘 중 하나로 결정한다.
npm install -g @openai/codex
리포지토리로 이동하여 codex를 실행하면 대화형 화면이 열린다.
처음에는 /status로 작업 디렉토리와 권한을 확인하고, /init으로 AGENTS.md의 초안을 만드는 것부터 시작할 수 있다.
초기 설정은 안전한 방향으로 설정한다
개인 설정은 ~/.codex/config.toml에 둔다.
처음부터 강력한 권한을 부여할 필요는 없다.
model_reasoning_effort = "medium"
personality = "pragmatic"
sandbox_mode = "workspace-write"
...
workspace-write라면 에이전트가 쓸 수 있는 범위를 작업 영역으로 제한할 수 있다.
on-request라면 추가 권한이 필요한 조작을 인간이 확인할 수 있다.
갑자기 전면 허용으로 전환하면 빨라진 것처럼 보이지만, 잘못된 디렉토리에서의 삭제나 의도하지 않은 외부 조작까지 빨라진다.
모델명은 설정 예시에서 제외했다.
사용 가능한 모델은 계약과 시기에 따라 달라지므로, /model에서 선택하고 안정화된 후에 개인 설정으로 고정하는 편이 이식하기 쉽다.
AGENTS.md에 판단 기준을 작성한다
Codex의 응답을 안정시킨 것은 세세한 프롬프트 기술보다 AGENTS.md였다.
이것은 에이전트용 README로, 작업 시작 시 자동으로 읽힌다.
설정 위치는 두 군데로 나눈다.
~/.codex/AGENTS.md: 자신이 모든 리포지토리에서 지키게 하고 싶은 원칙<repository>/AGENTS.md: 빌드 방법, 디렉토리 구성, 팀 고유의 규칙
나아가 서브 디렉토리에 AGENTS.md를 두면, 해당 하위 디렉토리에만 세부 규칙을 적용할 수 있다.
작업 위치와 가까운 지시가 우선되므로, 거대한 파일 하나에 모든 것을 채워 넣을 필요는 없다.
글로벌 측은 다음과 같은 수준부터 시작한다.
# 개발 공통 원칙
- 동작뿐만 아니라 유지보수성, 안전성, 테스트 가능성을 확인한다.
- 에러를 억제하지 않고, 원인을 특정하여 수정한다.
...
리포지토리 측에는 추상적인 마음가짐보다 판단에 사용할 수 있는 사실을 적는다.
# Repository Guidelines
## 구성
- 애플리케이션 코드는 `src/`에 둔다.
...
"품질을 높인다"와 같은 지시만으로는 작업 중의 선택을 바꾸기 어렵다.
"어떤 명령어를 실행할지", "무엇을 읽지 않을지", "완료 시 무엇을 확인할지"까지 작성하면 판단이 일치하게 된다.
단, 처음부터 수백 줄의 규칙을 만들 필요는 없다.
같은 실수를 두 번 수정했을 때가 규칙에 추가할 신호이다.
명령어 입구를 단일화한다
에이전트가 올바른 검증을 선택할 수 있는 것은 프로젝트 측에 신뢰할 수 있는 입구가 있는 경우에 한한다.
README에 긴 절차를 적기보다 Makefile이나 justfile, package.json의 scripts에 실행 절차를 둔다.
.PHONY: init lint test verify
init:
composer install
...
내가 다루고 있는 프로젝트에서는 make init이 Composer, Node.js, Ruby, 프론트엔드 자산의 초기화를 통합하며, make phpunit이 테스트 DB의 마이그레이션부터 테스트 실행까지 담당한다.
에이전트와 인간이 동일한 명령어를 사용하기 때문에, "로컬에서는 작동하지만 에이전트 환경에서는 절차가 누락되는" 차이가 줄어들었다.
락 파일 (Lock file) 또한 동일한 역할을 한다.
의존성 버전 (Dependency version)을 고정하지 않고서는 "제로 베이스에서 동일한 환경"을 재현할 수 없다.
MCP는 부족한 사실로 연결한다
MCP는 에이전트에게 무턱대고 도구를 늘려주는 메커니즘이 아니다.
로컬 코드만으로는 확정할 수 없는 사실로 향하는 전용 입구를 마련하는 메커니즘이다.
나의 환경에서는 다음과 같이 역할을 나누어 사용한다.
- OpenAI 공식 문서: Codex나 API의 현재 사양을 확인한다
- Context7: 라이브러리의 현재 문서를 확인한다
- codebase-memory-mcp: 함수, 호출 관계, 아키텍처를 그래프를 통해 조사한다
- Serena: 심볼 (Symbol) 단위로 코드를 검색하고 편집한다
- Chrome DevTools MCP: 실제 화면, DOM, 네트워크, 콘솔을 확인한다
- Redmine 등의 이슈 관리 MCP: 티켓의 사실과 작업 기록에 연결한다
먼저 공식 문서와 Context7을 추가한다.
codex mcp add openaiDeveloperDocs \
--url https://developers.openai.com/mcp
codex mcp add context7 -- \
...
화면이 있는 애플리케이션이라면 Chrome DevTools MCP를 추가한다.
codex mcp add chrome-devtools -- \
npx -y chrome-devtools-mcp@latest
규모가 큰 코드베이스에서는 전체 텍스트 검색 (Full-text search)만으로는 "이름은 찾았지만, 누가 호출하고 있는가"라는 문제가 남는다.
그래서 codebase-memory-mcp를 도입한다.
curl -fsSL \
https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/scripts/setup.sh \
| bash
...
리포지토리를 한 번 인덱싱 (Indexing)하고 상태를 확인한다.
codebase-memory-mcp cli index_repository \
"{\"repo_path\":\"$PWD\",\"mode\":\"moderate\",\"persistence\":true}"
AGENTS.md에는 코드 탐색 시 그래프 검색을 먼저 사용하고, 문자열이나 설정 파일에 대해서만 rg로 돌아가라고 적어둔다.
도구를 추가하는 것만으로는 에이전트가 기존처럼 전체 텍스트 검색을 선택할 가능성이 있기 때문이다.
심볼 편집을 중시한다면 Serena도 선택할 수 있다.
codex mcp add serena -- \
uvx --from git+https://github.com/oraios/serena \
serena start-mcp-server --context codex
연결 상태는 다음 명령어로 확인한다.
codex mcp list
외부 서비스의 인증 정보는 config.toml에 값을 직접 쓰지 않는다.
환경 변수 (Environment variable) 이름만 설정하고, 비밀 정보는 쉘 (Shell), 키체인 (Keychain), 또는 조직의 시크릿 관리 기반으로부터 전달한다.
[mcp_servers.issue_tracker]
command = "issue-tracker-mcp"
env_vars = ["ISSUE_TRACKER_URL", "ISSUE_TRACKER_API_KEY"]
반복되는 절차를 스킬로 만든다
AGENTS.md가 상시 적용되는 규약이라면, **스킬 (Skill)**은 특정 요청 시 기동되는 작업 절차이다.
예를 들어 버그 진단, 테스트 주도 개발 (TDD), 기사 편집, 머지 충돌 (Merge conflict) 해결은 각각 별도의 스킬로 만들 수 있다.
사용자 공통 스킬은 ~/.agents/skills/에, 리포지토리 고유 스킬은 .agents/skills/에 둔다.
.agents/skills/
└── diagnosing-bugs/
├── SKILL.md
...
최소 단위의 SKILL.md는 다음과 같은 형태가 된다.
---
name: diagnosing-bugs
description: 재현하기 어려운 결함이나 성능 저하를 진단할 때 사용한다.
...
Codex 내장 $skill-installer를 사용하면 준비된 스킬이나 GitHub 상의 스킬도 도입할 수 있다.
스킬 이름과 설명은 기동 판정에 사용되므로, "무엇을 하는가"뿐만 아니라 "언제 사용하고, 언제 사용하지 않는가"를 작성한다.
여러 스킬, MCP 설정, 후크(Hook)를 하나로 묶어 배포하고 싶다면, 플러그인 (Plugin) 단계로 넘어간다.
개인의 시행착오는 스킬, 팀에게 안정적으로 배포하는 단위는 플러그인으로 나누면 관리하기 쉽다.
역할별 에이전트로 병렬 작업 제어하기
모든 업무를 동일한 권한과 추론량으로 처리할 필요는 없다.
나의 환경에서는 가벼운 읽기, 통상 구현, 복잡한 조사라는 세 가지 역할로 나누어 운영한다.
~/.codex/agents/
├── fast_scan.toml
├── routine_worker.toml
...
읽기 전용 역할은 다음과 같이 만들 수 있다.
name = "fast_scan"
description = "검색, 코드 탐색, 가벼운 분석을 수행하는 읽기 전용 에이전트."
sandbox_mode = "read-only"
...
통상 구현과 복잡한 조사에서는 설명과 지시사항만 바꾸고, 모델은 부모 세션으로부터 상속받아도 좋다.
name = "deep_worker"
description = "어려운 디버깅, 설계, 보안, 모호한 다단계 조사를 담당한다."
developer_instructions = """
...
max_depth = 1은 루트 에이전트로부터의 직계 자식만을 허용하는 설정이다.
재귀적인 위임(Recursive Delegation)을 방지함으로써 토큰 소비와 작업의 확산을 예측하기 쉬워진다.
병렬화는 서로 독립적인 조사나 리뷰에 한해서만 사용한다.
후크와 규칙으로 경계를 기계화하기
문서상의 규약만으로는 방지할 수 없는 조작이 있다.
그래서 Codex의 **후크 (Hook)**와 **규칙 (Rule)**을 사용한다.
후크는 세션 시작, 도구 실행 전후, 종료 시점 등에 스크립트를 실행할 수 있다.
예를 들어, 시작 시점에 브랜치와 작업 트리(Worktree)의 상태를 표시하고, 종료 시점에 검증되지 않은 차이(Diff)가 없는지 확인할 수 있다.
{
"hooks": {
"SessionStart": [
...
사용자 공통 설정이라면 ~/.codex/hooks.json에, 리포지토리 고유 설정이라면 .codex/hooks.json에 둔다.
후크는 임의의 명령어를 실행할 수 있으므로, /hooks에서 내용을 확인하고 신뢰할 수 있을 때 활성화한다.
규칙은 샌드박스 외부에서 실행하는 명령어를 허용, 확인, 금지로 분류한다.
~/.codex/rules/default.rules에 우선 위험도가 높은 조작부터 작성한다.
prefix_rule(
pattern = ["git", "push"],
decision = "prompt",
...
과거에 한 번 사용했던 명령어를 반사적으로 모두 허용해서는 안 된다.
허용 리스트가 계속 늘어나면, 현재 목적과 무관한 강력한 조작까지 확인 없이 통과하게 된다.
티켓별로 worktree 분리하기
에이전트가 더 오래 작업할 수 있게 될수록, 하나의 작업 트리(Worktree)에 여러 변경 사항을 섞지 않는 것이 효과적이다.
티켓 단위로 Git worktree를 만들면, 원래 작업과 구현 중인 차이점을 물리적으로 분리할 수 있다.
git fetch origin
mkdir -p ../project-worktrees
git worktree add \
...
나의 환경에서는 이 처리를 tools/new-worktree.sh에 모아두었다.
스크립트는 브랜치 생성뿐만 아니라 로컬 확인용 심볼릭 링크(Symbolic Link)도 생성하며, 확인 URL을 표시한다.
구현 흐름은 다음과 같이 고정했다.
- 티켓의 현상과 수락 조건(Acceptance Criteria)을 읽는다.
- 전용 worktree를 만든다.
- 영향 파일, 데이터 흐름, 테스트, 리스크를 계획한다.
- 사람이 계획을 승인한다.
- 작게 구현하고, 초점을 맞춘 테스트를 실행한다.
- 전체 테스트와 차이(Diff) 리뷰를 수행한다.
- 확인 URL과 검증 결과를 보고한다.
여기서 사람이 승인하는 것은 코드의 한 줄 한 줄이 아니라, 변경 범위와 검증 방법이다.
에이전트의 자율성을 높이더라도 판단 책임까지 모호하게 만들지는 않는다.
프로젝트 초기화하기
OS와 Codex의 각 계층을 준비했다면, 대상 리포지토리를 가져온다.
git clone <repository-url>
cd <repository>
# 비밀 정보를 포함하지 않는 템플릿으로부터 로컬 설정을 만든다
...
실제 프로젝트에서는 make help로 이용 가능한 진입점을 확인할 수 있도록 해두어야 한다.
.env
리포지토리(Repository)에 둘 경우에도, 커밋하는 것은 .env.example만 하고, 실제 값은 출력, 로그, 에이전트(Agent)에 대한 지시 사항에 포함하지 않는다.
동작을 검사한다
구축이 끝나면, 단순히 실행이 되었다는 사실이 아니라, 각 계층(Layer)이 서로 연결되어 있는지 확인한다.
codex --version
codex doctor --summary
codex mcp list
...
Codex 내부에서는 /status, /mcp, /hooks를 확인한다.
그다음, 첫 번째 요청을 읽기 전용(Read-only)으로 설정한다.
이 리포지토리를 변경하지 말고 조사해 주세요.
AGENTS.md에서 구성, 초기화, 테스트, 금지 사항을 추출해 주세요.
코드 탐색 시에는 이용 가능한 그래프 MCP를 우선시하고, 찾을 수 없는 설정값만 rg로 찾아주세요.
...
이 요청에서 규약을 놓친다면, 구현으로 넘어가기 전에 AGENTS.md의 위치와 내용을 수정한다.
MCP를 호출하지 않는다면, 서버의 접속 상태와 어떤 상황에서 사용할지에 대한 라우팅(Routing) 지시를 수정한다.
환경의 결함을 프롬프트(Prompt)의 말투로 계속 메우려 하지 마라.
처음부터 전부 넣지 않는다
제로 베이스에서 단번에 현재의 구성으로 도약하면, 어떤 설정이 효과가 있었는지 알 수 없게 된다.
도입은 네 단계면 충분했다.
- Codex,
AGENTS.md,Makefile, 안전한 샌드박스(Sandbox)를 갖춘다. - 공식 문서와 코드 탐색용 MCP를 추가한다.
- 반복했던 작업만을 스킬(Skill)로 옮긴다.
- 작업이 독립적인 경우에만 역할별 에이전트와 병렬 실행을 추가한다.
훅(Hook)과 규칙(Rule)은 실제로 발생한 사고나 재작업을 기계적으로 방지할 수 있는 경우에 추가한다.
사용하지 않는 MCP, 오래된 스킬, 너무 넓은 허용 규칙은 정기적으로 삭제한다.
좋은 AI 구동 개발 환경은 에이전트에게 무엇이든 허가한 환경이 아니다.
어떤 사실을 참조하고, 어떤 규약을 따르며, 어디까지 자율적으로 진행하고, 무엇을 인간에게 반환할지가 명확한 환경이다.
처음에 느꼈던 "매번 똑같은 것을 가르치고 있다"라는 번거로움은 개별적인 불만이 아니었다.
그 각각이 다음에 추가해야 할 설정, 규약, 명령어, 스킬의 위치를 알려주고 있었다.
참고 자료
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기