SCoT와 CoT의 차이를 시각적으로 비교하는 이미지. 왼쪽의 모호한 구름(CoT의 한계)과 오른쪽의 체계적인 다이어그램(SCoT)이 대비되며, SCoT가 LLM 코드 생성 정확도를 높이는 원리를 보여줍니다.
|

SCoT: CoT의 한계를 넘어선 LLM 코드 생성의 새로운 표준

SCoT: CoT의 한계를 넘어선 LLM 코드 생성의 새로운 표준

LLM에게 코드 짜라고 시켰더니, 왜 자꾸 엉뚱한 답을 내놓을까요?

ChatGPT 같은 거대 언어 모델(LLM)이 놀라울 정도로 복잡한 코드까지 척척 생성해 내는 시대입니다. 하지만 현업에서 LLM을 써 본 개발자라면 누구나 공감하는 골칫거리가 있죠. 바로 그럴싸해 보이지만 실제로는 작동하지 않는 논리적 오류입니다.

이 문제를 해결하기 위해 등장한 것이 ‘생각의 사슬(Chain-of-Thought, CoT)’ 기법입니다. LLM에게 “코드를 짜기 전에, 먼저 말로 어떻게 풀지 생각해 봐”라고 요청하는 방식이죠.

하지만 CoT에도 명확한 한계가 있었습니다. CoT는 원래 자연어 추론을 위해 설계된 방식이라, 코드처럼 논리 구조가 빡빡한 작업을 시키면 정확도가 기대만큼 오르지 않았습니다.

그래서 개발자들은 근본적인 질문을 던졌습니다.

“LLM이 코드를 생성해야 한다면, 생각 역시 코드처럼 구조화되어야 하지 않을까?”

