23P by GN⁺ | ★ favorite | 댓글 1개
  • AI 코딩 도우미는 프로젝트 의도를 스스로 알 수 없으므로, 개발자가 맥락·목표·예시를 얼마나 잘 주느냐에 따라 결과 품질이 크게 달라짐
  • 디버깅에서는 코드와 오류만 던지기보다 기대 동작, 실제 동작, 실행 환경을 함께 제공하고 라인별 추적이나 최소 재현 예제로 문제 범위를 좁혀야 함
  • 리팩터링과 최적화는 “더 좋게”가 아니라 중복 제거, 병렬 처리, 오류 처리 유지, 버전 제약 같은 성공 기준을 명확히 해야 함
  • 새 기능 구현은 전체를 한 번에 맡기기보다 계획, 골격, 상태 관리, API 연동, 엣지 케이스를 작은 단계로 나눠 검토하며 확장하는 방식이 안전함
  • 모호한 질문, 과도한 요구, 질문 없는 코드 덤프, 불명확한 참조는 결과를 흔들며, AI는 일회성 생성기보다 반복 대화형 페어 프로그래머로 다뤄야 함

AI 코딩 도우미를 잘 쓰기 위한 기본 원칙

  • AI 코딩 도우미는 함수 자동완성, 버그 수정 제안, 모듈이나 MVP 생성까지 도울 수 있지만 프로젝트의 구체적 의도는 사용자가 제공한 정보에 의존함
  • 좋은 프롬프트는 AI를 “문자 그대로 받아들이는 협업자”처럼 대하고, 원하는 결과와 형식을 명확히 안내함
  • 기본 원칙은 다음과 같음
    • 풍부한 맥락 제공: 언어, 프레임워크, 라이브러리, 관련 함수나 코드 조각, 정확한 오류 메시지, 기대 동작을 포함함
    • 목표 구체화: “왜 안 되나?”보다 “이 JavaScript 함수가 기대값 대신 undefined를 반환하는 이유와 수정 방법”처럼 질문을 좁힘
    • 복잡한 작업 분해: 큰 기능을 한 번에 요청하지 않고 React 컴포넌트 골격 생성, 상태 관리 추가, API 호출 통합처럼 순차적으로 진행함
    • 입출력 예시 제공: [3,1,4] 입력이 [1,3,4]를 반환해야 한다는 식의 예시는 요구사항의 모호성을 줄임
    • 역할 지정: “senior React developer”, “JavaScript performance expert”, “code reviewer”처럼 역할을 주면 답변의 깊이와 스타일을 조정할 수 있음
    • 반복과 수정: 첫 답변이 맞지 않으면 재귀 대신 반복문 사용, 변수명 개선, 주석 추가처럼 후속 요청으로 방향을 조정함
    • 코드 명확성 유지: 의미 있는 함수명과 변수명, 일관된 포맷, 주석과 docstring은 AI가 코드 의도를 파악하는 단서가 됨

디버깅 프롬프트 패턴

  • 디버깅 요청에는 코드가 무엇을 해야 하는지, 실제로 무엇이 잘못됐는지, 어떤 오류가 발생했는지가 함께 들어가야 함
  • 좋은 디버깅 프롬프트는 보통 다음 정보를 포함함
    • 사용 언어와 실행 환경
    • 문제 코드
    • 정확한 오류 메시지 또는 잘못된 출력
    • 기대 출력
    • 예시 입력
    • 이미 시도한 방법
  • 복잡한 로직 버그는 AI에게 라인별 실행 추적을 요청해 상태 변화를 따라가게 할 수 있음
    • 예: “이 함수에서 total 값이 각 단계마다 어떻게 변하는지 추적하고, 어디서 누적이 잘못되는지 찾아줘”
  • 코드베이스가 크더라도 버그를 재현하는 작은 코드 조각을 만들 수 있다면 최소 재현 예제로 제시하는 편이 좋음
  • 첫 답변이 부분적으로만 유용하면 “수정된 코드를 보여줘”, “왜 이 변경이 문제를 해결하는지 설명해줘”처럼 후속 질문을 이어갈 수 있음

