GPT-4 및 Claude와 같은 자기회귀(Autoregressive) 거대 모델들은 코드를 토큰 단위로, 파일의 왼쪽에서 오른쪽으로 순차적으로 생성합니다. 짧은 코드 조각은 잘 처리하지만, 개발자가 대규모 코드베이스 깊숙이 있는 한 줄을 수정하려 할 때는 어려움을 겪습니다. 모델은 모든 후속 토큰을 다시 평가해야 하며, 파일 전체의 일관성을 유지하는 것은 매우 까다로운 작업이 됩니다.

확산(Diffusion) 모델은 무작위 토큰의 구름에서 시작하여 일관된 프로그램이 나타날 때까지 반복적으로 노이즈를 제거합니다. 정제 과정이 전체 시퀀스에 동시에 적용되기 때문에, 모델은 뒷부분을 다시 계산할 필요 없이 코드의 어떤 부분도 삽입, 삭제 또는 재작성할 수 있습니다.

현재의 패러다임이 소프트웨어 엔지니어링에서 어려움을 겪는 이유

자기회귀 방식은 모델이 코드를 선형적인 스트림으로 취급하도록 강제하며, 이는 다음과 같은 문제를 야기합니다.

  • 과거만 바라봄. 미래의 토큰을 볼 수 없으므로, 변경 사항이 이후의 줄에 어떤 영향을 미칠지 예측할 수 없습니다.
  • 후속 텍스트를 재계산함. 한 번의 수정이 새로운 예측의 연쇄 반응을 일으켜, 리팩토링이나 버그 수정 시 지연 시간(latency)을 증가시킵니다.
  • 장기적 오류의 누적. 초기의 불일치가 눈덩이처럼 불어나, 최종 파일의 구문이 깨지거나 논리적으로 일관되지 않게 됩니다.

파일 중간에 함수 본문을 삽입하거나 API 시그니처를 업데이트하는 등의 인필(infill) 작업이 필요할 때, 자기회귀 모델의 순차적 특성은 투박하고 오류가 발생하기 쉽습니다.

확산 모델이라는 대안: 단계별 예측이 아닌 반복적 정제

우리는 코드 파일을 노이즈가 섞인 신호로 취급합니다. 생성은 다음과 같은 여러 단계를 거쳐 진행됩니다.

  1. 순수 노이즈로 초기화. 모델에 무작위 토큰 시퀀스를 입력하며, 이는 종종 특수한 플레이스홀더로 표현됩니다.
  2. 점진적 디노이징. 각 단계에서 모델은 약간 더 깨끗한 버전을 예측하여 토큰을 그럴듯한 코드로 유도합니다.
  3. 완성된 프로그램으로 수렴. 정해진 단계 후에 노이즈가 사라지면 완전히 형성된 코드 조각이 남습니다.

각 단계에서 전체 시퀀스를 다시 검토하기 때문에, 모델은 어떤 단계에서든 어떤 토큰이든 수정할 수 있습니다. 이러한 전역적 관점(global view) 덕분에 모델은 뒤따르는 모든 내용을 다시 생성하지 않고도 누락된 import를 추가하거나, 변수 이름을 바꾸거나, 블록의 들여쓰기를 조정할 수 있습니다.

코드 중심의 확산 모델 설계하기

이미지에서 텍스트로 확산 모델을 이식하는 것은 단순히 바로 적용할 수 있는 작업이 아닙니다. 세 가지 기술적 변화가 중요합니다.

1. 이산 확산 (Discrete diffusion)

이미지 픽셀은 소수점 단위의 노이즈를 수용할 수 있지만, 코드 토큰은 범주형(categorical)입니다. 즉, 특정 키워드, 식별자 또는 기호 중 하나여야 합니다. 따라서 우리는 시퀀스가 사실상 무작위가 될 때까지 토큰을 중립적인 플레이스홀더(종종 [MASK])로 반복해서 교체하는 마르코프 체인(Markov chain)을 사용합니다. 역과정(reverse process)은 단계별로 원래의 토큰을 복구하는 방법을 학습합니다.

2. 구조적 인식 (Structural awareness)

프로그래밍 언어는 엄격한 구문 규칙을 적용합니다. Python에서는 들여쓰기가 범위를 정의하고, C 스타일 언어에서는 중괄호가 블록을 구분하며, 변수는 사용하기 전에 선언되어야 합니다. 코드를 단순 텍스트로 취급하는 확산 모델은 구문적으로 유효하지 않은 출력을 내놓을 것입니다. 이를 방지하기 위해 연구자들은 토큰 간의 어텐션(attention) 방식을 제한하는 구문 인식 어텐션 마스크(syntax-aware attention masks)를 추가하여, 모델이 계층 구조, 중첩 및 언어별 제약 조건을 준수하도록 강제합니다.

3. 계층적 정제 (Hierarchical refinement)

초기 확산 단계에서는 함수 시그니처, 클래스 정의, 모듈 구성과 같은 대략적인 구조를 스케치합니다. 이후 단계에서는 구두점, 공백, 명명 규칙과 같은 세부 사항을 다듬습니다. 이러한 coarse-to-fine 전략은 인간이 내부를 다듬기 전에 프로그램의 개요를 작성하는 방식과 유사하며, 각 단계에서 가장 중요한 부분에 계산 자원을 집중할 수 있게 합니다.

자기회귀 vs. 확산: 비교 분석

측면 자기회귀 확산
생성 흐름 순차적, 왼쪽에서 오른쪽으로 병렬적, 반복적 디노이징
전역적 일관성 긴 실행 시 드리프트(drift) 발생 가능성 높음 모든 토큰에 대한 통합적 관점
주요 사용 사례 채팅, 설명, 빠른 코드 조각 생성 리팩토링, 버그 수정, 대규모 코드 합성

표는 각 패러다임이 왜 서로 다른 맥락에서 빛을 발하는지 보여줍니다. 속도와 대화형 상호작용이 중요한 경우에는 자기회귀 모델이 유리합니다. 반면, 추가적인 계산 자원을 소모하더라도 최종 결과물이 구문적으로 정확하고 구조적으로 일관되어야 하는 경우에는 확산 모델이 유리합니다.

다음에 주목할 것

  • 하이브리드 파이프라인. 미래의 시스템은 자기회귀 모델이 빠른 초안을 작성한 뒤, 이를 확산 모델에 전달하여 정교하게 다듬는 방식을 채택할 수 있습니다.
  • 구조적 마스크를 위한 툴링. 연구자들은 확산 모델이 언어별 제약 조건을 준수할 수 있도록 구문 인식 어텐션 마스크(syntax-aware attention masks)를 지속적으로 개선하고 있습니다.

핵심 요약

확산 모델은 코드 생성의 패러다임을 뒤집습니다. 토큰을 하나씩 순차적으로 생성하는 대신, 반복적인 디노이징(denoising)을 통해 프로그램 전체를 조각해 나갑니다. 이러한 접근 방식은 대규모의 가변적인 코드베이스에서 전역적 일관성을 유지해야 하는 자기회귀 시스템의 핵심 약점을 공략합니다. 속도는 더 느리고 연산 비용은 더 많이 들지만, 확산 모델은 리팩토링, 버그 수정, 그리고 단순한 속도보다 깨끗하고 구문적으로 정확한 출력이 더 중요한 모든 시나리오에서 매력적인 도구가 됩니다. 가장 유망한 미래 경로는 자기회귀 모델의 빠른 초안 작성 능력과 확산 모델의 전체적인 정교화 능력을 결합한 하이브리드 워크플로우가 될 것으로 보입니다.