Disclamer: 이 문서는 사내용 세미나 진행을 위해, 사외에서 취득 가능한 정보만를 활용하여 사외에서 작성되었습니다.
◼︎ 왜 이 문서를 쓰게 되었나?
최근 새로운 모델의 도입으로 많은 부분이 개선되었지만, 사내에 배포된 LLM은 외부의 최신 모델에 비해 학습 데이터, 파라미터 수, 튜닝 수준이 부족할 수 있습니다. 이로 인해 답변이 모호하거나, 코드가 불완전하거나, 실제 업무 상황과 맞지 않은 경우가 있습니다. 이 문서에서는 사내 LLM의 "충분히 만족스럽지 않은 답변을 어떻게 극복할 것인가?"에 대한 이야기를 나누어 봅니다. 이후에 다루는 주제들에서 사내 LLM을 활용하여 실습을 진행하기 위해서는 이 부분에 대한 고민이 선행되어야 된다고 생각하여 첫 주제로 작성하게 되었습니다.
이후 부터 작성되는 프롬프트 전략에 대해서는 모든 상황에 맞는 정답 또는 표준이 없다고 생각합니다. 있더라도 그 유효기간이 매우 짧아 금방 구식이 되고 맙니다. 그러다보니 현시점의 개인적인 의견, 시각이 많이 포함되어 있습니다. 함께 토론하면서 더 나은 방법을 배워나가고 싶습니다. 의견이 있으시면, 편하게 댓글로 남겨주세요.
◼︎ 왜 사내 LLM의 답변 품질이 낮아질까?
너무 자명한 질문일 수 있지만, 이 질문에 대한 답변을 정리해보면 극복 방법에 대한 힌트를 얻을 수 있습니다.
- 학습 데이터의 한계: 오픈소스 모델은 외부의 데이터를 기반으로 학습되어 사내 도메인 특화 지식이 부족합니다.
- 컨텍스트 윈도우 제한: 파라미터 수, H/W 인프라의 제약으로 긴 코드나 요구사항을 넣으면 내용이 잘리거나, 무시될 수 있습니다.
- 추론 품질 저하: 최신 모델 대비 reasoning(test-time compute) 능력이 떨어져 "그럴듯한 오답"을 자주 출력합니다.
이 한계를 극복하는 근본적인 방법은 모델, 튜닝, H/W 인프라 확대 등이 있겠지만 우리는 질문하는 방식, 즉 프롬프팅(prompt)을 활용하여 LLM의 성능 한계를 극복하는 방법에 대해 알아봅니다.
◼︎ 실질적인 극복 전략
1. 질문을 단순화하고 단계를 쪼갠다.
사내 LLM은 긴 맥락을 추론하는 능력이 다소 부족합니다. 우리가 이 사실을 알고 있는데도 불구하고, 너무 많은 요구 사항을 한번에 요구 하는 것은 해결할 능력이 없는 것을 알고도 일을 던지는 것과 같습니다. 아래 예시를 함께 봅니다.
- 잘못된 질문 예시
"이 프로젝트 전체를 리팩토링 해줘. 가독성, parsing 성능, testable 구조, 잠재적 버그를 전체적으로 개선해줘."
이 질문은 한번에 너무 많은 항목을 요구 합니다. 사내 LLM은 문맥을 이해, 유지하지 못하거나 이 답변 저 답변을 오락가락 하는 산만한 답변을 출력하기 쉽습니다. 한번에 모든 항목을 요구하기 보다, 단계별로 나누어 task를 요구함으로써 LLM의 추론 부담을 낮추고, 결과물을 더 정확하게 할 수 있습니다.
- 개선된 질문 예시
1단계: "OO 파일의 가독성을 개선하기 위한 리팩토링 아이디어를 제시해줘."
2단계: "parsing 성능과 관련된 부분만 구체적인 코드 예시로 보여줘"
3단계: "운영 시점에 발생할 수 있는 잠재적 버그를 찾고, 해결 방법을 알려줘."
한 가지 짚고 넘어 갈 것은, 현재 사외에서 상용 서비스로 제공되는 최신 LLM, reasoning model은 한 번에 최대한 많은 context를 one-shot에 제공하는 것이 더 좋은 결과물을 출력한다고 알려져 있습니다. 우리가 상황에 따라 프롬프트 전략을 다르게 가져간다는 것을 인지하고 있어야 합니다.
참고자료: https://news.hada.io/topic?id=22450
2. 프롬프트를 구조화 한다.
모호한 질문 보다 역할(Role), 목표(Objective), 제약조건(Constraits), 출력형식(Output) 구조를 적용합니다. 같은 모델이라도 구조화된 프롬프트는 답변의 완성도를 크게 높입니다.
- 일반적인 질문
"테스트 코드를 작성해줘"
- 구조화된 질문
"너는 python 테스팅 전문가 역할을 맡아야 해"
목표: FastAPI 엔드포인트 /users에 대한 단위 테스트를 작성
제약조건: pytest 사용, DB는 mock으로 대체, 테스트 시나리오는 엔드포인트 성공, 실패 케이스를 모두 포함
사실 LLM에 페르소나를 부여하고, 구조화된 답변을 요청하는 방법은 GPT-3가 등장할 즈음 주목 받았던 초기 LLM 프롬프트 전략입니다. GPT-o 시리즈, reasoning model이 등장이후로는 사용자의 대화 기록(메모리)을 바탕으로 모델 스스로가 적합한 페르소나를 구축해 가도록 개선되어 이제는 잘 사용하지 않는(효과가 없다고 알려진) 방법입니다. 하지만 LLM 모델의 성능이 제한적일 때는 여전히 시도해볼만한 프롬프트 전략입니다.
참고자료: https://www.youtube.com/watch?v=eKuFqQKYRrA
3. 사고 체인에 개입하기
최신 reasoning model이 보여주는 사고 체인(chain-of-thought), 멀티 스텝 추론 성능을 기대하고 사내 모델을 접하게 되면, 다소 아쉬운 부분이 있는 것은 사실입니다. 사내 모델이 "한 번에 정답"을 내기 힘들다면, 사용자가 이 과정에 개입해서 "내가 먼저 정보를 제공 -> LLM은 가공"하는 방식을 사용하는 것이 효과 적입니다.
- 예시: 복잡한 사내 DB 스키마 관련 리팩토링 조언을 얻고 싶을 때
- 내가 먼저 스키마 다이어그램 요약을 제공 (혹은 다른 LLM 세션에서 정리 후 결과 복사)
- "이 스키마를 기준으로 유저 관련 API를 리팩토링할 때 예상되는 쿼리 성능 이슈를 알려줘"
이렇게 사용자가 1차 가공한 데이터를 기반으로 답변을 요청하면, 모델은 스스로 추론을 진행하지 않고, 사용자가 제공한 사실에 기반한 답변을 하게 됩니다. 또한, 원하는 데이터에 대한 예시를 몇가지 만들어서 LLM의 답변을 돕는 few-shot 프롬프팅 전략도 LLM의 사고 체인에 개입하여 답변의 품질을 향상시키는 방법으로 시도해볼 수 있습니다.
4. 반복적 피드백 루프
한 번의 답변으로 끝내려 하지 말고, 하나의 문제에 대해 반복적으로 피드백을 주고 다시 질문함으로써 답변 품질을 점진적으로 올리는 방법입니다. 편하게 표현하면 "만족스러울 때까지 다시 시킨다" 입니다.
- 예시
- 1차 피드백: "코드가 불완전하다면 어떤 부분이 누락된 것 같아?"라고 되묻기
- 2차 피드백: "테스트 코드가 통과하지 않을 수 있는 시나리오를 더 추가해줘"
- 3차 피드백: "지금 제시한 코드를 운영 환경에 맞게 수정해줘(Python 3.10, FastAPI 0.115)"
참고자료: https://minimaxir.com/2025/01/write-better-code/
5. 외부 자료 추가
사내 모델은 외부 RAG/MCP 연결을 통해 최신 자료를 참고하는 것이 매우 제한적입니다. (안됩니다.) 이럴 때는 사용자가 최신 정보를 1차 가공하여 LLM에게 전달할 수 있습니다.
- 예시
- 외부 최신 공식 문서 검색 -> 사내 LLM에 붙여넣기 -> 가공 요청 (file, context provider, indexing 활용)
- 질문: "OOO 문서는 FastAPI 0..15의 문서 중 response_model 관련 설명이다. 이 문서를 참고해서 기존 코드의 응답 타입 힌트를 개선해줘"
새로운 사실을 생성하는 부분은 약할 수 있지만, 사용자가 제공한 정보 가공은 충분히 잘 처리할 수 있습니다.
다음 문서에서는 간단한 실습을 통해 위 내용을 확인해보겠습니다.
'Vibe Coding' 카테고리의 다른 글
| [코드리뷰] 리뷰 해줄 사람이 없을 때, LLM 활용하기 (0) | 2025.09.10 |
|---|---|
| [리팩토링] LLM으로 테스트 불가능한 구조를 개선하기 (1) | 2025.09.10 |
| [리팩토링] LLM으로 운영 중인 코드, 안전하게 리팩토링하기 (0) | 2025.09.10 |
| [리팩토링] LLM을 사용하여 목적 기반으로 리팩토링 수행하기 (0) | 2025.09.07 |