Post

AI가 코드를 빨리 쓸수록 더 중요해진 것

AI가 코드를 빨리 쓸수록 더 중요해진 것

Intro

에이전틱 코딩을 본격적으로 쓰기 시작하고 나서 가장 먼저 달라진 건 속도였습니다. 작업 리듬이 바뀌었고, 결과물도 빠르게 나왔습니다. 문제는 그 이후에 왔습니다. 속도가 빨라질수록 코드베이스가 더 쉽게 흐트러졌고, 어느 시점부터는 새로운 작업을 시작하기 전에 먼저 되돌려야 할 게 더 많아졌습니다.

이 글은 그 체감을 정리한 기록입니다. 에이전틱 코딩에서 무엇을 해야 하는지 알려주는 글이 아닙니다. 제가 겪은 범위에서, 엔트로피가 예상보다 훨씬 빠르게 쌓이는 이유가 무엇인지, 그리고 그 문제를 줄이기 위해 지금 무엇을 시도하고 있는지를 써두려 합니다.


빠르게 쌓이는 엔트로피

먼저 인정해야 할 부분이 있습니다. 작은 단위의 코딩만 놓고 보면, 에이전트가 사람보다 훨씬 잘한다고 느끼는 순간이 많았습니다. 이미 책임이 정해진 함수 수정, 테스트 보강, 익숙한 패턴의 코드 작성에서는 사람이 손으로 따라가기 어려운 속도와 정확도를 보여줬습니다. 모델이 좋아지면서 맡길 수 있는 범위도 계속 넓어졌습니다.

그런데 범위가 넓어질수록 다른 문제가 더 빨리 드러났습니다. 구조나 기준 없이 작업을 이어가면, 코드베이스의 엔트로피가 결과물의 양보다 더 빠르게 올라가는 것처럼 느껴졌습니다. 제가 주로 본 증상은 비슷했습니다.

  • 비슷한 책임이 여러 위치에 흩어집니다.
  • 같은 개념을 가리키는 이름이 문맥마다 달라집니다.
  • 새 기능이 기존 구조를 정리하기보다 그 위에 얹힙니다.
  • 한 번 만들어진 패턴이 의도된 설계인지와 무관하게 반복됩니다.

이런 문제는 사람이 직접 코드를 작성할 때도 생깁니다. 다만 에이전틱 코딩에서는 누적 속도가 달랐습니다. 변경량이 늘어난 만큼, 작은 선택들이 쌓이는 속도도 빨라졌기 때문입니다.

여기서 제가 중요하게 보게 된 것은 감당 가능한 엔트로피의 한계였습니다. 사람이나 에이전트나 프로젝트의 복잡도를 무한히 감당할 수는 없습니다. 차이가 있다면 한계가 드러나는 방식과 속도에 가까웠습니다. 암묵적 맥락과 과거 선택의 흔적이 일정 수준을 넘으면, 현재 컨텍스트만으로 안정적인 방향을 잡기 어려워 보였습니다.

돌이켜보면 여러 개발 방법론도 이 문제를 다루기 위한 장치에 가깝지 않을까 생각하게 됐습니다. 레이어, 도메인 경계, 테스트, 리뷰는 복잡하게 얽힌 소프트웨어를 사람이 이해할 수 있는 단위로 낮추려는 시도처럼 보였습니다.

새 기능 개발도 비슷했습니다. 제가 기대하는 새 기능 개발은 단순한 코드 추가가 아니라, 새 코드가 들어갈 수 있도록 기존 엔트로피를 낮추는 작업까지 포함합니다. 하지만 명시적으로 요청하지 않으면 에이전트는 대체로 기존 구조를 최대한 보존한 채 새 코드를 얹는 쪽을 택하는 것처럼 보였습니다. 때로는 리팩터링을 요청해도 기존 작업을 보존하려는 힘이 더 크게 작동하는 느낌이 있었습니다.

