AI

Constraint Decay — LLM 에이전트가 구조적 제약 앞에서 무너지는 이유

자유로운 코드 생성에는 강한 LLM 에이전트가 API 계약·아키텍처 패턴·ORM 제약이 쌓이면 성능이 평균 30포인트 급락하는 현상을 분석한다.

10 min read
AILLMAgent코드 생성백엔드
Constraint Decay — LLM 에이전트가 구조적 제약 앞에서 무너지는 이유

LLM 에이전트가 "회원가입 엔드포인트 만들어줘"라고 하면 꽤 잘 만든다. 그런데 "FastAPI로, Clean Architecture 구조로, PostgreSQL을 SQLAlchemy ORM으로 연결해서, OpenAPI 명세에 맞게 만들어줘"라고 하면 어떻게 될까.

arxiv에 올라온 연구가 정확히 이 질문을 실험으로 검증했다. 결과는 예상보다 가파른 하락이었다.


Constraint Decay란

**Constraint Decay(제약 붕괴)**는 구조적 요구사항이 누적될수록 LLM 에이전트의 성능이 급격히 떨어지는 현상이다.

느슨한 명세에서는 강하다. "블로그 포스트 CRUD API 만들어줘"라는 요청에 에이전트는 꽤 잘 동작하는 코드를 만들어낸다. 그런데 기업 수준의 백엔드가 요구하는 제약들이 붙기 시작하면 이야기가 달라진다.

비유하면, 빈 종이에 집 그림을 그리라고 하면 잘 그리는 사람이 있다. 그런데 "설계도 규격은 이렇고, 건축법은 이렇고, 단열재는 이 등급, 창문은 이 방향으로, 배관은 이 규격"이라는 조건이 쌓이면 그림 실력이 아무리 좋아도 어디선가 어긋나기 시작한다. 조건 간 상충이 생기고, 우선순위 판단이 필요해지고, 전체를 한 번에 머릿속에 담기 어려워진다.

[💡 잠깐! 이 용어는?] OpenAPI 명세: REST API의 엔드포인트, 요청/응답 구조, 파라미터 등을 표준 형식으로 기술한 문서. 이 명세를 기준으로 클라이언트와 서버 간 계약이 정해진다.


실험 설계

연구팀은 이 현상을 체계적으로 측정하기 위해 동일한 OpenAPI 명세로 기능 요구사항을 고정했다. 기능 조건은 같고, 구조 조건만 다르게 쌓아가면서 성능 변화를 측정한다.

실험 규모:

구분내용
웹 프레임워크8개 (Flask, FastAPI, Django 등)
그린필드 과제80개 (처음부터 백엔드 구현)
기능 구현 과제20개 (기존 코드베이스에 기능 추가)
평가 방식E2E 동작 테스트 + 정적 구조 검증

구조적 제약은 4개 차원으로 나눴다:

  1. 프레임워크 선택 — Flask, FastAPI, Django 중 특정 프레임워크 지정
  2. 아키텍처 패턴 — Clean Architecture, 레이어드 아키텍처 등
  3. 데이터베이스 백엔드 — SQLite, PostgreSQL 등
  4. ORM 통합 — SQLAlchemy, Django ORM 등

기준 조건은 OpenAPI 명세만 주어진다. 제약 조건으로 갈수록 "Clean Architecture 구조로, PostgreSQL을, SQLAlchemy로 연결해서" 같은 요구사항이 추가된다.

[💡 잠깐! 이 용어는?] ORM(Object-Relational Mapping): 데이터베이스 테이블을 Python 클래스처럼 다룰 수 있게 해주는 도구. user.save() 한 줄이 내부적으로 SQL 쿼리로 변환된다. SQLAlchemy, Django ORM이 대표적이다.


핵심 결과

결론부터 말하면 제약이 쌓일수록 성능이 급락했다.

높은 구성 조건에서 완전 지정 과제로 갈수록 assertion pass rate가 평균 30포인트 하락했다.

30포인트면 단순한 성능 저하가 아니다. 합격 기준이 50%라고 했을 때, 80%에서 시작해서 50%로 떨어지면 그 에이전트는 더 이상 쓸 수 없는 수준이 된다는 의미다.

프레임워크별 성능 차이도 컸다:

