2026년 8월 4일 · engineering

Architecture, Guidance, and the Rules (3)

GuidanceRulesCodex

서론 - Guidance도 낡는다

이전 글에서는 Guidance를 프로젝트의 구조와 약속을 Agent가 읽고 적용하는 경로로 설명했다. index.md는 요청과 변경 영역에 맞는 규칙을 선택하게 하고, 세부 Guidance는 프로젝트에서 지켜야 할 기준과 그 이유를 전달한다. 글의 마지막에는 한 가지 조건을 덧붙였다. 규칙의 적용은 엄격하되, 규칙 자체는 코드와 팀의 변화에 맞춰 수정하고 버릴 수 있어야 한다는 것이다. 이는 꽤 불편하면서도 유연한 부분이다. 여타 Harness 들은 생각보다 리팩토링의 대상이 되는 일이 드물었다. 애초에 우리 개발자가 오픈 소스 혹은 fork 한 Harness 에 대한 수정도 제한적이었다.

한편, Guidance는 작성한 순간부터 조금씩 낡기 시작한다. 코드의 구조가 바뀌고, 새로운 도구와 작업 방식이 들어오며, 한때 유효했던 예외가 사라지기도 한다. Guidance는 프로젝트와 거의 동일한 시계열을 공유한다. 코드와 어긋난 Guidance는 단순히 도움이 되지 않는 문서로 남지 않는다. Agent에게 잘못된 경로를 자신 있게 제시한다는 점에서, 아무 규칙도 없는 상태보다 더 큰 혼란을 만들 수 있다!

이번 글에서는 Guidance에 규칙을 더하는 방법보다, 이미 작성한 규칙을 어떻게 현재의 코드와 계속 맞춰갈 것인지 이야기하려 한다. 그 과정에서 내가 Loutine 레포지토리의 Guidance를 정리하며 겪은 사례와, 노후화를 정기적으로 점검하기 위해 구성한 Codex Scheduled Task를 함께 살펴본다.

1. 코드가 바뀌면 문서의 신뢰도가 흔들린다.

Guidance는 Agent의 구현 기준이 되어주는 만큼, 내 지시대로 구현이 되면 만족스럽지만 지시나 의도에 벗어난 아웃풋이 나올 때는 당혹스럽다. 처음엔 의심스럽지만 수용할 수 있을 정도의 결과가 나오지만, 어느 순간 부터는 초기에 그렸던 그림과는 많이 멀어지기도 한다. Guidance의 노후화는 어느 순간 갑자기 오지 않고 부지불식 간에 찾아온다.

하루는 내 프롬프트에 따라 나온 Navigation Route 구현 코드를 보고 약간은 의아한 감정이 들어 Loutine의 Guidance를 레포지토리 전체의 문서와 실제 구현을 다시 대조한 적이 있다. 그 과정에서 Guidance와 과거 문서가 현재 코드와 다른 방향을 가리키는 사례를 발견했다. Navigation 문서는 이미 사라진 추상을 기준으로 설명하고 있었고, Firebase와 CloudKit 관련 문서에는 현재 레포지토리가 제공하지 않는 기능이나 비활성화된 설정이 섞여 있었다.

Guidance의 내용은 한때는 맞았을 수 있다. 그러나 코드와 의사결정이 바뀐 뒤에도 같은 문장이 남으면서 과거의 사실이 현재의 규칙처럼 보이게 되었다. 이 문제를 해결하기 위해 현 시점의 코드와 열려있는 Github Issue, 승인된 ADR을 다시 기준으로 삼아서 Guidance와 대조했다. 실제 Navigation 구성 요소와 SwiftData 설정을 확인하고, 완료된 Github Issue의 프롬프트에는 stale 문서라 표시했다. 한편, index.md에는 현재 코드, ADR, Guidance, 과거 계획이 충돌할 때 무엇을 우선해야 하는지도 명시하여 문서 간 신뢰도 우선순위를 정리했다. 마지막으로 Guidance와 실제 코드 간 괴리를 Agent와 함께 검토하고 필요하다면 Guidance의 내용을 수정한다.

이 수정 과정이 좋은 점은 내 프로젝트의 코드 구조와 패턴의 "기준"이 어떻게 이동하고 있는지를 파악할 수 있다는 점이다. Guidance는 작성 당시의 프로젝트 구조와 의사 결정 사항들, 유효한 패턴을 담고 있기 때문에 시간이 지남에 따라 이 기준은 변동할 수 있고, 아주 높은 확률로 크게 변화하게 된다. Data Layer가 참조할 Repository Layer의 provider가 바뀌는 경우가 있을 수 있고, 서버에서 캐시 정책을 수정함에 따라 클라이언트에서도 이에 맞는 패턴으로 수정해야할 수도 있다. 따라서 Guidance의 점검은 문서의 항목을 수정하는 정도의 업데이트가 아니라 문서와 의사결정 간의 움직임, 기준을 참고하여 신뢰도를 다시 세우는 일에 가깝다.

