프롬프트도 모듈화가 핵심! Decomposed Prompting으로 LLM 성능 극대화하기
LLM에게 복잡한 추론을 시키면 엉뚱한 답을 내놓아 답답할 때가 많습니다. 보통은 Chain-of-Thought(CoT)를 써서 “단계별로 생각하라”고 지시하지만, 이것도 입력이 길어지거나 논리가 깊어지면 길을 잃기 십상입니다.
소프트웨어 개발을 할 때, 수천 줄의 코드를 main() 함수 하나에 다 때려 넣지 않죠? 그런데 우리는 프롬프트 작성 시 이런 실수를 자주 범합니다.
오늘은 ICLR 2023에서 소개된 Decomposed Prompting (분해 프롬프팅)을 통해, 프롬프트를 ‘스파게티 코드’가 아닌 ‘잘 짜인 모듈’처럼 관리하는 방법을 소개합니다.
문제 정의: CoT는 왜 실패하는가?
우리는 LLM이 예시(Few-shot)와 과정(CoT)만 보여주면 알아서 배울 거라 기대합니다. 하지만 논문은 CoT가 가진 구조적 한계를 지적합니다.
- ❌ 기존 CoT: 복잡한 사고 과정과 문제 풀이를 하나의 긴 텍스트 덩어리로 처리합니다. 입력이 길어지면 모델의 집중력(Attention)이 분산되고, 중간에 하나만 틀려도 전체가 무너집니다. 디버깅도 불가능하죠.
- ⭕ Decomposed Prompting) 복잡한 문제를 쪼개서(Decompose), 각기 다른 전문 모듈(Handler)에게 위임합니다.
핵심 구조: 팀장과 팀원
이 기법은 프롬프트를 하나의 ‘거대 언어 모델’이 아니라, 역할이 분담된 ‘시스템’으로 바라봅니다.
- Decomposer (팀장): 직접 문제를 풀지 않습니다. 사용자의 질문을 분석해 “누가 이 일을 처리할지” 계획(Program)만 짭니다.
- Sub-task Handler (팀원): 팀장이 시킨 단순하고 구체적인 작업 하나만 처리합니다. LLM일 수도 있고, 계산기나 구글 검색 API 같은 외부 도구일 수도 있습니다.
💡 개발자 노트: 이것은 전형적인 모듈러 프로그래밍(Modular Programming)입니다. 특정 단계가 막히면 전체 프롬프트를 뜯어고칠 필요 없이, 해당 Handler만 수정하거나 더 똑똑한 모델로 갈아끼우면 됩니다.
작동 원리: 실전 예제
Case 1: 문자열 조작 (논리적 분해)
“Jack Ryan의 이름에서 각 단어 첫 글자를 따서 합쳐라”라는 미션이 있다고 칩시다.
- Decomposer: “일단 단어부터 분리해.” → [Split Handler] 호출
- Handler A: “Jack”, “Ryan” 반환
- Decomposer: “각 단어의 첫 글자만 뽑아.” → [Extraction Handler] 호출
- Handler B: “J”, “R” 반환
- Decomposer: “이걸 공백으로 합쳐.” → [Merge Handler] 호출
- 결과: “J R”
팀장은 논리적 흐름만 관장하고, 귀찮은 문자열 처리는 팀원에게 미룹니다.
Case 2: 리스트 뒤집기 (재귀의 마법)
이 논문의 백미는 재귀(Recursion)의 도입입니다. 아주 긴 리스트를 뒤집어야 할 때, CoT는 중간에 까먹습니다. 하지만 Decomposed Prompting은 리스트를 반으로 쪼개고, 각각 뒤집어서 합칩니다. 그래도 길면? 또 쪼갭니다.
이 방식을 쓰면 입력 길이가 아무리 길어져도 성능 저하가 거의 없습니다. 알고리즘의 효율성을 프롬프트로 구현한 셈입니다.
확장성: 모르는 건 검색엔진에게
LLM은 최신 정보나 정확한 계산에 취약합니다. 이때 Handler 자리에 LLM 대신 검색 엔진(Retrieval System)을 끼워 넣으면 환각(Hallucination)을 획기적으로 줄일 수 있습니다.
- 질문: “롤러코스터 Lost Gravity 제조사는 어느 나라 회사야?”
- Decomposer: (제조사를 먼저 찾아야겠군) → [검색 Handler] 호출
- Handler: “Mack Rides입니다.”
- Decomposer: (이제 나라를 찾자) “Mack Rides는 어느 나라 회사야?” → [검색 Handler] 호출
- Handler: “독일입니다.”
- 최종 답: 독일
‘다단계 질문’을 ‘단일 검색 질문’들로 쪼개서 처리하니 정확도가 올라갈 수밖에 없습니다.
요약 및 제언
Decomposed Prompting은 단순한 프롬프트 엔지니어링이 아니라 시스템 아키텍처에 가깝습니다.
- 모듈화: 복잡한 태스크는 무조건 관리 가능한 단위로 쪼개십시오.
- 재사용성: 잘 만든 프롬프트 조각(Handler)은 다른 프로젝트에서도 쓸 수 있습니다.
- 디버깅: 결과가 이상하면 전체를 의심하지 말고, 범인(특정 Handler)만 찾아 고치십시오.
혹시 지금 거대한 프롬프트 창 하나에 모든 지시사항을 쏟아붓고 계신가요? 이제 그 짐을 똑똑한 팀원들에게 나눠줄 때입니다.
