AI 코딩 일반

AI가 엉뚱한 곳을 고친다면? 방향 주는 지시법 (삽질 부검 2편)

DevPilot 2026. 9. 19. 18:31

삽질 부검 1편의 첫 실패는 성능을 개선해 달라는 지시에서 시작했습니다. 어디가 느린지 확인하기 전에 수정부터 맡겼죠. 이어서 없는 함수를 가져다 쓴 일, 예외를 숨긴 채 수정을 끝낸 일도 다뤘고요.

이번 편의 답: 원인을 모르면 조사부터 맡기고, 새 작업에는 현재 사실을, 수정할 때는 완료 조건을 알려주세요. 1편의 세 실패에 대응하는 요청문과 직접 실행할 예제를 담았습니다.

작업 명세의 기본 항목은 이전 글에서 정리했습니다. 이번에는 일이 이미 꼬이기 시작한 순간에 어떤 말을 덧붙일지 다뤄볼게요. 지시문에 중간 정류장을 두는 셈입니다. 원인도 모른 채 수정 완료까지 곧장 달리지 않도록요.

원인을 모르면 첫 요청은 조사에서 끝낸다

느리다는 증상만 보고 “캐시를 넣어줘”라고 하면 해결 방법을 먼저 골라준 꼴입니다. 요청을 너무 자주 보내는 문제인지, 서버가 늦게 응답하는지, 응답 뒤 화면을 그리는 데 시간이 걸리는지 아직 모르는데요.

이럴 때 첫 요청의 산출물은 원인 후보와 근거로 잡습니다. 어디를 고칠지는 그다음에 정하면 돼요. 아래 대괄호 부분에 실제 화면과 재현 순서를 채워 넣으세요.

[화면 또는 기능]에서 [구체적인 동작]을 하면 느려져.
재현 순서: [같은 현상을 다시 볼 수 있는 순서]
기대한 동작: [정상이라면 어떻게 보여야 하는지]

지금은 코드를 수정하지 말고 원인부터 조사해줘.
- 요청 횟수, 응답 시간, 화면 갱신 중 어디를 확인했는지 알려줘.
- 원인 후보마다 근거가 되는 코드나 측정 결과를 붙여줘.
- 확인된 사실과 아직 추측인 내용을 나눠줘.
- 측정할 수 없다면 필요한 화면이나 로그를 구체적으로 알려줘.

수정할 위치와 그 이유를 제안하는 데서 이번 작업을 끝내줘.

웹 화면이라면 브라우저의 Network 탭이 출발점이 될 수 있습니다. Chrome 개발자 도구의 공식 안내에는 요청을 발생시킨 위치를 보는 Initiator와 요청 시간의 세부 내역을 보는 Timing이 설명돼 있어요.

다만 같은 요청이 여러 번 보인다고 모두 불필요한 중복은 아닙니다. 재시도나 의도된 갱신인지도 확인해야 합니다.

▲ 처음부터 끝까지 한 번에 맡기기 어려운 작업이라면, 다음 단계로 넘어갈 조건을 먼저 정해둡니다.

조사에서 중복 호출이 원인으로 확인됐다면 “서버는 그대로 두고, 그 호출 지점만 수정해줘”라고 범위를 좁힐 수 있습니다. 처음부터 이 답을 정해놓고 조사시키면 진단이 또 한쪽으로 기울 수 있어요.

새 대화에는 이전 대화 전체보다 현재 사실을 넘긴다

1편의 두 번째 사례에서는 앞서 언급됐던 함수가 실제 코드에도 있는 것처럼 취급됐습니다. 새 작업에 필요한 것은 그 함수를 이야기했던 기억보다, 지금 저장소에 어떤 함수가 있는지예요.

그래서 새 대화를 시작할 때는 현재 목표, 확인한 위치, 남은 의문을 짧게 넘겨주는 편이 좋습니다. “아까 하던 거 이어서 해줘” 대신 다음 정도면 출발점을 알 수 있어요.

이번 작업의 목표: [고칠 동작 한 가지]
관련 위치: [확인한 파일·함수, 모르면 모른다고 적기]
확인한 사실: [재현 조건과 실제 결과]
아직 모르는 것: [추가 확인이 필요한 부분]
유지할 동작: [바꾸면 안 되는 입력·출력·화면 동작]

먼저 현재 파일을 읽고 관련 함수가 실제로 있는지 확인해줘.
이전 대화의 추측을 구현된 기능으로 가정하지 마.
수정 범위를 넓혀야 한다면 이유를 먼저 설명해줘.

새 대화로 넘어가도 파일에 남긴 수정은 없어지지 않습니다. 어떤 변경이 이미 들어가 있는지도 함께 알려줘야 해요. 인계 문서는 현재 코드로 다시 확인할 출발점입니다.

Claude Code의 공식 문서는 관련 없는 작업 사이에 /clear로 대화를 정리하는 방법을 안내합니다. 진행 중인 작업은 결정 사항과 남은 일을 먼저 기록하세요.

▲ 다음 작업을 시작할 사람도 현재 상태를 이해할 수 있을 정도로만 남겨보세요.

테스트 통과를 맡기기 전에, 무엇이 통과인지 정한다

“오류만 안 나게 해줘”에는 빠진 결정이 있습니다. 계산할 수 없는 입력이 들어왔을 때 0을 보여줘도 되는지, 입력을 거절해야 하는지예요. 예외를 잡아서 숫자 0을 반환하면 화면은 멀쩡해 보일 수 있습니다.

여기서는 1편의 예외 처리 문제를 별도의 Python 예제로 줄여보겠습니다. 실제 서비스 코드를 가져온 것은 아닙니다. 기준값과 현재값으로 감소율을 계산하되, 기준값이 0 이하이면 ValueError로 거절한다는 조건을 정했어요.

입력기대한 결과
기준값 100, 현재값 8020.0%
기준값 100, 현재값 1000.0%
기준값 0, 현재값 80ValueError로 거절

이 조건을 요청문에 넣으면, 에이전트가 결과를 맞춰야 할 기준이 생깁니다. 아래 입력 처리 방식은 이 예제에서 정한 것입니다. 실제 서비스에서는 오류 응답이나 화면 안내 등 기존 규칙에 맞게 바꾸세요.

감소율 함수가 기준값 0을 정상적인 0%로 돌려주고 있어.
기준값이 0 이하이면 ValueError로 거절하도록 수정해줘.

완료 조건:
- (100, 80)은 20.0, (100, 100)은 0.0을 반환한다.
- (0, 80)은 ValueError를 발생시킨다.
- 예외를 잡아 0을 반환하는 방식으로 통과시키지 않는다.

0 기준값 테스트가 수정 전에는 실패하는지 먼저 확인해줘.
수정 후 같은 테스트와 정상 입력 테스트를 실행해줘.
완료 보고에는 실행한 명령, 결과, 확인하지 못한 부분을 적어줘.

2026년 9월 19일, 아래 예제를 Python 3.11.6으로 로컬에서 실행했습니다. 오류를 0으로 바꿔버리는 함수도 정상 입력만 보면 2개 모두 통과했습니다.

0 기준값까지 검사하자 3개 중 2개만 통과했고, 입력을 검사하도록 바꾼 함수는 3개를 통과했습니다.

$ python3 direction_check.py
before | normal inputs: 2/2
before | including zero baseline: 2/3
after  | normal inputs: 2/2
after  | including zero baseline: 3/3

같은 잘못된 함수인데 검사할 입력을 추가하자 결과가 달라졌습니다. 통과 개수만 받아서는 놓치기 쉬운 부분이에요. 여러분이 받은 “테스트 통과”에는 처음 문제가 났던 조건도 들어 있었나요?

직접 실행할 예제 코드 보기

아래 내용을 direction_check.py로 저장한 뒤 Python 3으로 실행하면 됩니다. 외부 패키지는 필요 없습니다.

def before(original, current):
    try:
        return round((original - current) / original * 100, 1)
    except ZeroDivisionError:
        return 0.0


def after(original, current):
    if original <= 0:
        raise ValueError("original must be positive")
    return round((original - current) / original * 100, 1)


def check(fn):
    normal = sum((fn(100, 80) == 20.0, fn(100, 100) == 0.0))
    try:
        fn(0, 80)
    except ValueError:
        rejects_zero = 1
    else:
        rejects_zero = 0
    return normal, normal + rejects_zero


if __name__ == "__main__":
    before_normal, before_all = check(before)
    after_normal, after_all = check(after)
    print(f"before | normal inputs: {before_normal}/2")
    print(f"before | including zero baseline: {before_all}/3")
    print(f"after  | normal inputs: {after_normal}/2")
    print(f"after  | including zero baseline: {after_all}/3")
    assert (before_normal, before_all, after_normal, after_all) == (2, 2, 2, 3)

이 숫자는 예제 코드의 검증 결과입니다. AI 도구의 수정 성공률이나 성능 비교 결과는 아닙니다. 실제 프로젝트에는 자료형·입력 범위·호출부 동작 등의 검증이 더 필요해요.

지시를 길게 쓰지 않아도 되는 작업도 있다

버튼 문구 한 줄을 바꾸는데 조사 보고서부터 받을 필요는 없겠죠. 바꿀 위치와 결과가 분명하면 바로 수정하고 해당 화면을 확인하면 됩니다. 반대로 원인을 모르거나 수정 범위가 커질 수 있을 때는 중간 확인이 필요합니다.

Anthropic의 작업 계획 안내도 작은 수정에서는 계획 단계가 추가 부담이 될 수 있다고 설명합니다. 이번 요청문을 모든 작업에 통째로 붙이기보다, 지금 빠져 있는 조건을 골라 쓰세요.

원인을 모르면 조사 범위를, 작업을 넘길 때는 현재 사실을, 수정을 맡길 때는 완료 조건을 적는다.

자주 묻는 질문

Q. 관련 파일을 모르면 지시문을 어떻게 쓰나요?

A. 파일명을 추측해서 적지 말고 화면, 재현 순서, 실제 결과를 알려주세요. 관련 코드 위치를 찾는 일을 첫 작업으로 맡기면 됩니다.

Q. 지시문에 수정 금지라고 쓰면 파일 변경을 확실히 막을 수 있나요?

A. 자연어 지시만으로 변경을 차단한다고 보장할 수는 없습니다. 읽기 전용 조사에 맞는 모드와 권한 설정을 사용하고, 결과를 받은 뒤 실제 변경 내역도 확인하세요.

Q. 에이전트가 테스트를 실행할 수 없다고 하면요?

A. 실행하지 못한 이유와 필요한 환경, 실행할 명령을 따로 받으세요. 코드 수정은 끝났더라도 해당 검증은 미완료로 남겨두고, 실행 가능한 환경에서 확인해야 합니다.

다음 요청에 붙일 한 문장

어디를 고쳐야 할지 모를 때는 “지금은 수정하지 말고, 원인 후보와 근거를 먼저 알려줘”부터 붙여보세요. 수정할 위치를 정했다면 정상 결과와 실패 조건을 함께 넘기고요.

이번 편에서 남기고 싶은 기준은 에이전트가 다음에 무엇을 해야 할지 알 수 있는 지시입니다. 길이를 채우는 것보다, 지금 작업에 빠진 조건 하나를 적는 데서 시작하면 좋겠습니다.

함께 보면 좋은 글

삽질 부검 1편: AI 에이전트한테 시켰다가 날린 시간들
AI에게 좋은 작업 명세 쓰는 법
작업 유형별로 골라 쓰는 Devin 지시문 템플릿

참고 자료

Claude Code 공식 문서: 검증 기준, 작업 계획, 컨텍스트 관리
Chrome DevTools 공식 문서: 네트워크 요청 확인

공식 문서 확인 및 예제 실행: 2026년 9월 19일.