문제는 기존 코드가 무질서한 상태일 때 더 커졌습니다. 별도의 규칙이나 가이드를 주지 않아도, 에이전트는 이미 짜여 있는 코드를 사실상의 가이드처럼 읽는 순간들이 있었습니다. 그 코드가 의도된 설계인지, 우연히 쌓인 흔적인지와는 별개로 비슷한 패턴이 반복되는 것처럼 보였습니다.

제가 겪은 흐름을 조금 구조화하면 대략 이랬습니다.

  1. 기능은 빠르게 추가됩니다.
  2. 그 사이에 복잡도는 생각보다 훨씬 빠르게 불어납니다.
  3. 복잡도가 커진 만큼 구조를 다시 잡기 위한 비용도 같이 커집니다.
  4. 더 난감한 경우에는 비용을 들여도 복잡도가 생각만큼 낮아지지 않습니다.

마치 local minima에 갇힌 것처럼, 계속 고치고 있는데도 더 나은 구조로 빠져나가지 못하는 듯한 순간들이 있었습니다. 에이전트가 코드를 못 짜서라기보다는, 잘못된 환경에 너무 잘 맞춰 움직이면서 생기는 문제에 가까워 보였습니다.

이 지점에서 제게는 질문이 하나 생겼습니다. 에이전트가 제가 기대한 방향으로 나아가지 못했다면, 이유는 무엇이었을까.

  • 제가 목표를 충분히 명확하게 주지 못했거나, 에이전트가 좋은 판단을 할 수 있는 환경을 만들어주지 못했을 수 있습니다.
  • 반대로 모델의 성능이 아직 그런 수준에 닿지 못했을 수도 있습니다. 목표나 환경이 충분히 정리되지 않아도 알아서 좋은 구조를 찾아내고, 필요한 리팩터링까지 해가며 움직이기에는 아직 어려운 것일 수 있습니다.

둘 중 어느 쪽이든 제가 당장 바꿀 수 있는 것은 모델의 성능이 아니라, 에이전트가 참조할 환경이었습니다.


결이 다른 두 가지 규칙

그래서 규칙을 만들기 시작했습니다. 처음에는 “이건 이렇게 해줘, 이건 하지 마” 수준의 단순한 기준이었습니다.

시간이 지나면서 모든 규칙을 같은 밀도로 적을 필요는 없다는 걸 알게 됐습니다. 모델 성능이 좋아지면서, 짧게 언급해도 대체로 잘 따라오는 규칙과 그렇지 않은 규칙이 갈라졌습니다.

제가 보기에는 규칙을 먼저 두 종류로 나눠야 했습니다.

  • 좋고 나쁨의 규칙: 중복을 줄인다, 테스트 가능한 단위로 분리한다, 예외 처리를 명시한다.
  • 선택의 규칙: 상태 관리를 어디에 둘지, API 계층을 어떻게 나눌지, 도메인 로직과 UI 로직의 경계를 어디에 그을지 정한다.

좋고 나쁨의 규칙은 비교적 보편적인 소프트웨어 품질과 맞닿아 있습니다. 그래서 모델이 이미 알고 있는 일반적인 코드 품질 기준을 끌어다 쓸 수 있습니다. “중복을 줄여줘”, “테스트 가능한 단위로 나눠줘” 정도의 지시만으로도 어느 정도 기대한 방향에 가까워졌습니다.

반면 선택의 규칙은 일반 지식만으로 결정하기 어렵습니다. 어느 쪽이 더 좋다는 문제가 아니라, 이 프로젝트가 이미 어떤 선택을 해왔는지의 문제이기 때문입니다. 같은 상태 관리 방식이라도 어떤 프로젝트에서는 맞고, 다른 프로젝트에서는 어긋날 수 있습니다.

선택의 규칙이 없을 때 제가 반복해서 보게 된 흐름은 대략 이랬습니다.

  1. 에이전트가 매 요청마다 그럴듯한 선택을 새로 하는 것처럼 보입니다.
  2. 각각의 선택은 그 순간만 보면 틀렸다고 말하기 어렵습니다.
  3. 하지만 서로 다른 선택이 누적되면 코드베이스의 방향이 흩어지는 느낌이 생깁니다.
  4. 여기에 기존 구조를 보존한 채 새 코드를 얹는 경향이 겹치면 엔트로피가 다시 올라가는 것처럼 느껴졌습니다.

