LLM에게 코드 리뷰를 시켰더니 없는 함수를 지적하는 이유

LLM에게 코드 리뷰를

LLM에게 코드 리뷰를 맡겼는데, 왜 있지도 않은 함수를 썼다고 지적할까요? 답은 생각보다 단순합니다 — 리뷰를 하는 모델이 여러분의 실제 코드베이스가 아니라, 붙여넣은 몇 줄과 학습 당시 기억만 보고 판단하기 때문입니다. LLM에게 코드 리뷰를 시켰더니 없는 함수를 지적하는 현상은 모델 성능 문제라기보다 ‘컨텍스트 부족’ 문제에 가깝습니다.

이 글에서는 이 현상이 왜 생기는지, 그리고 프롬프트 구조를 어떻게 바꾸면 줄일 수 있는지를 실제로 동작하는 코드와 함께 정리해 보겠습니다.

코드 리뷰를 시켰더니 없는 함수를 지적한다면

diff만 붙여넣고 “이 코드 리뷰해줘”라고 요청하면, 모델은 그 변경 줄 바깥에 무엇이 있는지 전혀 모릅니다. 그런데도 apply_discount() 같은 함수가 어딘가 정의돼 있을 거라 가정하고 리뷰 문장을 만들어 냅니다.

이때 모델은 실제 코드베이스 대신, 학습 데이터에서 비슷한 이름의 함수가 어떻게 쓰였는지를 근거로 답을 채웁니다. 결과적으로 여러분의 파일에는 없는 함수를 “정의가 빠졌다”거나 “시그니처가 다르다”고 지적하는 일이 생깁니다.

왜 컨텍스트가 부족하면 없는 함수가 나올까요?

LLM은 답을 생성할 때 ‘모른다’는 상태를 잘 표현하지 못합니다. 확률적으로 가장 그럴듯한 다음 토큰을 이어 붙이는 구조라서, 정보가 없어도 문법적으로 자연스러운 문장을 끝까지 완성해 버립니다.

이런 현상을 흔히 환각이라고 부르는데, 코드 리뷰에서는 “이 함수는 정의돼 있지 않은 것 같다”거나 반대로 “이런 헬퍼 함수를 써야 한다”는 형태로 나타납니다. 모델이 참고할 수 있는 코드가 몇 줄뿐이면, 나머지는 학습 당시 봤던 비슷한 패턴으로 빈칸을 채우는 셈입니다.

모니터 화면의 코드를 검토하는 개발자

또 하나 중요한 조건은 컨텍스트 윈도우입니다. 모델마다 한 번에 읽을 수 있는 텍스트 양에 한계가 있고, 그 한계 안에 파일 전체나 관련 모듈까지 다 넣지 못하면 같은 문제가 반복됩니다.

프롬프트에 파일 전체와 관련 함수를 함께 넣어보세요

diff 한 줄만 보내는 대신, 그 파일에 실제로 정의된 함수 목록을 프롬프트에 같이 넣어주면 모델이 추측할 여지가 줄어듭니다. 아래는 이런 구조로 프롬프트를 만드는 실제 파이썬 코드입니다.

def build_review_prompt(file_path, diff, related_functions):
    context = "\n".join(related_functions)
    prompt = f"""다음은 수정된 코드의 diff입니다.

{diff}

이 파일에서 실제로 정의된 함수 목록입니다. 이 목록에 없는 함수를 호출한다고 지적하지 마세요.
{context}

위 정보를 참고해서 코드 리뷰를 해주세요."""
    return prompt

diff = "+ result = apply_discount(price, rate)"
related_functions = [
    "def apply_discount(price, rate): ...",
    "def calculate_tax(price): ...",
]

print(build_review_prompt("shop/pricing.py", diff, related_functions))

이 코드를 실행하면 아래와 같은 프롬프트가 만들어집니다.

다음은 수정된 코드의 diff입니다.

+ result = apply_discount(price, rate)

이 파일에서 실제로 정의된 함수 목록입니다. 이 목록에 없는 함수를 호출한다고 지적하지 마세요.
def apply_discount(price, rate): ...
def calculate_tax(price): ...

