LLM 을 활용하여 코드의 리뷰 및 수정을 반복 하려다 보면 다음과 같은 현상이 흔합니다.

오류 수정 → 관련 코드를 LLM이 재구성 → 중복/불필요하다고 판단한 코드 삭제 → 기존 기능 일부 소실 → 새로운 오류 발생 → 다시 수정 → 기능이 조금씩 변질

따라서 단순히 “오류를 수정해 줘”라는 Prompt를 잘 만드는 것 만으로는 부족하고, 다음의 작업 프로세스로 만들어야 합니다.

  1. 변경 범위 제한
  2. 기능 보존 규칙
  3. 변경 전후 검증
  4. Diff 검토
  5. 테스트/회귀 방지


가장 중요한 원칙

“기존 코드를 보존하면서 특정 오류만 최소 범위로 수정하라” 라고 작업을 정의하는 것입니다.

현재 코드의 기존 기능과 동작을 최대한 유지한다.
이번 작업의 목적은 아래 오류를 수정하는 것이다.
오류 수정에 직접 필요한 코드만 변경한다.
오류와 직접 관련 없는 코드는 수정하지 않는다.
기존 기능을 삭제하거나 단순화하지 않는다.

LLM에게 코드를 수정시킬 때에는 다음의 7개 항목을 명시하는 것을 추천합니다.

항목 목적
① 작업 목적 무엇을 고치는지 명확히 함
② 변경 범위 어디까지 수정할 수 있는지 제한
③ 보존 대상 절대 없어지면 안 되는 기능 지정
④ 금지사항 리팩토링/삭제/구조변경 방지
⑤ 변경 최소화 최소 Diff 유도
⑥ 검증 방법 수정 후 무엇을 검사할지 지정
⑦ 결과 보고 변경 내용을 LLM이 스스로 보고하게 함

특히 ③ 보존 대상 + ④ 금지사항 + ⑥ 검증이 중요합니다.



추천하는 LLM 개발코드 오류 수정 전용 작업 규칙

실제 개발환경에서 재사용할 수 있도록 작성하면 다음과 같은 형태가 좋습니다.

## 1. 작업 목적

현재 프로젝트의 기존 기능과 동작을 최대한 보존하면서, 사용자가 지정한 오류 또는 문제만 수정한다. 이번 작업의 최우선 목표는 다음과 같다.

1. 지정된 오류를 정확하게 수정한다.
2. 기존 정상 기능을 유지한다.
3. 변경 범위를 최소화한다.
4. 오류와 직접적인 관련이 없는 코드는 변경하지 않는다.
5. 기존 코드의 구조와 설계를 임의로 개선하거나 재작성하지 않는다.

## 2. 가장 중요한 원칙

**기존 코드를 새롭게 작성하는 것이 아니라, 기존 코드에 필요한 최소한의 수정(Patch)을 적용한다.** 기존 코드에 문제가 없는 경우 그대로 유지한다. 오류를 수정하는 과정에서 더 좋은 구조라고 판단되는 코드가 있더라도, 이번 작업의 오류 수정에 직접 필요한 경우가 아니라면 변경하지 않는다.

## 3. 절대 변경하면 안 되는 것

다음 항목은 오류 수정에 직접적인 영향을 주지 않는 한
절대로 삭제, 변경 또는 단순화하지 않는다.

* 기존 주요 기능
* 기존 사용자 동작
* 기존 화면/UI 구조
* 기존 데이터 처리 방식
* 기존 API 인터페이스
* 기존 함수 및 클래스의 외부 인터페이스
* 기존 파일 구조
* 기존 설정값
* 기존 데이터베이스 구조
* 기존 이벤트 처리
* 기존 예외 처리
* 기존 권한/인증 처리
* 기존 로그 및 모니터링 기능
* 기존 테스트 코드
* 기존 호환성 처리
* 기존에 의도적으로 존재하는 예외적인 코드

코드가 현재 사용되지 않는 것처럼 보이거나 중복되어 보인다는 이유만으로 삭제하지 않는다.

## 4. 금지사항

이번 작업에서는 다음 작업을 임의로 수행하지 않는다.