프레임워크특성에이전트 성능
Flask가볍고 명시적, 관례 적음상대적으로 높음
FastAPI자동화 기능 많음, 비동기낮음
Django관례가 많고 암묵적 규칙 많음낮음

관례가 많은 프레임워크에서 낮은 성능이 나온 이유가 있다. Flask는 무엇을 어디에 두어야 하는지 명시적으로 작성해야 한다. 에이전트 입장에서는 암묵적인 규칙이 적으니 오히려 다루기 쉽다. 반면 Django는 "이 파일은 여기 있어야 하고, 이 메서드는 이렇게 오버라이드해야 하고, 이 설정은 settings.py에 있어야 한다"는 관례들이 쌓여 있다. 이 관례를 정확히 맞추지 못하면 기능은 되더라도 구조 검증에서 탈락한다.


데이터 계층이 병목이다

실패 원인을 분석하면 데이터 계층 결함이 압도적으로 많다.

에이전트 로직 실패의 약 **45%**가 잘못된 쿼리 구성과 ORM 런타임 위반에서 발생했다.

ORM이 어려운 이유를 생각해보면 당연한 결과다. ORM은 쓰는 법이 제대로 된 SQL 쿼리를 만들지, 잘못된 것처럼 보이지 않는 쿼리를 만들지를 결정한다. 예를 들면:

SQLAlchemy 세션 관리 — 흔한 실수
# 에이전트가 자주 만드는 잘못된 패턴
def get_user(user_id: int):
    db = SessionLocal()  # 세션을 닫지 않는다
    return db.query(User).filter(User.id == user_id).first()
 
# 올바른 패턴 — 컨텍스트 매니저로 세션 관리
def get_user(user_id: int, db: Session = Depends(get_db)):
    return db.query(User).filter(User.id == user_id).first()

기능 테스트만 보면 두 코드 모두 통과할 수 있다. 하지만 구조적 검증을 통과하는 건 두 번째 코드뿐이다. 에이전트는 기능 요구사항을 먼저 충족시키려 하고, ORM 사용 규칙을 세밀하게 지키는 것은 후순위로 밀린다.

[💡 잠깐! 이 용어는?] 그린필드(Greenfield): 기존 코드가 없는 상태에서 처음부터 시작하는 프로젝트. 반대는 레거시 코드베이스에 추가하는 브라운필드(Brownfield) 개발이다.


실무에서의 시사점

이 연구가 말하는 것은 "AI 코드 생성은 못 믿는다"가 아니다. 더 구체적인 메시지다.

에이전트가 잘하는 것:

  • 자유로운 명세의 빠른 프로토타이핑
  • 가볍고 명시적인 프레임워크(Flask 등)에서의 구현
  • 기능 요구사항이 중심인 코드 생성

에이전트가 약한 것:

  • 엄격한 아키텍처 패턴 준수
  • ORM과 데이터 계층의 세밀한 규칙 적용
  • 기능 요구사항과 구조 요구사항을 동시에 만족시키기

실무 팀에서 에이전트 코드를 리뷰할 때 우선순위를 어디에 둬야 하는지가 보인다. 로직이 맞는지보다 데이터 계층이 규칙대로 되어 있는지를 먼저 봐야 한다. ORM 세션 관리, 쿼리 구성 방식, 트랜잭션 처리 — 이 부분에서 에이전트가 가장 많이 틀린다.

또 하나의 시사점은 프레임워크 선택이다. AI 에이전트와 함께 일하는 팀이라면, 관례가 많은 프레임워크보다 명시적인 프레임워크가 에이전트 코드의 품질을 높이는 데 유리하다.


정리

  • Constraint Decay: 구조적 제약이 쌓일수록 LLM 에이전트 성능이 급락하는 현상
  • 높은 구성에서 완전 지정 과제로 가면 assertion pass rate 평균 30포인트 하락
  • Flask처럼 명시적인 프레임워크에서 성능이 높고, Django·FastAPI에서 낮다
  • 실패의 **45%**는 데이터 계층 — ORM 사용 실수와 잘못된 쿼리 구성
  • 에이전트 코드 리뷰 시 데이터 계층을 우선 점검할 것
  • 기능 요구사항과 구조 요구사항을 동시에 만족시키는 것은 아직 미해결 과제

참고: