Codex CLI에서 리뷰 요청이 실패하는 두 가지 함정 — `-i`의 가변 길이 인자와 `tail` 누락을 간과한 구현 절차
요약
Codex CLI를 이용한 코드 리뷰 자동화 과정에서 발생할 수 있는 두 가지 흔하고 까다로운 실패 사례와 해결책을 제시합니다. 특히 이미지 첨부 시 `-i` 뒤에 위치 인수를 넣지 않도록 주의해야 하며, `tail` 누락으로 인한 파이프라인 오류 방지 및 CI 환경에서의 안정적인 구현 절차를 안내합니다.
핵심 포인트
- 이미지 포함 리뷰 시: `-i` 옵션 뒤에 위치 인수를 추가하지 않도록 주의하세요.
- 출력 결과는 `--output-last-message`로 파일에 저장하여 비교 분석이 용이합니다.
- `tail` 누락이나 파이프라인 오류 방지를 위해 CI 환경에서 `test -s`를 활용하는 것이 효과적입니다.
- 직전 세션 재개 시에는 `codex exec resume --last` 명령어를 사용하여 토큰 소모와 시간을 줄일 수 있습니다.
검증에 사용된 환경은 다음과 같습니다. 이후의 명령어는 모두 셸(shell)에서 실행한다는 전제입니다.
$ codex --version
codex-cli 0.144.5
$ node -v
...
셸은 bash 5.2 / zsh 5.9로 확인했습니다. GitHub Actions의 ubuntu-24.04 러너에서도 같은 동작이었습니다. 버전이 올라가면 인자 파서(argument parser)의 정의가 바뀔 수 있으므로, CI 로그에는 반드시 codex --version의 출력을 남기도록 합니다.
codex exec으로 코드 리뷰를 자동화할 때, exit code는 0이고 로그에도 오류가 없지만 출력이 비어있는 상태에 직면했습니다. 원인은 두 가지이며, 둘 다 **조용히 실패(silently fail)**하는 것이 까다롭습니다. 이를 인지하지 못하고 '리뷰 통과'라고 판단하면, 리뷰 과정 자체가 무의미해집니다.
이 글에서는 재현 절차와 대책, 그리고 CI에 적용하는 방법까지 순서대로 작성하겠습니다.
이미지를 첨부하여 리뷰를 시키려고 다음과 같이 작성했습니다.
# NG: 프롬프트가 이미지 경로로 해석됨
codex exec \
-i screenshots/error.png \
...
이 형태에서는 `
--output-last-message
이것은 마지막 메시지 전체를 파일에 기록하므로, head로 하든
tail로 하든
grep으로 하든,
나중에 원하는 기준으로 읽을 수 있습니다. 파일이 남기 때문에 리뷰 결과를 PR 커멘트에 옮기거나, 과거 리뷰와 차이점을 비교하는 것도 가능합니다. mkdir -p를 잊으면 디렉토리가 없어 실패하므로 주의하세요.
이미 tail로 누락시켜 버린 경우에도 직전 세션을 재개할 수 있습니다.
codex exec resume --last \
"직전 리뷰의 High 지적만, 대상 파일의 행 번호와 수정 패치안과 함께 다시 출력해"
컨텍스트 전체를 다시 전송할 필요가 없으므로 토큰 소모도 실행 시간도 줄일 수 있습니다. 다만 --last는 말 그대로 직전 세션을 가져오기 때문에, 다른 터미널에서 병렬로 codex를 구동하고 있다면 의도치 않은 세션에 연결될 수 있습니다. 병렬 실행할 때는 세션 ID를 기록해 두세요.
| 목적 | 명령어 | 주의사항 |
|---|---|---|
| 이미지 포함 리뷰 | `printf '%s' "..." | codex exec -i img.png -` |
| 전체 내용 저장 | --output-last-message .codex/review.md | 출력할 디렉토리를 미리 만들기 |
| 부분 표시 | head / grep / bat | 원본 파일을 지우지 않기 |
| 중간에 끊겼을 경우 복구 | codex exec resume --last "..." | 직전 세션 한정 |
| CI에서의 비대화 실행 | codex exec ... < /dev/null | stdin을 반드시 닫기 |
GitHub Actions에 올릴 때는 이 형태가 안정적입니다.
- name: Codex review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
...
마지막 test -s가 효과를 발휘합니다. 파일이 비어있으면 작업(job)이 실패하므로, '아무것도 건지지 않았는데 성공 처리'하는 것을 막을 수 있습니다. 함정 1과 같은 누락은 여기서 처음으로 감지됩니다.
- 가변 길이 인수를 가진 옵션의 뒤에 위치 인수를 넣지 마세요.
-i외에도 동일하게 발생합니다 -
<<<는 줄 바꿈이 혼입됩니다. 엄격하게 전달하고 싶다면printf '%s'를 사용하세요. | tail은 SIGPIPE로 상류 프로세스를 죽일 수 있습니다. 파일 경유로 하세요 -
--output-last-message의 출력지는 사전에mkdir -p를 해야 합니다 -
버전별로 동작이 바뀌므로codex --version을 반드시 로그에 남기세요
Q. --로 구분하면 해결되나요?
A. 효과가 있는 경우가 많지만 인자 파서(argument parser)에 의존적입니다. stdin 방식으로 통일하는 것이 장기적으로 안전합니다.
Q. 리뷰 결과는 터미널 방식이 좋은가요, 파일 방식이 좋은가요?
A. 1차 저장은 파일, 열람은 터미널입니다. --output-last-message로 .codex/review.md에 기록하고, bat이나 delta로 색상 표시를 합니다. CI에서는 파일이 유일한 정답입니다.
Q. 출력이 중간에 끊겼는지 판별하는 방법은요?
A. 출력의 맨 앞에 반드시 High라는 제목을 포함하도록 프롬프트에서 지정하고, grep -q '^## High'로 검사합니다.
codex exec의 두 가지 함정은 둘 다 에러를 내지 않고 조용히 망가지는 것이 본질적인 문제입니다. 대책은 간단하여, 프롬프트는 stdin으로부터 -로 전달하고, 출력은, 그리고 --output-last-message로 파일에 남기는 빈 파일을 감지해서 실패하게 만드는 것. 이 3가지를 템플릿화해 버리면, 리뷰 자동화는 안정됩니다. 복구 수단으로 resume --last도 함께 기억해 두면, 사고가 났을 때 만회하기 빠릅니다. BENTEN Web Works — 업무 자동화・시스템 개발의 프리랜서 엔지니어입니다.
GAS / Python / RPA를 사용한 업무 자동화나, 웹 제작・시스템 개발에 대한 상담을 받고 있습니다.
'이런 것도 자동화할 수 있을까?'라는 질문만이라도 부담 없이 문의해 주세요.
👉 업무 자동화 서비스 — 상세/문의는 여기를 클릭
🐦 X (구 Twitter) — 매일의 지식을 발신 중
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기