이런 선택들이 계속 쌓이면, 결국 프로젝트가 사람의 인지 수준 안에서 이해하기 어려운 상태로 밀려나는 것 같았습니다. 앞에서 말한 실패도 같은 방향에 있다고 생각합니다. 코드가 동작하지 않는 문제가 아니라, 사람이든 에이전트든 안정적으로 판단하기 어려운 복잡도로 프로젝트가 흘러가는 문제였습니다.

그래서 다음 시도는 “가능한 한 많은 선택을 정해두자”는 수준을 넘어서 에이전트가 작업 중에 새로 판단해야 하는 상황 자체를 최대한 마주치지 않도록, 처음부터 거의 모든 것을 정의해보려는 방향으로 갔습니다.


단일 규칙 파일의 한계

두 종류의 규칙을 모두 명시하다 보니, 문서화해야 할 내용도 자연스럽게 늘어났습니다. 처음에는 모든 규칙을 하나의 파일에 넣기 시작했습니다. 에이전트가 알아야 한다고 생각한 내용을 전부 적어두면 매번 같은 기준으로 작업할 수 있을 것이라 기대했습니다. 효과는 분명 있었습니다. 반복되는 실수가 줄었고, 같은 종류의 파일들은 마치 템플릿 엔진을 거친 것처럼 구조와 표현이 안정됐습니다. 파일을 생성하는 위치나 코드를 추가하는 위치도 훨씬 일관됐습니다. 코드의 모양, 생성 위치, 읽는 흐름 같은 여러 관점에서 복잡도가 낮아지는 체감이 있었습니다. 엔트로피가 줄어들면서 일관성가독성이 좋아지는 느낌도 분명했습니다.

그런데 규칙 파일이 길어지면서 세 가지 문제가 드러났습니다.

  • 규칙이 늘어날수록, 필요한 규칙을 누락하는 빈도가 조금씩 늘어났습니다.
  • 아무리 신중하게 작성해도, 서로 논리적으로 충돌하거나 두 조건을 동시에 만족시키기 어려운 규칙이 생겼습니다.
  • 대화 컨텍스트가 길어지면 처음에는 잘 따르던 규칙도 어느 순간 놓치는 경우가 있었습니다.

그래서 한동안은 단일 규칙 파일 안에서 최대한 잘 동작하게 만드는 쪽으로 개선했습니다. 규칙을 더 짧게 압축하고, 서로 겹치는 문장을 줄이고, 충돌할 만한 표현을 걷어냈습니다. 이해하기 어려운 맥락은 별도로 설명하거나 예시를 붙였습니다. 이 방식도 어느 정도 효과가 있었습니다. 단일 파일 안에 기준이 모여 있으니, 에이전트가 적어도 한 번은 같은 문맥을 읽고 작업을 시작할 수 있었기 때문입니다.

여러 파일로 나누는 시도도 해봤지만, 처음에는 기대만큼 잘 동작하지 않았습니다. 파일을 나누면 각 문서는 짧아졌지만, 에이전트가 지금 어떤 파일을 읽어야 하는지 판단하지 못하면 오히려 필요한 규칙을 놓쳤습니다. 규칙을 분리하는 것만으로는 부족했고, 분리된 규칙을 찾는 방법까지 같이 설계해야 했습니다.

체감이 달라진 건 Claude Opus 4.6부터였습니다. 제가 써본 범위에서는 단일 규칙 파일 환경에서도 처음으로 꽤 안정적으로 규칙을 지키며 개발한다고 느낀 모델이었습니다. 이 부분은 단순히 지시를 잘 따르는 능력만의 문제는 아닌 것 같습니다. MRCR v2 같은 긴 컨텍스트 벤치마크에서 Opus 4.6의 성능이 크게 올라간 것을 보면, 방대한 규칙 파일 환경에서는 “규칙을 따를 줄 아는가”만큼이나 “긴 대화와 긴 문서 속에서 앞의 규칙을 끝까지 잊지 않는가”가 중요해 보였습니다. 물론 긴 컨텍스트 능력만으로 충분하다는 뜻은 아닙니다. 규칙을 얼마나 정확히 따르는지 보려면 IFEval 같은 instruction following 벤치마크도 함께 봐야 한다고 생각합니다.