위 정보를 참고해서 코드 리뷰를 해주세요.

함수 목록을 명시적으로 넣어주는 것만으로도, “이 함수가 정의돼 있지 않다”는 식의 잘못된 지적은 눈에 띄게 줄어듭니다. OpenAI가 제공하는 함수 호출 기능을 활용하면 아예 모델이 스스로 코드베이스를 검색해서 함수 존재 여부를 확인한 뒤 답하게 만들 수도 있습니다.

정적 분석 도구를 함께 쓰면 줄어드는 오류, 줄어들지 않는 오류

컨텍스트를 늘리는 것만으로 모든 문제가 해결되지는 않습니다. 어떤 방식으로 리뷰를 요청하느냐에 따라 위험과 준비 비용이 달라집니다.

AI 챗봇과 코드 오류를 분석하는 화면

방식 LLM이 보는 정보 없는 함수 지적 위험 준비 비용
diff만 붙여넣기 변경된 줄뿐 높음 낮음
파일 전체 + diff 파일 내 전체 함수 중간 중간
관련 파일 + 함수 목록 모듈 간 의존관계까지 낮음 높음 (사전 정리 필요)
에이전트형 도구(코드베이스 검색) 필요할 때 직접 검색 가장 낮음 도구 설정 필요

Claude Code나 Cursor 같은 에이전트형 도구는 답변 전에 실제로 파일을 검색해서 함수 정의를 확인하는 방식으로 이 문제를 줄입니다. ESLint, Pylint 같은 정적 분석 도구로 “정의되지 않은 이름 사용”을 먼저 걸러낸 뒤, 그 결과를 LLM 리뷰와 함께 넘기는 방식도 실무에서 쓰이는 접근입니다.

다만 정적 분석은 언어와 프로젝트 설정에 따라 오탐이 나올 수 있고, LLM 리뷰는 문맥적인 설명(왜 이렇게 짜는 게 나은지)에 강한 대신 존재 여부 같은 사실 확인에는 약합니다. 두 도구를 같은 자리에 두고 비교하기보다, 서로 다른 역할로 나눠 쓰는 편이 현실적입니다.

컨텍스트를 충분히 줘도 오류가 남는 경우는 없을까요?

있습니다. 함수 목록을 프롬프트에 넣어도 모델이 그 지시를 무시하고 새로운 이름을 지어내는 경우가 여전히 발생합니다. 지시를 얼마나 잘 따르는지는 모델과 버전마다 다르기 때문에, 프롬프트 구조만으로 완전히 없앨 수 있는 문제는 아닙니다.

모노레포처럼 코드베이스가 크면 관련 함수 목록 자체를 정리하는 작업이 오래 걸리고, 컨텍스트를 늘릴수록 요청당 처리 시간과 비용도 함께 늘어납니다. 그래서 작은 PR에는 파일 전체를 붙여넣는 방식이 낫고, 큰 레포에는 검색 기반 에이전트 도구를 쓰는 편이 비용 대비 효율이 좋습니다.

다음 코드 리뷰 프롬프트에는 이 체크리스트를 넣어보세요

LLM에게 코드 리뷰를 시켰더니 없는 함수를 지적하는 문제는 모델이 게을러서가 아니라, 애초에 판단할 근거를 충분히 받지 못했기 때문에 생깁니다. diff 대신 파일 전체와 실제 함수 목록을 같이 넘기고, 가능하면 정적 분석 결과를 먼저 붙여주는 것만으로도 지적의 정확도가 눈에 띄게 달라집니다.

작은 PR이라면 오늘 소개한 build_review_prompt 형태로 함수 목록을 직접 넣어보시고, 레포가 크다면 코드베이스를 검색할 수 있는 에이전트형 도구로 바꿔보시는 것을 권해드립니다. 환각이라는 현상 자체를 없앨 수는 없지만, 모델이 볼 수 있는 정보를 넓혀줄수록 그 빈도는 확실히 줄어듭니다.

LLM에게 번역을 시켰더니 숫자와 단위가 틀릴 때 — 검증 후처리 설계

참고: LLM에게 코드 리뷰를 — 위키백과

Leave a Comment