f-string 프롬프트로 도배했다가 후회한 날 — Prompt Template 이야기

Step-by-step infographic on understanding, filling variables, optimizing, and applying prompt templates

f-string 프롬프트로 도배했다가 후회한 날 — Prompt Template 이야기

처음 LLM 서비스를 짤 때 저는 프롬프트를 전부 f-string으로 박아 넣었습니다. “그냥 문자열인데 뭐” 하고요. 기능이 대여섯 개로 늘어나자 같은 말투 지시(“친절하게, 존댓말로”)가 여기저기 복붙돼 있었고, 톤을 한 번 바꾸려면 파일을 열 개씩 뒤져야 했습니다. Prompt Template은 이 “프롬프트 관리 지옥”에서 저를 꺼내준 기능이라 애정이 좀 있습니다.

템플릿이 뭘 해결해 주나

핵심은 단순합니다. 고정된 틀은 한 곳에 두고, 바뀌는 값만 변수로 꽂는 거예요. HTML 템플릿과 발상이 똑같습니다. 아래처럼요.

from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "너는 {role}야. 항상 존댓말로 답해."),
    ("human", "{topic} 를 초보자 눈높이로 설명해줘"),
])

msg = prompt.format_messages(role="IT 강사", topic="벡터 DB")
for m in msg:
    print(m.type, ":", m.content)

말투 지시를 system 한 곳에만 두니, 톤을 바꿀 때 여기 한 줄만 고치면 전체가 따라옵니다. 복붙 지옥이 사라진 순간이었습니다.

제가 실제로 밟은 지뢰: 중괄호

가장 많이 당한 실수가 이겁니다. 프롬프트 안에 JSON 예시를 넣으려고 {"name": "..."}를 그대로 썼더니 KeyError가 터졌어요. 템플릿은 {}를 변수로 해석하기 때문입니다. 리터럴 중괄호를 넣으려면 {{ }}로 두 번 써야 합니다. 이거 몰라서 30분을 날렸습니다. 문서엔 한 줄 있는데, 막상 처음 겪으면 원인을 못 찾더라고요.

실무 팁: partial로 반복 값 고정

매번 안 바뀌는 값(예: 오늘 날짜, 회사명)은 prompt.partial(company="...")로 미리 채워두면 호출부가 깔끔해집니다. 저는 시스템 지시를 partial로 고정하고, 사용자 입력만 invoke에 넘기는 식으로 정리했더니 코드가 훨씬 읽기 쉬워졌어요.

정리하며

Prompt Template은 화려한 기능이 아니라 “프롬프트도 코드처럼 관리하자”는 습관에 가깝습니다. 저처럼 f-string으로 도배했다가 나중에 우는 일을 피하려면, 프롬프트가 서너 개를 넘어가는 순간 바로 템플릿으로 옮기시길 권합니다. 다음 글에서는 이렇게 만든 응답을 프로그램이 쓰기 좋은 JSON으로 바꾸는 Output Parser를, 제가 파싱 에러로 고생한 사례와 함께 다뤄보겠습니다.

댓글 남기기

How are you? good!에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기