* 전체 코드 재작성
* 대규모 리팩토링
* 함수 통합
* 클래스 구조 변경
* 파일 이동
* 파일 삭제
* 변수/함수 이름의 대규모 변경
* 사용하지 않는 코드라고 판단하여 삭제
* 중복 코드 제거
* 새로운 라이브러리 도입
* 프레임워크 변경
* 기존 API 변경
* 기존 데이터 구조 변경
* 기존 기능의 동작 방식 변경
* 성능 개선을 위한 구조 변경
* 코드 스타일 전체 변경

위 작업이 오류 해결에 반드시 필요한 경우에는
먼저 해당 필요성을 설명하고 변경 범위를 명시한다.

## 5. 수정 범위 원칙

오류와 직접 관련된 코드만 수정한다. 가능하면 다음 순서로 접근한다.

1. 오류 발생 위치 확인
2. 오류의 직접적인 원인 확인
3. 원인과 연결된 최소 범위 확인
4. 최소한의 코드 수정
5. 기존 기능의 영향 여부 확인
6. 수정 결과 검증

수정 범위가 확대될 경우,
왜 추가적인 변경이 필요한지 설명한다.

## 6. 기존 기능 보존

코드를 수정하기 전에 기존 코드에서 다음을 식별한다.

### 기존에 존재하는 주요 기능

* 기능 A:
* 기능 B:
* 기능 C:
* 기능 D:

### 반드시 유지해야 하는 동작

* 동작 A
* 동작 B
* 동작 C

위 기능과 동작은 오류 수정 이후에도 동일하게 유지되어야 한다.

---

## 7. 변경 전 분석
바로 코드를 수정하지 않는다. 먼저 다음을 분석한다.

1. 현재 오류가 무엇인지
2. 오류가 발생하는 위치
3. 오류가 발생하는 직접적인 원인
4. 관련된 함수/클래스/파일
5. 수정으로 영향을 받을 가능성이 있는 기존 기능
6. 수정하지 않아도 되는 코드

분석 결과를 먼저 간략하게 제시한 후 수정한다.

## 8. 변경 최소화 원칙

가능한 경우 기존 코드를 유지하면서
다음과 같은 최소 수정 방식을 우선한다.

* 조건문 수정
* 잘못된 변수 처리 수정
* 예외 처리 보완
* 누락된 검증 추가
* 잘못된 API 호출 수정
* 타입 오류 수정
* 경계조건 수정

전체 구조를 변경하는 방법은 최소 수정으로 해결할 수 없는 경우에만 사용한다.

## 9. 수정 후 검증
수정이 완료되면 반드시 다음을 확인한다.

### 오류 수정 여부
* 원래 오류가 해결되었는가?

### 기존 기능 보존 여부
* 기존 주요 기능이 삭제되지 않았는가?
* 기존 동작이 변경되지 않았는가?
* 기존 API/interface가 변경되지 않았는가?
* 기존 데이터 처리 방식이 변경되지 않았는가?

### 변경 범위
* 오류와 직접 관련 없는 코드가 변경되지 않았는가?
* 불필요한 리팩토링이 포함되지 않았는가?
* 불필요한 코드 삭제가 발생하지 않았는가?

### 회귀 가능성
* 기존 기능에 새로운 오류가 발생할 가능성이 있는가?
* 수정한 코드가 다른 기능에 영향을 주는가?


## 10. 결과 보고
수정 후 다음 형식으로 결과를 보고한다.

### 수정한 오류
* 어떤 오류를 수정했는지

### 원인
* 오류의 근본 원인

### 변경한 파일
* 파일명

### 변경한 코드
* 변경된 함수/클래스/영역

### 변경 이유
* 왜 해당 부분을 변경했는지

### 기존 기능 보존 확인
* 유지된 주요 기능
* 영향을 받지 않은 기능

### 테스트 및 검증
* 수행한 테스트
* 확인한 결과

### 추가 변경이 필요한 사항
* 있으면 명시
* 없으면 "없음"

## 11. 매우 중요한 규칙
**오류를 수정하는 것보다 기존 정상 기능을 보존하는 것을 우선한다.**

오류를 수정하기 위해 기존 기능의 변경이 불가피한 경우에는
임의로 변경하지 말고,

1. 변경이 필요한 이유
2. 영향을 받는 기능
3. 변경으로 발생할 수 있는 위험
4. 대체 가능한 최소 수정 방법