2. 현실과 충돌한 규칙은 더 구체적으로 바뀐다

Guidance가 현실과 충돌했다고 해서 항상 규칙을 없애야 하는 것은 아니다. 기존 원칙은 유지하면서 실제 필요를 좁은 예외로 기록해야 할 때도 있다. 내 Loutine 프로젝트를 기준으로, 각 모듈간 의존 관계를 예시로 들 수 있다.

나는 초기에 Loutine의 Domain 계층이 Shared 구현에 의존하지 않는 것을 기본 원칙으로 삼았다. 그러나 Routine UseCase의 기존 catch 경계에서 오류를 기록하려면 RoutineDomainImplementationHelperMyLogger를 사용해야 했다. 로깅을 위해 전체 의존성 원칙을 풀어버리면 다른 Shared 모듈까지 Domain 계층으로 들어올 근거가 생긴다. 반대로 원칙만 고수하면 이미 합의한 오류 기록을 구현할 수 없었다.

그래서 예외의 범위를 다음과 같이 제한했다. 이러한 제한사항은 너무나 디테일하고 불필요한 제약으로 볼 수도 있다. 사람에게 적용하기에는 지켜지기에도 쉽지 않을 수 있고 에러에 취약하기도 하다. "사람에게 적용하기에는" 그렇지만 Agent에게는 아니다. 어느 정도까지 이런 형태의 if-else if 형태의 예외가 가능한지는 나 역시 알아가고 있다.

  • Helper에 직접 의존할 수 있는 대상은 RoutineDomainImplementation뿐이다.
  • 이 때, MyLogger.error는 UseCase의 catch 경계에서 사용한다.
  • RoutineDomainInterface는 계속 프레임워크와 Shared 구현으로부터 독립적이어야 한다.
  • 이 예외를 다른 Domain-to-Shared 의존성의 선례로 사용하지 않는다.

좋은 예외는 원칙을 흐리는 문장이 아니라 원칙이 어디까지 유효한지 더 정확하게 보여주는 문장이다. 반복되는 충돌을 근거 없이 허용하는 대신, 허용할 대상과 이유, 확장해서는 안 되는 경계를 함께 남기고 있다.

반대로 한 번 발생한 상황을 모두 Guidance에 기록할 필요는 없다. 특정 작업에서만 필요한 명령 순서라면 Skill이나 작업 계획에 더 가깝다. 코드로 판별할 수 있는 조건은 테스트나 정적 검사로 옮기는 편이 낫다. Guidance에는 여러 작업에서 반복해 판단해야 하고, 코드만 읽어서는 그 이유를 복원하기 어려운 프로젝트의 약속이 남아야 한다. 말 그대로 프로젝트의 토대에 가까운 기준이 Guidance가 될 수 있는 것이다.

3. 문서의 규칙과 실행 가능한 검증을 나눈다

Guidance는 개발자의 의도와 판단 기준을 설명할 수 있지만, 그 문장이 현재 코드와 일치하는지 스스로 확인하지는 못한다. 그래서 기계적으로 판별할 수 있는 조건은 실행 가능한 검증으로 연결해야 한다.

예를 들어 index.md가 가리키는 파일이 실제로 존재하는지, 저장소의 검증 명령이 package.json이나 프로젝트 설정과 일치하는지, 제거된 도구 이름이 문서에 남아 있는지는 스크립트나 검색으로 확인할 수 있다. 테스트할 수 있는 동작을 장문의 Guidance로만 강제하는 것도 적절하지 않다. 테스트는 동작이 깨졌다는 사실을 보여주고, Guidance는 왜 그 동작을 지켜야 하는지, 어떤 기준 위에서 그 동작의 정합성이 타당한지를 설명한다.

당연하게도, 모든 노후화를 정적 검사로 찾을 수 있는 것은 아니다. 새로운 작업 방식이 반복되고 있는데 아직 문서에 반영되지 않았는지, 예외가 누적되어 기존 원칙을 다시 써야 하는지, 과거의 설명이 현재 코드의 의미를 왜곡하는지는 저장소의 맥락을 함께 읽어야 판단할 수 있다. 이 영역을 주기적으로 살펴보기 위해 나는 Loutine 프로젝트에 Codex Scheduled Task를 설정했다.

스크린샷 2026-08-04 오후 5.35.52.png