참고로 Anthropic의 Opus 4.7 system card와 여러 외부 리뷰에서는 MRCR v2 8-needle 기준으로 Opus 4.7이 Opus 4.6보다 크게 낮은 점수를 보였다는 내용이 확인됩니다. 이후 Opus 4.8 발표에서는 MRCR v2보다 코딩, 에이전틱 작업, 전문 업무 벤치마크가 더 전면에 나왔습니다.

Anthropic은 MRCR v2가 긴 문맥 속 유사한 항목을 구분해 찾는 능력을 강하게 측정하지만, 실제 작업 전체를 대표하는 지표로는 한계가 있다는 취지의 설명도 합니다. 그 설명은 이해됩니다. 다만 제 워크플로우처럼 방대한 규칙과 긴 대화 속에서 앞의 조건을 잊지 않는 능력이 중요한 환경에서는, 여전히 MRCR v2가 꽤 의미 있는 신호처럼 느껴졌습니다.

그래서 우스갯소리로 Opus보다 상위 프론티어 모델인 Fable 5은 4.7이나 4.8의 연장선이 아니라, 처음 등장했을 때 유난히 영특하게 느껴졌던 4.6을 다시 데려와 개선한 버전이 아니냐는 말도 나오는 것 같습니다.

생각이 바뀐 계기는 단순히 긴 컨텍스트에서 앞의 내용을 덜 잊는다는 점만은 아니었습니다. 긴 작업을 끝까지 물고 가며 추적하고, 중간에 놓치지 않고 마무리하는 능력이 꽤 좋아졌다고 느꼈습니다. 그렇다면 이제는 규칙을 여러 파일로 나누어도, 필요한 맥락을 찾아가며 잘 동작하지 않을까 하는 생각이 들었습니다.

그래서 규칙을 영역별로 다시 나누기 시작했습니다. 여기서 핵심이라고 느낀 건 단순한 파일 분리가 아니라 탐색 가능성이었습니다. 에이전트가 지금 어떤 작업을 하는지에 따라 어떤 규칙 파일을 읽어야 하는지 알 수 있어야 했습니다.

지금은 세 가지를 조합합니다. 영역별로 규칙 파일을 나누고, 어떤 상황에서 어떤 파일을 읽어야 하는지 라우팅 정보를 담은 인덱스 문서를 둡니다. 여기에 관련 파일을 찾을 때 참고할 수 있는 glob 패턴 같은 힌트도 함께 넣습니다. 마지막으로 에이전트에게 그 인덱스를 어떻게 활용해야 하는지 짧은 가이드를 붙입니다.

이 방식이 가능한 이유도 따로 있었습니다. 프로젝트 초반부터 디렉터리 구조, 파일 이름, 책임 분리 같은 컨벤션을 꽤 강하게 잡아두었기 때문입니다. 규칙 파일을 나눠도 어디를 찾아야 하는지 예측할 수 있으려면, 코드베이스 자체도 어느 정도 탐색 가능한 형태로 정리되어 있어야 했습니다.

예상과 달리 꽤 잘 동작했습니다. 에이전트는 필요한 규칙만 읽고도 단일 파일에 가까운 일관성을 유지했습니다. 아직 정량적으로 비교할 수단이 없어서, 이 방식이 얼마나 더 낫다고 단언하기는 어렵습니다. 그래도 방향은 분명해진 것 같습니다. 규칙은 한곳에 무한히 쌓기보다, 필요한 시점에 발견될 수 있도록 설계하는 게 낫습니다.