디버깅 예시: 모호한 질문과 개선된 질문

  • 예시 코드는 mapUsersById(users)가 사용자 배열을 ID 기반 객체로 변환하려는 Node.js/JavaScript 함수임
  • 버그는 for (let i = 0; i <= users.length; i++) 조건에 있음
    • 배열 길이가 1이면 i = 0i = 1이 실행됨
    • users[1]undefined가 되고 user.id 접근에서 TypeError가 발생함
  • “왜 mapUsersById 함수가 작동하지 않나?”처럼 함수명만 주는 프롬프트는 맥락이 부족함
    • AI는 배열이 비었는지, 각 user에 id가 있는지, usersundefined인지 같은 일반적 가능성을 나열할 수 있음
  • 개선된 프롬프트는 다음을 함께 제공함
    • 함수의 목적: 사용자 객체 배열을 ID 키 기반 객체로 변환
    • 예시 입력: { id: 1, name: "Alice" }
    • 오류 메시지: Cannot read property 'id' of undefined
    • 코드 조각
    • 기대 결과: { "1": {id: 1, name: "Alice"} }
  • 이렇게 정보를 좁히면 AI가 루프 조건의 <=i < users.length로 바꾸는 수정과 그 이유를 직접 제시할 수 있음

디버깅을 보완하는 요청 방식

  • 원인을 모를 때는 코드와 함께 “이 코드에서 TypeError: cannot read property 'foo' of undefined가 발생할 수 있는 이유는 무엇인가?”처럼 가능한 원인 목록을 요청할 수 있음
  • 러버덕 방식으로 사용자가 함수 동작을 설명하고, AI에게 그 설명이 맞는지 검토하게 할 수 있음
  • 깨질 가능성이 있는 테스트 케이스를 AI에게 만들게 할 수 있음
    • 빈 배열
    • 매우 큰 숫자
    • null
    • 예상하지 못한 입력
  • “code reviewer” 역할을 부여하면 버그뿐 아니라 누락된 null 체크나 나쁜 관행도 함께 찾기 쉬움

최신 디버깅 시나리오 예시

  • React Hook 의존성 문제에서는 “useEffect가 이상하다”보다 정확한 코드, 기대 동작, 실제 동작, 콘솔 오류를 함께 제공하는 프롬프트가 더 유용함
    • 예시 오류는 Warning: Maximum update depth exceeded
    • 기대 동작은 userId가 바뀔 때 한 번 사용자 데이터를 가져오는 것
    • 실제 동작은 무한 재렌더링임
    • 질문은 의존성 배열에서 무엇이 무한 루프를 일으키는지와 수정 방법에 집중함
  • Next.js 14 전자상거래 앱의 상태 관리 설계 요청은 기술 스택과 요구사항을 함께 제시함
    • App Router와 Server Components
    • TypeScript strict mode
    • SEO를 위한 서버 측 데이터 가져오기
    • 장바구니와 사용자 동작을 위한 클라이언트 상호작용
    • 내비게이션 간 상태 유지
  • 상태 관리 선택지는 Zustand, React Query/TanStack Query + Zustand, 단일 Zustand store with slices처럼 구체적으로 비교 요청함

리팩터링과 최적화 프롬프트 패턴

  • “이 코드를 리팩터링해줘”는 너무 열려 있어 AI가 사용자의 기준과 다른 방향으로 코드를 바꿀 수 있음
  • 리팩터링 목표는 구체적으로 지정해야 함
    • 가독성 개선
    • 유지보수성 향상
    • 중복 제거
    • 성능 최적화
    • 더 관용적인 코드 스타일
    • 특정 라이브러리나 패러다임 사용
  • 코드 맥락도 함께 제공해야 함
    • 전체 함수나 관련 코드 조각
    • 사용 언어와 프레임워크
    • React class component를 Hooks 기반 functional component로 바꾸는지 같은 목표 스타일
    • Node.js v14, ES6 modules 같은 버전과 환경 제약
  • 리팩터링 결과와 함께 변경 이유를 요청하면 AI가 코드 의도를 제대로 이해했는지 검토할 수 있음
  • “seasoned TypeScript expert”, “experienced Python developer mentoring a junior”처럼 역할을 지정하면 더 높은 기준의 리팩터링과 설명을 유도할 수 있음