이 작업은 매주 AGENTS.md의 업데이트 필요성을 점검한다. 새로 발견한 워크플로, 명령어, 레포지토리 운영 규칙이 이미 Guidance에 반영되어 있는지 확인하고, 수정이 필요하다면 최소한의 변경만 제안한다. Scheduled Task는 내 검토 없이 파일을 수정하지는 않는다.

매주 Loutine 저장소의 AGENTS.md 업데이트 필요성을 점검하고, 실제 파일은 수정하지 말고 제안 보고만 해줘.

점검은 AGENTS.md, ~/.codex/guidance/index.md, 작업 방식과 관련된 Guidance를 정해진 순서로 읽는다. 필요한 경우에만 현재 설정이나 관련 문서를 추가로 확인한다. 결과는 변경 필요 여부, 제안하는 최소 패치, 그 판단의 근거와 아직 확인하지 못한 TODO로 나눈다. 근거가 부족하다면 규칙을 만들어내지 않고 TODO만 남긴다.

이렇게 구성한 이유는 Guidance의 유지보수까지 Agent에게 위임하기 위해서가 아니다. Agent의 권한을 불일치를 발견하고 보고하는 데까지만 제한하고 내가 프로젝트의 기준 변화에 둔감해지지 않기 위해서이다. Agent는 최근 작업과 현재 저장소를 대조해 검토할 지점을 제시하지만, 무엇을 프로젝트의 규칙으로 채택할지는 여전히 개발자가 결정한다.

4. Guidance를 유지하는 피드백 루프

Scheduled Task를 포함한 유지보수 흐름은 다음과 같이 정리할 수 있다.

코드와 작업 방식의 변화
    → Guidance와의 불일치 점검
    → 근거가 있는 최소 변경 제안
    → 개발자의 검토와 승인
    → Guidance의 수정·추가·삭제
    → 다음 작업에서 다시 적용하고 검증

이 흐름에서 자동화는 판단을 대신하지 않고 검토 주기를 만든다. 기능을 구현하는 세션은 당장의 완료 조건에 집중하기 쉽다. 반면 정기 점검은 여러 작업에서 반복된 변화가 있는지, 임시 예외가 사실상 새로운 원칙이 되었는지, 더 이상 사용하지 않는 설명이 남았는지를 한 걸음 떨어져 살펴보게 한다.

점검 결과가 항상 변경으로 이어질 필요도 없다. 현재 AGENTS.md가 여전히 저장소의 진입점 역할만 잘 수행하고 있다면 변경하지 않는 것이 좋다고 생각한다. 세부 규칙이 이미 적절한 Guidance 파일에 있다면 같은 내용을 루트 문서에 복제할 이유도 없다. Guidance의 유지보수는 문서를 계속 늘리는 작업이 아니라, 필요한 정보만 현재 위치에 남기는 작업이다.

규칙을 삭제해야 하는 시점도 같은 흐름에서 드러난다. 코드나 테스트가 이미 해당 제약을 구조적으로 강제하거나, 더 이상 존재하지 않는 도구와 경로를 설명하거나, 예외가 누적되어 기존 원칙이 현실을 설명하지 못한다면 문장을 보존하는 것보다 수정하거나 지우는 편이 낫다.

결론 - 엄격하게 적용하고, 쉽게 고친다

Architecture는 서비스의 의도를 코드의 구조에 담는다. Guidance는 Agent가 그 의도와 프로젝트의 약속을 읽고 적용할 수 있는 경로를 제공한다. 그러나 그 경로가 계속 유효하려면 현재 코드와 작업 방식에 맞춰 Guidance 자체를 검토해야 한다.

나는 Guidance를 한 번 작성하고 끝나는 규칙집보다 저장소와 함께 바뀌는 운영 문서에 가깝게 생각하게 되었다. 현실과 충돌한 원칙은 더 구체적인 예외로 다듬고, 기계적으로 확인할 수 있는 조건은 테스트와 검증으로 옮기며, 과거의 사실은 현재의 지시와 구분해야 한다.

Codex Scheduled Task는 이 과정에서 Guidance를 자동으로 고치는 장치가 아니다. 개발자가 다시 판단해야 할 시점을 놓치지 않도록 정기적으로 질문을 돌려주는 장치다. 자동화는 불일치를 발견하고 최소 변경을 제안하지만, 규칙을 채택하고 그 결과에 책임지는 일은 여전히 개발자의 몫으로 남는다.

결국 살아 있는 Guidance에 필요한 것은 더 많은 문서가 아니라 반복 가능한 피드백 루프다. 규칙은 적용할 때는 엄격해야 하지만, 더 이상 프로젝트의 현실을 설명하지 못한다면 언제든 수정하고 버릴 수 있어야 한다.