을 먼저 설명한다.

확신할 수 없는 기존 코드의 의미를 임의로 추측하여 삭제하거나 변경하지 않는다.

**기존 코드의 의도를 모르는 경우에는 보존하는 방향을 선택한다.**

이 정도의 Prompt를 **기본 시스템 규칙 / 프로젝트 개발 규칙**으로 두는 것을 추천합니다.


Prompt 하나만으로는 부족합니다

여기서 아주 중요한 부분이 있습니다. LLM에게 “기능을 삭제하지 마”라고 10번 써도 완벽하게 방지되지는 않습니다. 왜냐하면 LLM은 현재 코드만 보고 다음과 같이 판단할 수 있기 때문입니다.

  • “이 함수는 호출되지 않는 것 같은데?”
  • “이 코드는 중복으로 보이는데?”
  • “이 로직은 불필요한 것 같은데?”
  • “더 좋은 방법이 있으니 구조를 변경하는 것이 좋겠다.”

따라서 Prompt + 개발 프로세스로 막는 것이 좋습니다.

1. 특히 추천하는 방법: “수정”과 “리팩토링”을 완전히 분리

이게 상당히 중요합니다. LLM 작업을 다음처럼 분리하세요.

### 작업 A — Bug Fix

오류 수정만 한다.
기존 기능을 보존한다.
최소 변경한다.

### 작업 B — Refactoring

구조를 개선한다.
중복을 제거한다.
코드를 정리한다.

### 작업 C — Feature Development

새로운 기능을 추가한다.

세가지 작업을 한 Prompt에서 동시에 시키지 않는 것이 좋습니다. 특히 오류를 수정하고 코드도 전체적으로 개선해줘. 같은 요청은 위험합니다. LLM 입장에서는 Bug Fix + Refactoring + Optimization 작업으로 해석됩니다.

2. Git을 적극적으로 활용하세요

LLM을 이용한 코드 수정에서는 Git Diff가 사실상 필수적인 안전장치라고 생각하시면 됩니다.

# 수정 전/후를 비교해서 다음을 봅니다.
$ git diff

+ 수정된 코드
- 삭제된 코드

특히 위험한 것은:

- 기존 함수
- 기존 조건
- 기존 예외처리
- 기존 API 호출
- 기존 이벤트 처리

같은 삭제입니다. 따라서 LLM에게도 다음과 같이 요구하는 것은 이것도 상당히 효과적입니다.

수정 후 전체 파일을 다시 작성하지 말고, 변경된 부분만 Patch/Diff 형태로 제시하라.”


3. 더 강력한 방법: “변경 예산(Change Budget)”

LLM에게 수정 가능한 범위를 숫자/파일 단위로 제한하는 방법을 가장 추천합니다. 이렇게 하면 LLM이 갑자기 프로젝트 전체를 재작성하는 것을 상당히 줄일 수 있습니다.

이번 작업의 변경 범위는 **최대 2개 파일**이다.

기존 함수의 인터페이스는 변경하지 않는다.

새로운 파일을 생성하지 않는다.

기존 함수를 삭제하지 않는다.

오류와 직접 관련된 함수 외에는 변경하지 않는다.

대규모 변경이 필요하다고 판단되면 코드를 수정하지 말고
먼저 변경 필요성을 보고한다.

4. 더 좋은 방법: “보존 목록”을 별도로 만든다

프로젝트가 어느 정도 규모가 있는 경우에 이 방법을 강력하게 추천합니다. 예를 들어 프로젝트에 다음 문서를 하나 만들어 놓습니다.

docs/PROJECT_INVARIANTS.md

간단한 예시 내용을 살펴보면 다음과 같습니다.

# Project Invariants

## 반드시 유지해야 하는 기능

1. 사용자 로그인
2. 데이터 저장
3. 데이터 조회
4. CSV Export
5. 실시간 이벤트 처리
6. 권한 검사

## 변경하면 안 되는 Interface

- login()
- getUser()
- saveData()
- exportCSV()

## 변경하면 안 되는 데이터

- users
- projects
- settings

## 주의가 필요한 영역

- authentication/
- database/
- event/

그리고 LLM에게 다음과 같이 문서내용을 참고하라고 지정하는 방식을 사용합니다. 이것은 단순 Prompt보다 훨씬 강력합니다.

PROJECT_INVARIANTS.md를 먼저 읽어서 프로젝트 내용을 이해 합니다.

해당 문서에 정의된 기능과 인터페이스 및 기능들은 오류 수정 과정에서 변경하지 않는다.

변경이 반드시 필요한 경우 먼저 보고한다.

5. “LLM에게 코드를 수정시키기 전에 먼저 분석하게 하는 것”도 중요

바로 코드를 수정시키지 마세요. 다음과 같이 2단계 작업을 추천합니다.

  1. 코드를 수정하지 말고 분석작업을 진행하고, 결과 내용을 사람이 확인합니다.
코드를 수정하지 말고 분석만 하라.

- 오류 원인
- 관련 파일
- 관련 함수
- 영향받는 기능
- 수정 방법
- 예상되는 변경 범위

를 설명하라.
  1. 위 분석을 기준으로 최소한의 코드만 수정
    위 분석을 기준으로 최소한의 코드만 수정하라.
    

    이렇게 단계적으로 접근하면 LLM이 갑자기 프로젝트 구조를 재해석해서 대규모 변경하는 것을 줄일 수 있습니다.

6. 그리고 “Self Review Prompt”를 별도로 두세요

코드 수정이 끝난 뒤 LLM에게 자기가 만든 변경을 다시 공격적으로 검토하도록 하는 것입니다.

# LLM 코드 수정 후 회귀검증 Prompt

방금 수정한 코드를 대상으로
"오류가 해결되었는가?"뿐만 아니라
"기존 기능이 손상되지 않았는가?"를 중심으로 검토하라.

다음 항목을 반드시 확인한다.

## 1. 변경 내용 확인

* 어떤 코드가 추가되었는가?
* 어떤 코드가 수정되었는가?
* 어떤 코드가 삭제되었는가?

## 2. 삭제된 코드 검토

삭제된 코드가 있다면 각각에 대해 확인한다.

* 정말 사용되지 않는 코드인가?
* 다른 파일에서 참조될 가능성이 있는가?
* 특정 조건에서 실행되는 코드가 아닌가?
* 예외 상황을 처리하는 코드가 아닌가?
* 향후 기능을 위해 존재하는 코드가 아닌가?

확신할 수 없다면 삭제가 적절하지 않은 것으로 판단한다.

## 3. 기존 기능 회귀검증

기존 코드에서 제공하던 주요 기능이
수정 이후에도 동일하게 동작하는지 검토한다.

특히 다음을 확인한다.

* 입력 처리
* 출력 처리
* 데이터 저장
* 데이터 조회
* API 호출
* 이벤트 처리
* 예외 처리
* 권한 처리
* UI 동작
* 파일 처리
* 비동기 처리

## 4. Interface 검증

다음 항목이 변경되지 않았는지 확인한다.

* 함수 이름
* 함수 인자
* 반환값
* 클래스 인터페이스
* API 요청/응답
* 데이터 구조
* 파일 형식

## 5. 오류 수정 검증

처음 제시된 오류가 실제로 해결되었는지 확인한다.

단순히 코드상으로 해결된 것처럼 보이는 것이 아니라
실행 흐름을 기준으로 검증한다.

## 6. 불필요한 변경 검출

오류 수정과 직접적인 관련이 없는 변경이 있다면 찾아낸다.

다음 유형의 변경은 특히 주의한다.

* 리팩토링
* 함수 통합
* 코드 삭제
* 변수명 변경
* 구조 변경
* 파일 이동
* 라이브러리 변경
* 동작 방식 변경

## 7. 최종 판단

다음 중 하나로 판단한다.

### SAFE

오류가 수정되었고 기존 기능에 영향을 주지 않는다고 판단됨.

### REVIEW_REQUIRED

오류는 수정되었으나 기존 기능에 영향을 줄 가능성이 있음.

### UNSAFE

기존 기능의 삭제 또는 동작 변경이 발견됨.

REVIEW_REQUIRED 또는 UNSAFE인 경우
문제가 되는 코드를 구체적으로 설명한다.

코드를 임의로 추가 수정하지 말고,
먼저 문제점과 권장 수정 방법을 보고한다.