리팩터링 예시: getCombinedData

  • 예시 함수 getCombinedData(apiClient)/users/orders를 각각 가져오고, 사용자별 주문을 찾아 결과 배열을 만드는 코드임
  • 원래 코드에는 다음 문제가 있음
    • 사용자와 주문을 가져오는 fetch 로직이 중복됨
    • 오류 메시지가 단순함
    • 두 요청을 순차 실행함
    • 사용자마다 orders.filter를 수행해 조합 단계가 비효율적일 수 있음
  • “위 함수를 리팩터링해줘”라는 요청만으로도 AI가 Promise.all, ordersByUser 맵, .map을 사용할 수 있지만 사용자의 의도와 맞지 않는 변경이 생길 수 있음
    • 예시에서는 개별 오류 메시지가 Failed to fetch data로 합쳐져 어떤 호출이 실패했는지 정보가 줄어듦
  • 개선된 프롬프트는 원하는 기준을 나열함
    • fetch 중복 제거
    • 두 목록을 병렬로 가져오기
    • 사용자와 주문 fetch의 오류 처리를 각각 유지
    • 중첩 루프 대신 더 효율적인 조회 구조 사용
    • 변경 이유를 주석으로 설명
  • “더 좋게”의 기준을 사용자가 정의하면 AI가 Promise.all, 개별 ok 체크, ordersByUser 조회 맵, users.map 기반 결과 생성을 요구에 맞춰 구성할 수 있음

리팩터링 후 검증과 학습

  • 큰 코드나 긴 변경 목록은 한 번에 처리하지 말고 단계별로 나누는 편이 좋음
    • 먼저 가독성을 위한 리팩터링
    • 이후 알고리듬 최적화
  • 대안 비교도 요청할 수 있음
    • 함수형 스타일로 바꾸기
    • 반복문 대신 배열 메서드 사용
    • 재귀 방식과 반복 방식 비교
  • AI가 제안한 리팩터링의 설명을 읽으면 reduce로 맵을 만드는 방식 같은 새로운 API나 기법을 배울 수 있음
  • AI가 만든 리팩터링은 항상 테스트나 샘플 입력으로 검증해야 함
    • 프롬프트에 중요한 제약이 빠졌다면 AI가 미묘한 버그를 만들 수 있음
    • 필요하면 “리팩터링된 함수의 단위 테스트를 만들어줘”라고 요청할 수 있음

새 기능 구현 프롬프트 패턴

  • 새 기능은 구현 방식이 여러 가지라서 AI가 프로젝트 요구와 스타일에 맞도록 안내해야 함
  • 먼저 큰 목표를 설명한 뒤 단계별로 나누는 방식이 권장됨
    • 예: React 앱에 제품 이름 검색 기능 추가 계획 요청
    • 이후 검색 입력 컴포넌트, 검색 상태, 필터링 로직을 각각 구현 요청
  • 기존 프로젝트에 기능을 추가한다면 비슷한 컴포넌트나 참조 코드를 제공하는 것이 좋음
    • UserList와 유사한 ProductList를 만들되 검색 바를 포함하도록 요청하는 식임
  • 프로젝트의 아키텍처나 스타일도 명시해야 함
    • Redux 사용 여부
    • 특정 CSS 프레임워크
    • MVC 패턴
    • 상태를 controller에 둘지 view에 둘지 같은 제약
  • IDE에서 Copilot을 사용할 때는 주석과 TODO를 인라인 프롬프트로 활용할 수 있음
    • 예: // TODO: Validate the request payload (ensure name and email are provided)
  • 새 함수나 기능에는 사용 예시나 간단한 테스트 케이스를 함께 제시하는 편이 좋음
    • formatPrice(2.5)'$2.50'을 반환해야 한다는 식의 예시는 출력 형식을 고정함

React 제품 목록 기능 구현 예시

  • 예시 요청은 ProductList React functional component 생성을 목표로 함
    • /api/products에서 {id, name, ...} 배열을 가져옴
    • 상태에 저장함
    • 검색 입력으로 제품 이름을 대소문자 구분 없이 필터링함
    • <ul>에 제품명을 표시함
    • 로딩 상태와 API 실패 오류 메시지를 처리함
  • AI는 useState, useEffect, fetch, products.filter, toLowerCase, loading, error 상태를 포함한 컴포넌트를 생성할 수 있음
  • 프로젝트가 직접 fetch를 쓰지 않고 useProducts() 커스텀 훅을 사용한다면, 후속 프롬프트에서 그 제약을 추가해 컴포넌트를 조정해야 함
  • 정렬 드롭다운 같은 추가 요구사항은 기존 대화 맥락 위에 확장할 수 있음
    • sortOrder 상태 추가
    • A-Z 또는 Z-A 선택
    • 필터링된 목록을 localeCompare로 정렬
  • 기능 구현에서는 스캐폴딩 → 검토 → 수정 → 확장의 반복이 중요함