지금은 여기서 더 나아가 hook이나 메모리 시스템을 함께 쓰는 방법도 시도하고 있습니다. 에이전트가 매번 규칙을 수동으로 떠올리기를 기대하기보다, 필요한 시점에 더 정교하고 정확하게 맥락을 꺼내 쓰게 만드는 쪽에 가깝습니다.


규칙을 넘어선 컨텍스트

시간이 지나면서 규칙만으로는 부족하다는 것도 알게 됐습니다. 프로젝트가 진행되는 과정에서 생기는 다른 종류의 컨텍스트도, 에이전틱 코딩에서는 규칙만큼 중요한 기준이 됐습니다. 왜 이 구조를 선택했는지, 어떤 대안을 버렸는지, 어떤 제약 때문에 타협했는지 같은 내용은 코드만 읽어서 복원하기 어려웠습니다.

그래서 이런 컨텍스트를 주입 가능한 형태로 관리하는 방법을 찾기 시작했습니다. 특히 ADR 같은 결정 문서를 가능한 한 남기고, 작업을 시작할 때 그 문서를 컨텍스트로 활용하는 시도를 했습니다. 결정 문서가 많지 않았을 때는 꽤 잘 동작했습니다. 에이전트가 코드만 보는 것이 아니라, 그 코드가 왜 그런 모양이 되었는지까지 함께 읽을 수 있었기 때문입니다.

그런데 여기서도 다시 문제가 생겼습니다. 결정 문서는 그 순간의 상태에서 어떤 결정을 내렸고, 그 결과 새로운 상태가 만들어졌다는 기록에 가깝습니다. 즉, 어떤 시점의 결정은 과거의 여러 결정을 부분적으로 바꾸거나, 때로는 완전히 무효화할 수 있습니다.

문제는 문서가 시간 순서대로 쌓인다고 해서 현재의 논리적 최종 상태가 바로 드러나지는 않는다는 점이었습니다. 최신 결정을 이해하려면 과거 결정들을 따라가며 어떤 것이 유지되고, 어떤 것이 대체됐고, 어떤 것이 더 이상 유효하지 않은지 계산해야 합니다.

극단적으로 생각하면, 1년 동안 수많은 결정이 쌓여 있다가 마지막에 “그동안의 모든 결정을 철회한다”는 결정이 추가될 수도 있습니다. 이때 에이전트가 시간순 문서를 처음부터 읽고 현재의 최종 상태를 제대로 계산해낼 수 있을까 하는 의문이 들었습니다.

사람도 이걸 매번 정확히 하기는 어렵습니다. 에이전트에게는 더 어렵습니다. 오래된 결정 문서를 잘못 읽으면, 이미 폐기된 선택을 지금도 유효한 기준으로 오해할 수 있습니다.

그래서 지금은 결정 문서를 단순히 많이 남기는 것보다, 최종 상태가 계산된 문서를 함께 관리하는 것이 중요하다고 생각하고 있습니다. 결정의 원문은 시간순 기록으로 보존하되, 에이전트가 참조할 때는 현재 유효한 상태가 계산된 문서를 보게 하는 방식입니다. 이벤트 소싱에서 스냅샷을 만들어 중간 상태를 저장하는 것처럼, 중간 단계의 상태를 계산해두거나 최종 상태를 계속 갱신해 참조시키는 방법을 시도하고 있습니다.

그 시도의 일환으로 메모리 시스템도 함께 써보고 있습니다. 흥미로웠던 점은, 메모리 시스템을 평가하는 벤치마크에서도 이미 비슷한 문제가 중요한 축으로 다뤄진다는 점이었습니다. 예를 들어 LongMemEval이나 LOCOMO 같은 벤치마크는 단순히 과거 사실을 기억하는지만 보지 않고, 시간 순서에 따른 추론이나 지식이 갱신됐을 때 최신 상태를 제대로 따라가는지도 평가합니다. 제가 결정 문서에서 겪은 문제도 결국 비슷했습니다. 과거의 기록을 많이 가지고 있는 것보다, 시간에 따라 바뀐 내용 중 지금 유효한 상태를 정확히 계산해낼 수 있는지가 더 중요했습니다.