이처럼 수정 Prompt와 별도로 사용하는 것이 좋습니다.

7. 한 단계 더 나아가면 “3단계 Agent 구조”가 좋습니다

개발 업무에 LLM을 적극적으로 사용한다면 다음의 구조로 작업을 진행하겠습니다.

     ┌──────────────┐
     │   Bug/Issue  │
     └──────┬───────┘
            ↓
   ┌─────────────────┐
   │ 1. ANALYZER     │
   │ 원인/영향 분석     │
   └────────┬────────┘
            ↓
   ┌─────────────────┐
   │ 2. PATCHER      │
   │ 최소 코드 수정     │
   └────────┬────────┘
            ↓
   ┌─────────────────┐
   │ 3. REVIEWER     │
   │ 회귀/기능 보존     │
   └────────┬────────┘
            ↓
      PASS / FAIL

3단계 내용을 다른말로 정리하면 다음과 같습니다.

  1. Analyzer : “어디가 문제인가?”

  2. Patcher : “최소한으로 고쳐라.”

  3. Reviewer : “기존 기능을 망가뜨리지 않았는가?”

이와같은 구조가 단일 LLM Prompt보다 훨씬 안전합니다.

8. “Skills” 활용

SkillsLLM Agentre-usable skill/instruction 형태로 활용한다면 상당히 좋은 방법입니다. 예를 들어 프로젝트에 다음과 같이 만들어 둘 수 있습니다.

.ai/
├── skills/
│   ├── bug-fix/
│   │   └── SKILL.md
│   │
│   ├── regression-review/
│   │   └── SKILL.md
│   │
│   ├── refactoring/
│   │   └── SKILL.md
│   │
│   └── feature-development/
│       └── SKILL.md
│
├── rules/
│   ├── project-invariants.md
│   ├── architecture.md
│   └── coding-rules.md
│
└── tests/

그리고 작업 종류에 따라 Skill을 선택합니다.

  1. 버그(오류)의 수정
    버그 수정
     ↓
    bug-fix skill
     ↓
    regression-review skill
    
  2. 새로운 기능 추가:
    feature-development skill
    
  3. 리팩토링:
    refactoring skill
    

이렇게 작업 종류별로 LLM 행동을 분리하는 것이 좋습니다. 특히 “Bug Fix Skill”에는 이런 규칙을 넣으세요

BUG FIX SKILL

목표:
기존 기능을 유지하면서 특정 오류를 최소한의 변경으로 수정한다.

우선순위:

1. 기존 기능 보존
2. 오류 해결
3. 변경 범위 최소화
4. 코드 품질 개선

금지:

- 불필요한 리팩토링
- 코드 정리
- 사용되지 않는 코드 삭제
- API 변경
- Interface 변경
- 구조 변경
- 파일 이동
- 기능 제거

원칙:

"Don't rewrite. Patch."

확신하지 못하는 코드:
삭제하지 말고 유지한다.

변경 범위 확대가 필요한 경우:
수정 전에 이유를 보고한다.

수정 후:
반드시 regression review를 수행한다.

9. 테스트 코드

LLM이 기존 기능을 삭제하는 문제를 Prompt만으로 해결하려고 하면 한계가 있습니다. 가장 강력한 방법은 결국 “기존 기능이 정상이라는 것을 테스트로 정의하는 것” 입니다. 예를 들어 기존 기능이 20개라면 각각의 함수에 대한 Test 코드내용을 프로젝트 코드에 포함합니다.

Feature A → test A
Feature B → test B
Feature C → test C
...
Feature T → test T

그리고 LLM에게 다음과 같은 내용을 추가 합니다.

버그 수정 후 기존 테스트를 모두 실행하라.

기존 테스트가 실패하면
오류 수정이 성공한 것으로 판단하지 않는다.

이렇게 LLM에게 내용을 입력하면 이 코드가 필요 없어 보인다 라는 판단보다는 이 코드를 삭제하면 test_17이 실패한다. 라는 객관적인 보호장치가 생깁니다.

10. 추천하는 최종 구조