기능 구현을 더 안전하게 만드는 요청

  • AI에게 먼저 골격을 만들게 하고, 프로젝트 고유의 검증 규칙이나 DB 호출은 사용자가 채울 수 있음
    • 예: 사용자 등록용 Node.js Express route 골격 생성
  • 엣지 케이스를 함께 묻는 방식도 유용함
    • 검색 결과가 비는 경우
    • 제품이 아직 로드되지 않은 상태
    • 매우 큰 목록에서 debounce가 필요한 경우
  • docstring이나 사용 예시를 먼저 작성하고 AI에게 구현을 채우게 할 수 있음
    • fibonacci(n)의 0-indexed 정의
    • fibonacci(5) -> 5 예시
    • 반환값 설명
  • 이런 방식은 주석을 사실상 명세로 사용해 AI가 요구에 맞춰 코드를 작성하게 함

흔한 프롬프트 안티패턴

  • 모호한 프롬프트

    • “작동하지 않으니 고쳐줘”처럼 맥락이 부족하면 AI는 일반론을 말할 가능성이 큼
    • 코드, 오류 메시지, 기대 결과, 실제 결과를 추가해야 함
  • 과부하된 프롬프트

    • 인증, React 프런트엔드, 배포 스크립트를 포함한 전체 Node.js 앱 생성처럼 너무 많은 작업을 한 번에 요청하면 결과가 뒤섞이거나 일부 요구가 누락될 수 있음
    • 작업을 순차 단계로 나눠야 함
  • 질문이 없는 코드 덤프

    • 큰 코드만 붙이고 “여기 내 코드야”라고 하면 AI가 요약, 수정, 설명 중 무엇을 해야 할지 알기 어려움
    • “버그를 찾아줘”, “TODO를 완성해줘”, “이 코드가 하는 일을 설명해줘”처럼 목적을 명시해야 함
  • 성공 기준이 모호함

    • “더 빠르게”, “더 깨끗하게”는 기준이 주관적임
    • 선형 시간으로 최적화, 전역 변수 제거, 클래스로 변경, 변수명 개선처럼 기준을 구체화해야 함
  • AI의 확인 질문 무시

    • AI가 React class component인지 functional component인지 묻는다면 필요한 정보가 부족하다는 신호임
    • 같은 요청을 반복하지 말고 빠진 세부사항을 보완해야 함
  • 불명확한 참조

    • 긴 대화에서 “위 코드”라고만 말하면 AI가 다른 코드 조각을 참조할 수 있음
    • 함수명을 명확히 쓰거나 코드를 다시 인용하는 편이 안전함

프롬프트가 실패했을 때 고치는 방법

  • 먼저 AI 출력에서 무엇이 빠졌거나 잘못됐는지 확인해야 함
    • TypeScript를 요청했는데 JavaScript가 나왔는지
    • 반복문을 원했는데 재귀가 나왔는지
    • 브라우저용 코드가 필요한데 Node.js API를 썼는지
  • 새 프롬프트에는 빠진 요구사항을 강조함
    • “TypeScript로 작성하고 타입 주석을 포함해줘”
    • “재귀를 쓰지 말고 반복문을 사용해줘”
    • “외부 라이브러리는 사용하지 마”
    • “브라우저에서 실행되어야 하므로 Node 전용 API를 쓰지 마”
  • 복잡한 요청에서 반복 실패하면 더 작은 단위로 나누거나, AI에게 먼저 요구사항을 어떻게 이해했는지 되풀이하게 할 수 있음
  • 대화가 여러 번 꼬였다면 새 세션에서 개선된 프롬프트로 다시 시작하는 방법도 있음

개발 워크플로에 적용되는 결론

  • 프롬프트 엔지니어링은 AI 코딩 도우미를 일회성 코드 생성기가 아니라 페어 프로그래머처럼 쓰기 위한 기술임
  • 효과적인 프롬프트는 동료 개발자에게 도움을 청할 때와 같은 정보를 제공함
    • 코드가 해야 할 일
    • 실제로 잘못된 동작
    • 관련 코드 조각
    • 오류 메시지
    • 기대 출력
  • 역할 지정, 반복 질문, 단계적 구현, 설명 요청은 문제 해결뿐 아니라 사용자가 새 패턴을 배우는 데도 도움이 됨
  • AI는 많은 코드와 문제 해결 사례를 학습했지만, 현재 문제에 어떤 사례가 관련 있는지는 사용자가 제공하는 맥락에 따라 달라짐
  • 좋은 프롬프트는 한 번에 완성하는 문장이 아니라, 다른 엔지니어와 대화하듯 명확성, 인내, 세부사항을 더해 가는 반복적 대화

댓글과 토론

Hacker News 의견들
  • 경험상 진짜 프롬프트 엔지니어링 기법은 세 가지뿐이라고 봄: 문맥 내 학습(예시 제공, 즉 원샷/퓨샷 vs 제로샷), 생각의 사슬(단계별로 생각하라고 지시), 구조화된 출력(JSON 같은 지정 형식으로 내보내라고 지시)
    여기에 글에서 말하는 역할 프롬프트를 추가할 수도 있음. RAG는 제공한 문맥을 모델이 요약하게 만드는 별개의 영역에 가깝고, 나머지는 결국 원하는 일을 명확한 평문으로 말하는 데로 귀결됨

    • 문맥이 왕
      TypeScript로 시작해 데이터 과학 질문을 하면 잘 못 풀지만, Python으로 시작해 같은 질문을 하면 훌륭한 답이 나옴. LLM은 아직 도메인 간 지식 전이를 제대로 못 하므로 올바른 방식으로 먼저 준비시켜야 함
    • 역할 프롬프트조차 개인적으로는 완전히 쓸모없다고 봄. GPT-3 때는 의미가 있었을지 몰라도, 대부분의 LLM은 이미 자신이 “전문 프로그래머”라는 걸 알고 있음. 많은 사람이 프롬프트 엔지니어링이라는 말로 스스로를 속이는 듯함
      요구사항을 명확히 쓰고, 필요하면 예시를 추가하고, 출력이나 추론 모델의 추론 흔적을 확인하면 됨. 원하는 결과가 아니면 조정하며 반복하고, 몇 번 해도 안 되면 AI를 포기하고 머릿속 추론 모델을 쓰면 됨
    • 사람들이 모든 걸 프롬프트 하나나 거대한 요청 하나에 몰아넣고 전체 문맥을 던지려는 게 핵심 문제라고 봄. 말한 세 가지는 맞지만, 하나의 거대한 요청 대신 여러 부분으로 나누고, 작은 문맥의 여러 프롬프트가 각자 구조화된 출력을 내게 해서 서로 이어 먹이는 편이 좋음
      프롬프트는 초점을 좁히고, 명시적 출력 형식과 예시를 넣고, 문맥을 과부하시키지 않는 게 좋음. 그러면 결국 위의 세 가지로 정리됨
    • 3번과 관련해, 동료들과 과학 분야 사용 사례를 연구했음: https://doi.org/10.1038/s41467-024-45563-x
    • 보충하자면, 우리의 사용 사례에서는 저샷이나 퓨샷 프롬프트 엔지니어링이 통하지 않아서 미세조정을 더 많이 썼음
  • 가끔 아주 길고 복잡한 프롬프트가 모델의 인지 성능을 떨어뜨리는 것 같다는 느낌을 받음. 통제하고 제대로 엔지니어링한다는 느낌은 줄 수 있지만, 순효과가 있는지는 확신하기 어려움
    결국 아주 단순하고 최소한의 프롬프트를 쓰고, 몇 번 반복하며 작은 조정을 하는 방식으로 수렴했음

    • 나도 정확히 그렇게 쓰기 시작했음. 1) 필요한 만큼의 문맥, 유지되는 가정, 목표만 줌. 2) 답을 검토하고 초기 프롬프트를 반복 개선함. 비용 면에서도 경제적임
      에이전트를 쓰다가 너무 많이 데였음. 계속 빙빙 돌면서 프롬프트 하나에 30달러를 태우고, 코드베이스를 망치거나 이전에 작성된 코드로 되돌아가곤 했음. 또 AI가 프로젝트에 많은 코드를 쓰게 하면 나중에 발전시키고 확장하고 자신 있게 진행하기가 더 어려워짐. 직접 생각하고 쓰지 않은 코드는 기억에도 잘 남지 않음
    • 찾아봐야겠지만, 전문가의 어휘를 쓰면 일반인의 표현보다 더 나은 결과가 나온다는 근거가 있음. 말이 되는 게, 사람들이 “일상적으로” 말하는 공간은 틀릴 가능성이 더 높고, 전문 용어로 말하는 공간은 더 정확할 가능성이 높기 때문임. 학습도 그런 공간들을 서로 연관시킬 것임
    • 다른 종류의 작업에서 동료가 아주 장황한 프롬프트를 써둔 적이 있었음. 통합해야 해서 프롬프트용 CRUD 작업을 추가했고, 테스트 삼아 “이걸 ...로 분석해” 정도의 아주 짧은 프롬프트를 만들어 봤음
      출력은 거의 비슷했는데, 긴 프롬프트의 출력에는 그 프롬프트의 문구를 그대로 참조하는 부분이 꽤 많이 들어갔음. incoherent하진 않았지만, 모델이 프롬프트에서 작업을 추출해 기본 응답을 만든 뒤 불필요한 조각들을 섞어 넣는 것처럼 보였음. 적어도 이 특정 작업에서는 모델을 쉽게 다르게 “생각”하게 만들 수 없어 보였음. 참고로 모델은 Gemini 2.5였음
    • 오늘 비슷한 일을 겪었음. CLAUDE.md에 큰 상세 프롬프트를 넣고 코드 리뷰를 돌리다가, 그 파일이 아직 없는 브랜치에서 실행했더니 더 좋은 결과가 나왔음
    • 나도 같은 결론에 이르렀는데, 그렇다면 AI 연구소들의 엄청나게 긴 프롬프트는 어떻게 설명해야 할까?
      https://docs.anthropic.com/en/release-notes/system-prompts#m...
  • “프롬프트 엔지니어링” 같은 건 없다고 봄. 제대로 의미 있는 문장을 쓰는 능력이 언제부터 엔지니어링이 됐나?
    “소프트웨어 엔지니어링”보다도 더 심함. 안타까운 건 이런 직무 공고가 아마 생길 것이고, 사람들은 문장 쓰는 놀라운 능력으로 스스로를 프롬프트 엔지니어라고 부를 것이라는 점임

    • “제대로 의미 있는 문장”이 무엇인지는 많은 변수에 따라 달라짐. 이를 테스트하고 추적하고 기록하고 버전 관리하면 “감으로 프롬프트 쓰기”에서 프롬프트 엔지니어링으로 넘어간다고 봄
      이런 작업을 다룬 논문도 많음. 어떤 방식은 다른 방식보다 더 잘 먹힘. 구조화가 중요하고, 문체가 중요하고, 정보 순서가 중요하고, 문제를 다시 진술하는 것도 중요함. 모델 계열마다 특이점도 있음. API로 제공되는 모델을 쓰면 새 버전이 기존 프롬프트에서 여전히 잘 동작하는지 내부 검사가 필요하고, 이런 검사와 테스트가 프롬프트 엔지니어링임. 많은 사람이 과장 광고에 반사적으로 반응하다가, 그걸 비웃고 싶어서 중요한 측면을 놓치는 것 같음
    • 동네 바리스타가 스스로를 커피 엔지니어라고 부른다면, 그쪽이 더 그럴듯한 직함으로 느껴질 것 같음
    • 직접 겪어보지 못했다고 해서 불가능하다고 단정하는 건 조심해야 함. 복잡한 문제에서 LLM으로 높은 레버리지의 결과를 내려면 프롬프트 엔지니어링이 필요함. 충분조건은 아니지만 필요조건에 가까움
      없으면 해법에 도달할 가능성이 낮고, 있으면 해법의 90%까지 간 뒤 마지막 구간을 미세조정할 가능성이 훨씬 높아짐. 그래도 보장되진 않음. 어쩌면 “프롬프트 엔지니어링”이라는 말이 나쁘고, 보편적으로 적용되는 견고하고 반복 가능한 원칙보다는 기술, 취향, 판단의 요소가 더 크니 “프롬프트 제작”이라고 불러야 할지도 모름
    • 문맥이 왕
      예를 들어 계약업체 팀이 둘 있다고 해보자. 하나는 자국 팀이고 원격으로 일하며, 다른 하나는 인도에 있는 인도 팀임. 둘에게 정확히 같은 방식으로 소통하고 메시지를 전혀 조정하지 않을까? 당연히 조정할 것이고, 그게 바로 “프롬프트 엔지니어링”임
      언어 모델은 서로 다르고 지금은 좀 까다로워서, 각 모델에서 좋은 출력을 얻으려면 특정한 입력이 필요함. 직접 해볼 수 있음. 무료 티어의 주요 모델들에게 특정 언어로 간단한 스크립트를 작성해 달라고 해보면, 전부 다른 출력을 내고 각자 빠지는 특정한 “스타일”이 있음
    • 현대의 알고리즘 기반 브레인롯이 평균 소비자의 완전한 문장 읽기 능력, 하물며 문장 쓰기 능력까지 망가뜨린 이후부터임
  • 요즘 프롬프트 가이드가 너무 많음. 개인적으로는 꽤 불필요하다고 봄. 시간을 들여 도구를 쓰고, 익숙해지고, 작동 방식을 이해하면 어떤 프롬프트를 써야 할지는 꽤 분명해짐

    • Google이 인기를 얻었을 때도 같은 과장과 FOMO가 있었던 게 떠오름. 관련 책들이 나왔고, 그걸 사지 않으면 가까운 미래에 원시인이 될 것처럼 굴었음
      실제로는 누구나 하루면 전부 배울 수 있었고 그걸로 끝이었음. 그런 도구들을 전부 모르면 뭔가 놓치는지 논쟁할 필요가 없었음
    • 프롬프트 가이드를 읽거나 숙련된 사용자를 보는 게 매우 가치 있는 사람들도 있다고 봄
      많은 사람은 스스로 더 잘해지려고 의식적으로 생각하지 않지만, 그중 일부는 관련 글 하나를 읽거나 영상 하나를 봄. 나도 다른 사람들이 이 도구를 쓰는 걸 보거나 동료들과 논의하면서 유용한 팁을 몇 가지 얻었음을 쉽게 인정함. 도구를 혼자 쓰기만 했다면 얻지 못했을 개선임
    • 오래전 사용자 스토리를 쓰는 법에 대한 가이드가 있었음. “[역할]로서, [목표]를 달성하기 위해 [작업]을 할 수 있기를 원한다” 같은 형식이었고, 높은 수준에서 생각하는 사람들에게 요구사항을 덜 모호하게 전달하는 법을 가르치는 데 유용했음
      단순해 보일 수 있지만, 경험상 뛰어난 개발자도 구조화되지 않은 요구사항을 놓치거나 오해할 수 있고, 그게 그들의 잘못은 아님
    • 적어도 다른 사람들이 이 도구로 어떻게 생산성을 내는지 보는 데는 유용함. 내가 이미 하던 일을 개선해 주는 영리한 아이디어를 가끔 찾기도 함
      이 분야의 현재 상태를 기록하는 의미도 있음. 1년 전에 뭔가를 시도해 보고 여전히 별로라고 생각하기 쉽기 때문임. 보통은 시행착오로 바퀴를 재발명하기 전에 먼저 조사하는 편을 선호함. 사람들이 자기 시간을 들여 발견한 것을 공유해 주는 게 고마움. 십대였을 때처럼 마음껏 탐색할 시간이 항상 있는 건 아니기 때문임
    • 분명 직관적이지 않은 요령들이 있음. 예를 들어 “please” 같은 공손한 표현은 전부 지우는 게 좋아 보임
  • 오래전에 컴퓨터과학 석사 과정에서 프로그래밍 과학 수업을 들었음. 그때 배운 검증 방식이 데이터 엔지니어링 작업에서 프롬프트를 짜는 데 도움이 됨
    기본적으로 “입력 (…)과 사전조건 (…)이 주어졌을 때, 사후조건 (…)을 만족하는 Spark 코드를 작성해 달라”는 식임. 입력, 사전조건, 사후조건을 형식적으로 명세할 수 있으면 보통 잘 동작하는 코드를 얻음

    1. Science of programming, David Gries
    2. Verification of concurrent and sequential systems
  • 내 경험상 문제가 LLM으로 풀 수 없는 것이라면, 어떤 프롬프트 “엔지니어링”도 실제로 도움 되지 않음. 해결하는 유일한 방법은 부분적으로 풀어서, 즉 하위 작업이나 예시로 나누고 모델이 제 몫을 하게 하는 것임
    내가 틀렸다면 좋겠음. 다른 경험이 있다면 공유해 주면 좋겠음

    • LLM을 쓰는 기술의 일부는 문제를 효과적으로 쪼개는 감각, 그리고 언제 쪼개야 하고 언제 그러지 말아야 하는지 아는 감각이라고 봄. 글에서도 이 부분을 다룸
      앞으로는 LLM과의 상호작용을 개선하기 위해 코드를 재구성하고, 정리하고, 주석 다는 방식도 보게 될 것 같음. LLM도 이런 작업을 더 잘하게 되고, 프로그래머가 어려워하는 문제를 어떻게 쪼개면 좋을지 제안할 수도 있음
    • 프롬프트 엔지니어링의 의도는 원하는 형식으로 더 나은 해법을 더 빨리 얻는 것이라고 봄. 그래도 이상적으로는 모델이 그냥 “알아서” 하고, 질문을 엔지니어링할 필요가 없어야 함
  • 프롬프트를 너무 과하게 엔지니어링하는 것처럼 보임
    그냥 원본 코드나 오류를 붙여넣고 평범한 질문을 해도 충분히 잘 됨. 모델들이 알아서 파악할 만큼 똑똑함

  • 프롬프트를 쓰는 데 “엔지니어링”이라는 말을 붙이는 건 너무 진지하지 않아 보임

    • 몇 년 전 프롬프트 “엔지니어링”이 한창 유행할 때 꽤 웃긴 비유를 본 적이 있음
      “누군가를 프롬프트 엔지니어라고 부르는 건, Subway에서 일하는 사람의 셔츠에 ‘Sandwich Artist’라고 적혀 있다고 그를 예술가라고 부르는 것과 같다.”
      농담은 제쳐두고 직함에 너무 매달릴 필요는 없음. engineer라는 말은 오래전부터 의미가 희석돼 거의 무의미해졌음
      https://jobs.mysubwaycareer.eu/careers/sandwich-artist.htm
    • 미국에는 “세일즈 엔지니어”도 있음. 내 경험상 그들은 팔아야 하는 물건이 어떻게 동작하는지 전혀 모르는 사람들이었음
    • 이건 기본적으로 소프트웨어 엔지니어링 전반에 대해 늘 나오는 논쟁과 같은 것 아닌가?
    • 상상력이 채팅 인터페이스에서 웃긴 고양이 사진을 요청하는 수준에서 멈췄기 때문임
      API와 자동화 워크플로 안에서 쓰이는 프롬프트들이 있고, 그 이상도 있음
    • IT는 단어와 그 의미가 죽으러 가는 곳임. 애초에 단어가 뭔가를 의미할 필요가 있었는지도 궁금함
  • 이제 LLM을 효과적으로 쓰려면 확실히 이해하고 프롬프트를 맞춤화해야 하는 것처럼 보임. 그런데 이게 전부 주관적이지 않나? 질문을 어떻게 쓰느냐에 따라 다른 답을 받음
    조금 더 객관적이어야 하는 것 아닌가? 단지 표현이 다르다는 이유로 결과가 달라지는 건 무작위적인 것 아닌가? 이 전체가 너무 혼란스러움

    • 덧붙이면 내 경험은 이렇다. 앞단에서 프롬프트 엔지니어링에 많은 시간을 쓰고도 나쁜 결과를 얻을 때가 있고, 그냥 대충 던졌는데 좋은 결과가 나올 때도 있음. 프롬프트를 받는 도구 자체가 비결정적일 때, 프롬프트 엔지니어링에 정해진 전략을 옹호하기는 어려움
      그리고 예시들이 “나쁜 프롬프트에 대한 AI의 응답(시뮬레이션)”을 달고 있는 것도 웃김
  • 처음에는 모델이 충분히 좋지 않아서 내가 원하는 걸 못 준다고 계속 생각했음
    시간이 지나면서 진짜 문제는 내가 애초에 무엇을 원하는지 정리하지 못했다는 데 있다는 걸 깨달음. 먼저 내 생각을 명확히 하고, 그다음 AI가 그것을 정리하도록 해야 했음. 더 구체적이고 인내심 있게 요청할수록 더 잘 응답함