AI가 짠 코드의 구조적 결함, 팀이 잡는 법

AI가 짠 코드의 구조적 결함, 팀이 잡는 법

린트 경고가 숨긴 암묵적 계약과 에이전트가 만든 상태 아키텍처의 구멍—코드 생성 이후 품질 보증을 어떻게 설계할 것인가

AI 코드 품질 린트 경고 상태 관리 LLM 생성 코드 코딩 에이전트 로컬 우선 암묵적 계약 AI-First 워크플로우
광고

에이전트가 코드를 빠르게 뽑아낸다. 문제는 그 다음이다. 동작하는 것처럼 보이는 코드가 실제로는 암묵적 계약 위에 얹혀 있거나, 상태 아키텍처가 처음부터 잘못된 방향으로 굳어가고 있는 경우가 많다. 속도는 얻었지만, 구조적 부채는 조용히 쌓인다.

린트 경고는 '정리 요청'이 아니다

dev.to에 올라온 S.A. Shkuratov의 글 "Not Every Lint Warning Is Cosmetic"은 이 문제를 정면으로 건드린다. pylint, flake8, mypy를 돌리다 보면 흔히 "이건 그냥 네이밍 스타일 문제잖아"라고 넘기고 싶은 경고들이 나온다. 그런데 그 경고들이 실제로는 코드베이스 안에 숨어 있는 '암묵적 계약'을 가리키는 신호였다는 것이 이 글의 핵심 주장이다.

네 가지 실제 사례가 설득력 있다. Enum 네이밍 정규화가 SQLAlchemy의 퍼시스턴스 시맨틱 문제로 이어졌고, 함수 시그니처 경고가 소유권 체크 누락을 드러냈다. 모듈 크기 경고는 경계 분리가 필요하다는 신호였고, docstring 경고는 API 라이프사이클 계약을 명시적으로 만들어야 한다는 압력이었다. 겉으로는 코스메틱처럼 보이는 것들이 실제로는 "이 코드에서 중요한 계약이 아직 암묵적 가정 위에 앉아 있다"는 가장 이른 신호였다는 것이다.

LLM이 빠르게 초안을 만들어준 코드에서 이 문제가 특히 두드러진다. LLM은 로컬에서 그럴듯하게 보이는 코드를 잘 만든다. 함수 하나만 봐서는 문제없어 보인다. 하지만 모듈 경계, 도메인 계약, 영속성 시맨틱 같은 '전역 맥락'을 LLM이 항상 제대로 반영한다고 기대하기 어렵다. 린트 경고는 바로 그 지점을 짚어준다. 정리 도구가 아니라, 암묵적 계약을 명시적으로 만들라는 강제 장치다.

에이전트가 만든 상태 아키텍처의 구조적 함정

상태 관리는 더 심각하다. dev.to의 또 다른 글 "Why agent-built apps need a local-first state layer"는 Claude Code, Cursor 같은 코딩 에이전트가 만든 앱의 전형적인 패턴을 정확히 짚는다. 에이전트는 UI 컴포넌트에서 서버를 직접 호출하는 방식을 기본값으로 선택한다. 빠르게 동작하는 데모를 만드는 최단 경로이기 때문이다.

문제는 이 패턴이 퍼지는 속도다. 컴포넌트마다 fetch를 직접 호출하고, 같은 데이터의 다른 버전이 여러 컴포넌트에 분산되고, 낙관적 업데이트는 매번 일회성 핵으로 처리된다. 결국 앱 전체에 명확한 상태 경계가 없는 상태로 굳어버린다. 이 글의 저자가 만든 VibeLayer라는 오픈소스 프로젝트는 그 해법으로 로컬 우선 상태 레이어를 제안한다. 핵심 규칙은 단순하다: UI는 로컬 상태에서 읽고, 명명된 뮤테이션을 통해서만 쓴다. 뮤테이션은 로컬에 먼저 퍼시스트되고, 백엔드 동기화는 나중에 일어난다.

이 접근이 흥미로운 이유는 에이전트를 더 똑똑하게 만들려는 시도가 아니라는 점이다. 에이전트에게 더 좁은 선택지를 주는 것이 목표다. 컴포넌트에서 fetch를 직접 쓰지 못하게 구조가 막아서면, 에이전트도 그 경계 안에서만 움직인다. 아키텍처 제약이 에이전트의 '나쁜 기본값'을 차단하는 가드레일이 되는 것이다.

두 문제가 가리키는 하나의 실천

두 글이 서로 다른 레이어에서 같은 문제를 다루고 있다는 게 흥미롭다. 린트 경고 이슈는 코드 레벨의 암묵적 계약을, 상태 아키텍처 이슈는 설계 레벨의 구조적 기본값을 다룬다. 하지만 둘 다 가리키는 방향은 같다. AI 생성 코드의 품질 보증은 코드가 만들어진 이후에 팀이 능동적으로 개입하는 구조를 필요로 한다는 것이다.

테크 리드 입장에서 이걸 팀 프로세스로 번역하면 이렇다. 첫째, 린트 파이프라인을 '스타일 교정기'가 아니라 '계약 감지기'로 재정의하라. pylint, mypy, flake8 경고가 나왔을 때 "이게 실제로 어떤 계약을 건드리고 있나"를 묻는 습관이 팀에 있어야 한다. 경고를 suppress하기 전에 한 번은 파고드는 것을 팀 규범으로 만드는 것이다. 둘째, 에이전트가 코드를 생성하기 전에 상태 아키텍처의 기본 규칙을 먼저 확정하라. 컴포넌트에서 직접 API 호출을 허용할 것인가, 상태 레이어를 어떻게 분리할 것인가—이 규칙이 없으면 에이전트는 항상 가장 빠른 경로를 선택하고, 그 선택이 수백 개의 컴포넌트에 복제된다.

전망: 가드레일 설계가 AI 코드 품질을 결정한다

AI 코딩 도구가 팀 워크플로우에 깊숙이 들어올수록, 품질 보증의 무게중심이 이동한다. '코드 리뷰에서 문제를 잡는 것'에서 '에이전트가 나쁜 선택을 하지 못하게 구조로 막는 것'으로. 린트 규칙, 아키텍처 가이드라인, 상태 레이어 컨벤션이 단순한 팀 코딩 스타일이 아니라 AI 생성 코드의 품질을 결정하는 가드레일이 된다.

에이전트는 더 빨라지고 있다. 하지만 빠르게 만들어진 코드가 팀이 오래 유지할 수 있는 코드가 되려면, 그 코드가 생성되는 구조 자체를 팀이 먼저 설계해야 한다. 속도는 에이전트가 챙긴다. 구조는 팀이 챙겨야 한다.

출처

더 많은 AI 트렌드를 Seedora 앱에서 확인하세요