프로젝트가 LLM을 이용한 개발 중심으로 바뀌고 있다면 다음 구조를 권합니다.

                    [PROJECT RULES]
                          │
                          ▼
                 PROJECT_INVARIANTS
                          │
                          ▼
                   [USER ISSUE]
                          │
                          ▼
                    ANALYZER
                          │
                 변경 범위/원인 분석
                          │
                          ▼
                     PATCHER
                          │
                 최소한의 코드 수정
                          │
                          ▼
                 AUTOMATED TEST
                          │
                          ▼
                    REVIEWER
                          │
             ┌────────────┴────────────┐
             ▼                         ▼
           PASS                       FAIL
             │                         │
             ▼                         ▼
          Commit                원인 재분석

그리고 Git까지 붙이면 이와같은 구조가 상당히 안전합니다.

Git commit
   ↓
LLM Bug Fix
   ↓
git diff
   ↓
Test
   ↓
LLM Regression Review
   ↓
Human Review
   ↓
Commit

11. 특히 피해야 할 Prompt

다음과 같은 표현은 가능하면 피하는 것을 권합니다. 특히 “알아서” 라는 단어가 위험합니다. LLM에게 판단 권한을 너무 많이 주기 때문입니다.

  1. 전체적으로 개선해줘
  2. 코드를 깔끔하게 정리해줘
  3. 불필요한 부분은 삭제해줘
  4. 더 좋은 구조로 변경해줘
  5. 최적화해줘
  6. 중복 코드를 제거해줘
  7. 문제가 있는 부분을 알아서 수정해줘

대신에 다음과 같은 단어로 대체하는 것을 추천합니다. 즉 판단 범위를 제한하는 것이 좋습니다.

  1. 오류와 직접 관련된 부분만 수정하라
  2. 변경이 필요한 이유를 먼저 설명하라
  3. 기존 기능을 보존하라
  4. 확실하지 않은 코드는 삭제하지 마라
  5. 변경 범위를 최소화하라

LLM 작업 전에 다음을 만들어 놓는 것도 좋습니다.

[BEFORE]

기존 기능:
- 로그인 가능
- 검색 가능
- 저장 가능
- CSV 출력 가능

입력:
- user_id
- keyword

출력:
- User
- SearchResult

제약:
- API interface 유지
- DB schema 유지

LLM 수정 후:

[AFTER]

기존 기능:
- 로그인 가능 ✓
- 검색 가능 ✓
- 저장 가능 ✓
- CSV 출력 가능 ✓

입력:
- user_id ✓
- keyword ✓

출력:
- User ✓
- SearchResult ✓

제약:
- API interface 유지 ✓
- DB schema 유지 ✓

이것을 Invariant / Contract라고 생각하시면 됩니다. 즉 LLM에게 단순히 코드를 주는 것이 아니라, “이것은 변경할 수 없는 계약이다.” 라는 정보를 함께 주는 것입니다.



결론

현재 말씀하신 상황이라면 저는 Prompt 하나를 길게 만드는 것보다 다음 5개를 구축하는 방향을 추천합니다.

PROJECT_RULES

프로젝트 전체의 개발 규칙

PROJECT_INVARIANTS

절대 변경되면 안 되는 주요 기능/API/데이터/동작

BUG_FIX_SKILL

오류 수정 전용 규칙

Patch, Don’t Rewrite

REGRESSION_REVIEW_SKILL

수정 후 기존 기능이 없어지거나 변경됐는지 검사

⑤ 자동 테스트 + Git Diff

LLM의 판단을 실제 코드/테스트로 검증


특히 중요한 것은 “오류 수정 Prompt”와 “기능 보존 Prompt”를 하나로 합치는 것입니다.

그리고 더 안정적으로 하려면:

Analyzer → Minimal Patch → Test → Regression Reviewer → Human Approval

이라는 파이프라인으로 만드는 것을 권합니다.

원하시면 다음 단계로는 실제 개발 프로젝트에 바로 넣을 수 있는 형태로 AGENTS.md / SKILL.md / PROJECT_INVARIANTS.md / BUG_FIX.md / REGRESSION_REVIEW.md 5개 파일을 하나의 표준 템플릿으로 설계해 드릴 수 있습니다. 특히 GPT/Codex 계열, Claude Code, Cursor, VS Code Copilot 등에서 공통으로 사용할 수 있는 구조를 기준으로 만들면 좋습니다.