직접 경험하며 느낀 프롬프트 엔지니어링의 핵심

이상현·2025년 9월 15일

AI

목록 보기
1/1
post-thumbnail

"이렇게 프롬프트를 짜면 AI의 성능이 극적으로 올라갑니다."

피곤할정도로 많이 듣는 이야기이다. 이런 말을 볼 때 마다 과연 정말 그럴까? 하는 의심이 들었다.
그래서 Anthropic, Google 등에서 내놓은 여러 프롬프트 엔지니어랑 가이드를 보며 이런저런 기법을 실제로 적용하며 코딩해봤다.

실제로 돌려보니 몇몇 기법은 별 의미 없고 프롬프트만 복잡해지게 만들었고, 몇몇 기법은 진짜 성능이 극적으로 올라가는걸 느꼈다. 이 글에서는 어떤것이 진짜 중요하고 어떤것이 그정도는 아니였는지 경험을 공유해보려고 한다.

코드 작성 작업을 지시하기 위한 프롬프트 엔지니어링 경험 공유입니다.

효과 좋은 것

퓨샷 프롬프팅 (예시 제공) ⭐️⭐️⭐️

이름은 그럴듯 하지만 그냥 원하는 결과물의 예시를 몇개 적어주는거다.

원하는 산출물의 형태를 예시로 들어주는 것은 모든 프롬프트 엔지니어링 중에 최고의 성능 향상을 이끌어낸다.

참고로 퓨샷은 2~4개 멀티샷은 5개 이상의 예시를 제공하는거라고 한다. 하지만 그냥 두세개만 줘도 잘 한다. 현업에서도 퓨샷을 사용하는 비율이 더 높다.

한번 사용하고 말 프롬프트라면 몰라도 반복적으로 사용할 프롬프트라면 원하는 Best Practice 코드를 예시로 꼭 작성해주자.

아래는 테스트코드 작성 프롬프트에 적용한 퓨삿 프롬프팅 예시이다.
별 거 없어 보이지만 이 예시만으로 AI는 한글 메소드명, Junit,AssertJ, given-when-then 을 사용한다는 규칙을 지키게 되어 일관된 코드를 작성하게 된다.

# 테스트 코드 결과물 예시

```java
class CalculatorTest {
    @Test
    void 두_양수를_더했을_때_예상하는_결과값이_나온다() {
        // given
        Calculator calculator = new Calculator();
        int a = 5;
        int b = 3;

        // when
        int result = calculator.sum(a, b);

        // then
        assertThat(result).isEqualTo(8);
    }
    
    @Test
    void 영으로_나누면_예외가_발생한다() {
        // given
        Calculator calculator = new Calculator();
        double a = 10;
        double b = 0;

        // when & then
        assertThatThrownBy(() -> calculator.divide(a, b))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("0으로 나눌 수 없습니다.");
    }
}
```

프로젝트 맥락 전달 ⭐️⭐️

프로젝트의 목적이 무엇인지, 어떤 언어의 어떤 버전을 사용하는지, 코드 스타일 등 프로젝트 맥락을 작성하는 것이다.
이런 정보들을 전달해줘야 불필요한 수정을 거치지 않아도 된다.

사용하는 Agent가 Claude code 면 claude.md, Github Copilot 이면 .github/copilot-instructions.md 에 작성하는 내용이다.

이런 내용을 적으면 좋다.

# 개요

이 프로젝트는 쇼핑몰 서비스의 백엔드 API를 구현한다.
사용 언어는 Java 17, Spring boot 3 이다.

## 폴더 구조

- `main/`: 소스코드
- `test/`: 테스트 코드
- `build/`: 빌드 스크립트와 CI/CD 도구

## 코딩 가이드라인

- space 대신 tab을 사용한다
- 테스트 함수명은 한글 명령문으로 작성한다.
- 객체의 책임을 분리한다

요즘 Agent 는 어차피 알아서 프로젝트 구조를 탐색하기 때문에 안적어줘도 된다고 생각할 수 있지만,
그 탐색 과정이 모두 토큰 낭비이고, 불필요한 정보가 쌓이며 할루시네이션 빈도를 높힌다. 불변하는 규칙은 꼭 적어주자.

예시: Vscode Github

작업 세분화 하기 ⭐️⭐️

큰 작업을 지시한다면, 작업을 세분화하는게 훨씬 좋다.

테스트 코드 작성해

->

# 테스트 코드 작성 작업