자동화보다 판단 환경

최근에는 하네스 엔지니어링, 루프 엔지니어링, 동적 워크플로우, 에이전트 스웜처럼 사람의 개입을 더 줄이는 방향의 시도도 많이 보입니다. 저도 그 방향이 틀렸다고 생각하지는 않습니다. 모델이 좋아질수록 사람이 직접 챙기던 절차 중 일부는 모델이나 하네스가 흡수하게 될 가능성이 높다고 봅니다.

다만 지금 제 워크플로우에서는 우선순위가 조금 다릅니다. 제가 먼저 줄이고 싶은 것은 사람의 개입 횟수라기보다, 프로젝트가 감당하기 어려운 방향으로 복잡해지는 속도입니다. 앞에서 말한 것처럼 엔트로피를 낮추고, 사람이 인지 가능한 수준의 프로젝트를 유지하고, 지속 가능한 형태로 개발을 이어가는 것이 아직은 더 중요하게 느껴집니다.

그래서 아직은 사람의 개입이 상대적으로 더 들어가는 방향으로 개발하고 있습니다. 이유를 정리하면 대략 세 가지입니다.

  1. 에이전트가 모든 선택을 안정적으로 대신할 만큼 완벽하다고 느끼지는 않습니다.
  2. 사람도 특정 시점에 미래의 모든 요구사항을 완벽하게 명세할 수 없습니다.
  3. 개발에는 옳고 그름보다 정답이 없는 선택의 순간이 더 많고, 그 선택을 항상 제가 원하는 방향으로 에이전트가 해주리라고 기대하기는 어렵습니다.

이 관점에서는 범용 하네스 오케스트레이션보다, 프로젝트의 특성에 맞춘 커스텀 하네스가 더 자연스러웠습니다. 모든 것을 일반화하려 하기보다, 이 프로젝트에서 반복되는 판단과 컨텍스트 주입 과정을 먼저 안정화하고 있습니다. 그중 일반화할 수 있는 부분만 조금씩 바깥으로 꺼내는 쪽에 가깝습니다.

물론 이 방향이 정답인지는 아직 모르겠습니다. 최신 트렌드와 모델의 변화, 그리고 제가 실제로 겪은 불편함 사이에서 계속 조정하는 중입니다. 다만 지금까지의 경험으로는, 모델의 성능 향상에 모든 것을 맡기기보다 모델이 좋은 판단을 하기 쉬운 환경을 설계하는 쪽이 더 안정적으로 작동했습니다.


마치며

저는 Cursor가 서비스를 열었을 때부터 결제해서 써왔습니다. 그동안 여러 방식으로 시도해봤고, 솔직히 이런 세상이 이렇게 빨리 올 거라고는 생각하지 못했습니다. 이 글은 그 과정에서 생긴 고민과 문제의식, 그리고 지금 제가 시도하고 있는 방향을 정리해본 기록에 가깝습니다.

에이전트에게 더 많은 일을 맡기는 것은 분명 중요합니다. 생산성이 올라가는 체감도 큽니다. 하지만 생산성이 늘어나는 만큼, 그 속도를 지속 가능한 방향으로 누적시키는 일도 중요하다고 생각합니다.

물론 이 방향이 정답이라고 말하고 싶지는 않습니다. 모델의 성능이 좋아지면서 지금 제가 공들여 만들고 있는 방법 중 일부는 모델의 기본 능력으로 흡수될 수도 있습니다. 그래서 더 궁금합니다. 다른 개발자들은 이 변화 속에서 어떤 문제를 겪고 있고, 어떤 방법을 시도하고 있는지요.

대 AI 시대, 에이전틱 코딩, 누구나 메이커가 될 수 있다고 말하는 시대입니다. 개발자의 역할이 사라질 수도 있다는 이야기도 계속 나옵니다. 그런 흐름 속에서 개발자 동료 여러분은 무엇을 시도하고 있고, 어떤 방식으로 살아남거나 적응하고 있습니까?

This post is licensed under CC BY 4.0 by the author.