이 질문에서 시작된 새로운 기법이 바로 SCoT(Structured Chain-of-Thought), 즉 ‘구조화된 생각의 사슬’입니다. 2023년 발표된 한 논문(https://arxiv.org/pdf/2305.06599)에 따르면, 이 SCoT 기법은 기존 CoT 대비 코드 생성 정확도를 최대 13.79%까지 끌어올렸습니다.

대체 SCoT가 무엇이고 기존 CoT와 어떻게 다르기에 이런 차이를 만드는지, 그 원리를 명쾌하게 파헤쳐 보겠습니다.

1. CoT의 한계: 왜 코드 생성에 부족했을까?

SCoT를 이해하려면 먼저 CoT가 왜 실패했는지 알아야 합니다. CoT는 LLM이 ‘자연어’로 추론 단계를 거치도록 유도합니다.

CoT 예시 (자연어 서술)

결과를 -999999로 초기화합니다.
리스트의 리스트를 반복합니다.
합계를 0으로 초기화합니다.
리스트를 반복합니다.
요소를 합계에 더합니다.
...

간단한 문제엔 도움이 되지만, 논리가 복잡해지면 치명적인 약점인 모호함(Ambiguity)이 드러납니다.

위 예시에서 2번 ‘반복’과 4번 ‘반복’이 서로 어떻게 연결되는 걸까요? 사람은 문맥상 ‘이중 반복문(Nested Loop)’이라고 이해하지만, LLM은 이 둘을 별개의 반복문으로 오해하거나 구조를 혼동해 잘못된 코드를 생성할 수 있습니다.

모든 코드는 본질적으로 순차(Sequence), 분기(Branch), 반복(Loop)이라는 3가지 기본 구조로 이루어집니다. 하지만 자연어로 풀어서 설명하는 CoT 방식은 이 중요한 구조 정보를 명시적으로 담아내지 못합니다.

2. SCoT(Structured CoT)란 무엇인가?

SCoT는 이 모호함을 정면으로 돌파합니다. LLM에게 자연어 서술이 아닌, 프로그램 구조(Program Structures)를 사용해 생각의 단계를 만들라고 요청합니다.

즉, LLM이 생각하는 과정 자체를 프로그래밍 언어의 관점에서 구조화하도록 강제하는 것입니다.

SCoT의 핵심 구성 요소

  1. 순차 구조 (Sequence): 1번 다음 2번을 순서대로 실행합니다.
  2. 분기 구조 (Branch): if…, if…else…처럼 특정 조건에 따라 다른 단계를 실행합니다.
  3. 반복 구조 (Loop): for…, while…처럼 특정 조건 동안 단계를 반복합니다.

또한 SCoT는 명확한 입출력 구조(Input-Output Structure)를 먼저 정의하게 함으로써, LLM이 문제의 요구사항과 변수의 타입을 명확히 인지하고 시작하도록 돕습니다.

3. CoT vs SCoT: 명확성의 차이

백문이 불여일견입니다. 앞서 봤던 모호한 CoT 예시를 SCoT로 변환하면 그 차이가 극명하게 드러납니다.

SCoT 예시 (구조적 서술)

Input: arry: list[list], K: int
Output: result: int or float
1: Initialize_a_result_with -999999 (Sequence)
2: for list in the list of lists: (Loop Structure)
3: Calculate the sum of the list
4: if the sum is great than result: (Branch Structure)
5: Update the result
6: Divide result by K (Sequence)
7: return result

차이가 보이시나요?

CoT에서는 모호했던 2번과 4번 단계가, SCoT에서는 for 루프(반복 구조)와 그 안에 중첩된 if문(분기 구조)으로 명확하게 표현됩니다.

SCoT는 “어떻게 문제를 풀지”에 대해 소스 코드의 관점에서 생각하도록 LLM을 제약함으로써, 모호함을 제거하고 최종 코드의 논리적 정확성을 극대화합니다. 복잡한 중첩 루프나 if-elif 구조도 명확하게 표현할 수 있죠.

4. SCoT 프롬프트, 실제 구현은? (2-Step 파이프라인)

SCoT 프롬프트는 CoT와 달리 2단계에 걸쳐 실행됩니다.

Step 1: SCoT (계획) 생성 프롬프트

먼저 LLM에게 문제(요구사항)를 줍니다. 그리고 이 문제를 풀기 위한 SCoT(구조화된 추론 과정)를 생성하라고 요청합니다.

[프롬프트 예시] “요구사항을 이해하고 해결 과정을 작성하세요. 이 과정은 입출력 구조로 시작해야 합니다. 순차, 분기, 루프의 세 가지 기본 구조를 사용하여 해결 과정을 구축하세요.”

이때 몇 가지 예시(Few-shot examples)를 함께 제공하여 SCoT가 어떤 형태여야 하는지 알려줍니다.

Step 2: 코드 생성 프롬프트

1단계에서 생성된 SCoT를 입력값으로 삼아, LLM에게 이 SCoT를 기반으로 실제 코드를 작성하라고 요청합니다.

[프롬프트 예시] “(1단계에서 생성된 SCoT…)” “# 위의 해결 과정을 확인하고 이를 기반으로 코드를 작성하세요. 참고: 해결 과정에 오류가 포함될 수 있습니다.”

여기서 흥미로운 점은 “해결 과정에 오류가 포함될 수 있습니다”라는 지시어입니다.

이는 SCoT가 ‘완벽한 청사진’이 아닌 소프트 템플릿(Soft Template) 역할을 하도록 유도합니다. 즉, LLM은 SCoT의 큰 구조적 논리는 따르되, 세부 사항은 스스로 비판적으로 검토하고(double-check) 코드를 구현하게 됩니다.

이 2단계 접근 방식은 LLM이 ‘다양한 해결책 탐색(1단계)’과 ‘구조화된 코드 구현(2단계)’이라는 두 가지 작업을 분리해서 집중하도록 만듭니다.

5. 그래서, SCoT는 정말 효과가 있는가? (데이터로 증명)

논문은 SCoT의 효과를 검증하기 위해 ChatGPT와 Codex 모델을 대상으로 3개의 주요 코드 생성 벤치마크(HumanEval, MBPP, MBCPP)에서 테스트를 진행했습니다.

측정 지표는 ‘Pass@1’입니다. Pass@1은 LLM이 생성한 첫 번째 코드가 모든 테스트 케이스를 통과할 확률을 의미합니다. 개발자에게는 ‘한 방에 성공할 확률’인 셈이죠.

결과는 압도적이었습니다.

  • HumanEval (Python): SCoT가 CoT 대비 Pass@1 성능 13.79% 향상
  • MBPP (Python): SCoT가 CoT 대비 Pass@1 성능 12.31% 향상
  • MBCPP (C++): SCoT가 CoT 대비 Pass@1 성능 6.63% 향상

Pass@1 지표에서 13% 이상의 향상은 코드 생성 분야에서 엄청난 성과입니다. 이는 SCoT가 LLM의 코드 생성 추론 능력을 확실하게 잠금 해제했음을 보여줍니다.

6. SCoT가 ‘가짜 코드(Pseudocode)’보다 나은 이유

SCoT를 보고 “이거 그냥 의사 코드(Pseudocode) 아닌가?”라고 생각할 수 있습니다. 실제로 둘은 매우 유사해 보입니다.

하지만 논문은 SCoT가 의사 코드보다 더 나은 중간 단계라고 주장합니다. 결정적인 차이는 추상화 수준에 있습니다.

  • 의사 코드: 너무 구체적입니다. (예: sum = 0; for i in list…처럼 구현 세부 사항까지 지시)
  • SCoT: 더 추상적입니다. (예: Calculate the sum of the list처럼 논리적 뼈대만 제시)

SCoT는 LLM에게 구현의 세세한 부분까지 지시하는 대신, 논리적 구조의 뼈대만을 제공합니다. 이를 통해 LLM은 뼈대를 따르면서도 유연하게 최적의 코드를 구현할 자유를 갖게 됩니다.

실제로 논문에서 SCoT 대신 의사 코드를 중간 단계로 사용했을 때, SCoT보다 모든 벤치마크에서 성능이 더 낮았습니다. SCoT의 ‘적절한 추상화 수준’이 코드 생성에 더 유리함이 증명된 것입니다.

결론: 코드 생성을 위한 LLM, 이제 ‘구조적’으로 생각하게 하라

SCoT(Structured Chain-of-Thought)는 코드 생성을 위한 LLM 프롬프트 엔지니어링의 중요한 진일보를 보여줍니다.

기존 CoT가 모호한 자연어 설명에 의존했다면, SCoT는 시퀀스, 분기, 반복이라는 프로그램의 핵심 구조를 LLM의 ‘생각 과정’에 직접 주입합니다.

그 결과는 HumanEval 벤치마크 기준 최대 13.79%의 정확도 향상으로 나타났습니다.

단순히 정답률만 높은 것이 아닙니다. SCoT로 생성된 코드는 인간 개발자가 수동으로 평가했을 때도 기존 방식보다 정확성(15.27%↑), 가독성(코드 스멜 10.66%↑), 유지보수성(15.90%↑) 모든 측면에서 더 높은 점수를 받았습니다.

이는 SCoT가 단순히 테스트 케이스만 통과하는 코드가 아니라, 더 읽기 쉽고, 더 깔끔하며, 유지보수하기 좋은 코드를 생성하도록 유도한다는 의미입니다.

만약 여러분이 LLM을 활용해 코드를 생성할 때, 부정확한 논리와 빈번한 오류로 골머리를 앓고 있다면, 이제 LLM에게 “자연어로 생각하라”고 말하는 대신, SCoT를 사용해 “코드처럼 구조적으로 생각하라”고 요청해 보시기 바랍니다.

Similar Posts