1. 첨부된 명세서를 분석한다.
2. 기존에 작성되어있는 테스트 코드 스타일을 파악한다.
3. 테스트 전략을 수립한다. (경계값, 핵심 시나리오 파악)
4. 단위 테스트를 구현한다.
5. 테스트를 실행하고 디버깅한다.

각 단계에 세부 지침을 더 작성해도 좋다.
하지만 과하면 오히려 성능 저하가 될 수 있으니 핵심만 간결하게 잘 전달하자.

길게 생각하게 하기 ⭐️

Agent 가 작업을 길고 신중하게 하게 하기위한 여러가지 방법들이 있다.

  • Sequential MCP
  • Github Copilot의 Think, Todo Tool
  • CoT (프롬프트에 "단계별로 생각하세요" 포함하기)

사용해본 결과, 3~5단계 이상의 세부 작업으로 나누어질 수 있는 작업에서는 눈에 띄는 성능 향상을 보인다.

하지만, 요즘 발전된 Agent들은 작업이 복잡하다면 알아서 작업을 오래 진행하도록 발전하고 있어 지시가 중복될 수 있다.
복잡하지 않은 작업에 위 방법을 적용해봤자 토큰 사용량만 늘어날 수 있다.

좋은 프롬프트의 기준?

좋은 프롬프트란, 옆에 앉아있는 개발자에게 프롬프트를 보여줬을 때, 무슨 작업을 지시하는건지 잘 알아듣는다면 좋은 프롬프트라고 한다.

단순하게 생각하면 된다. 사람이 알아보기 쉬우면 AI도 알아듣기 쉽다.

별로였던 것

너무 길고 복잡한 프롬프트

작업을 맡기다 보면 마음에 들지 않아 프롬프트에 계속 지시를 누적하다 보면 핵심인 내용과 그렇지 않은 내용이 구분되지 않아 작업 성능이 오히려 더 낮아졌다.

문서 상으로는 프롬프트는 200,000 토큰 (md 파일 기준 10,000줄 이상)의 길이를 가져도 괜찮다고 한다.
하지만 시스템 프롬프트 같이 이미 agent 에 내장된 프롬프트도 있고, 작업이 길어지면 컨텍스트가 쌓이게 되어 너무 길게 작성하면 점점 성능 하락과 할루시네이션이 발생 빈도가 높아진다.

개발자가 작성하는 프롬프트는 10,000 토큰 (약 500~700줄) 이하로 유지하는것이 여러모로 좋은것 같다.

XML 포맷 사용

Anthropic 문서에서는 Claude 모델은 XML 포맷이 Markdown 포맷보다 더 낫다는 언급이 있다.
하지만 사람이 보기에 가독성이 떨어지고, 막상 같은 내용을 Markdown 과 XML 로 비교해보면 체감되는 성능 차이는 없었다.

프롬프트 또한 코드처럼 유지보수를 해야하기 때문에 가독성도 중요하다. 그냥 Markdown 쓰자.

결론

AI의 성장이 엄청 가파르다. AI를 활용하는 기법이나 도구 또한 마찬가지이다. 대세가 된 도구도 몇달뒤면 뒤쳐져있는 것이 요즘 현실이다.

게다가, 어떤 사람은 "이 프롬프트를 넣으면 작업을 잘하게 해줍니다" 라고 하고, 어떤 사람은 "이 한줄만 추가하면 작업이 간결해져서 토큰 사용량이 줄어듭니다!" 라고 한다.

또한, 같은 목적을 가진 기능이 MCP 로도 구현되어있고, LLM 모델 자체에도 탑재되어있고, AI Agent 기능에도 구현되어있고, 프롬프트에도 넣으라고 하고, 시스템 프롬프트로 이미 들어가있기도 하다.

이런 정보의 호수 속에서 우리가 신경쓰면 좋은 프롬프트 엔지니어링에서 변하지 않는 핵심 원칙을 세가지만 추려보자면 다음과 같다.

  • 몇가지 예시 제공
  • 프로젝트 맥락 전달
  • 작업 세분화

이 세개만 활용해도 AI의 성능을 어느정도 최대치로 끌어올릴 수 있다.

참고자료
Anthropic - 프롬프트 엔지니어링 개요
Google - 프롬프트 엔지니어링: 개요 및 가이드
Prompt engineering for GitHub Copilot Chat
여러 프롬프트를 모아둔 레포지토리 - Awesome Copilot

0개의 댓글