4.1 메시지 역할 구조: system, user, assistant

OpenAI의 Chat Completions API는 전통적인 단일 Prompt-Response 방식과는 달리, "대화형" 문맥을 반영할 수 있는 메시지 배열(messages array) 구조를 채택하고 있습니다. 이 구조는 하나의 메시지(message)가 특정한 역할(role)을 기반으로 작성되어야 하고, 이러한 메시지가 시간 순으로 배열되어 전체 대화 문맥을 구성합니다.

각 message 객체는 다음과 같은 기본 형식을 갖습니다:

{
  "role": "user",
  "content": "파이썬에서 리스트와 튜플의 차이는 무엇인가요?"
}

role 필드는 다음 세 가지 중 하나를 갖게 됩니다:

  • system

  • user

  • assistant

이 절에서는 각 역할의 목적, 특징, 사용하는 이유, 그리고 실전에서의 예시까지 상세히 다룰 것입니다.

4.1.1 system 역할

System 메시지는 대화의 "시작 지점"에서 LLM의 동작 범위, 성격, 스타일 등을 지시하는 특별한 목적의 메시지입니다. 이 메시지는 모델에게 일종의 초기 상태, 즉 '페르소나(persona)'와 '행동 가이드라인'을 설정해줍니다.

특징

  • 대화의 흐름보다 '방향'을 정한다.

  • 반드시 첫 메시지일 필요는 없지만, 첫 메시지에 두는 것이 일반적이다.

  • 주로 system prompt라고 부른다.

  • 모델에게 직접 출력을 유도하는 내용은 포함하지 않는 것이 일반적이다.

예시 1: 도움말 챗봇

{
  "role": "system",
  "content": "당신은 친절하고 정중하게 행동하는 고객지원 AI입니다. 대화는 한국어로 진행됩니다."
}

이 프롬프트를 통해 모델은 "고객지원", "친절", "정중함", "한국어 사용"이라는 행동 규칙을 내면화하게 됩니다.

예시 2: 전문가 에이전트

{
  "role": "system",
  "content": "너는 10년 이상 경력을 가진 데이터 과학자이며, 초보 개발자의 질문에 친절히 조언하는 역할을 한다. 답변은 항상 예시 코드를 포함해라."
}

모델이 출력 콘텐츠를 구성할 때, 누가 말하고 어떤 톤으로 말해야 하는지를 이 프롬프트에서 설정합니다.

Best Practice

  • 인격적 묘사(persona), 지식 수준, 말투(tone), 언어 제약 등을 기술하라.

  • "스토리텔링 대신 요점을 간결히 말해 줘", "응답에는 반드시 마크다운 형식을 사용해" 등도 system 메시지에 적합.

4.1.2 user 역할

User 메시지는 실제 사용자의 질문이나 요청을 표현합니다. 이 메시지는 가장 직관적인 채널로 작동하며, 우리의 질문, 입력 데이터, 지시문 등을 전달하는 데 사용됩니다.

특징

  • 질문, 명령, 데이터 입력 등 다양하게 사용됨.

  • 모델이 현재 대화 흐름의 중심 콘텐츠를 생성하는 데 사용함.

  • 여러 개의 user 메시지를 순차적으로 추가할 수 있음.

예시 1: 질문

{
  "role": "user",
  "content": "엑셀에서 피벗 테이블을 어떻게 만들 수 있나요?"
}

예시 2: 지시 및 예제 입력

{
  "role": "user",
  "content": "다음 문장을 영어로 번역해 줘: '오늘 날씨가 정말 좋아요.'"
}

예시 3: 대화 이어가기

{
  "role": "user",
  "content": "좋아요, 그러면 JSON 형식으로 표현해 줄 수 있나요?"
}

이와 같이 user 메시지는 대화의 목적을 주도하며, 흐름을 결정합니다.

4.1.3 assistant 역할

Assistant 메시지는 앞서 있었던 prompt들(user/system)에 대한 모델의 응답을 구성하며, 종종 대화 상태를 유지하기 위해 히스토리의 일부로 저장됩니다.

특징

  • 모델이 생성한 응답을 포함한다.

  • 이전 message의 context 처리를 위해 대화의 연속성 유지를 돕는다.

  • 다음 API 호출에서는 assistant 메시지를 포함시켜야 문맥이 이어짐.

예시 1: 일반 응답

{
  "role": "assistant",
  "content": "피벗 테이블을 만들려면 우선 데이터를 선택한 후, '삽입 > 피벗 테이블' 메뉴로 가세요. 그 다음..."
}

예시 2: 중립적 발화

{
  "role": "assistant",
  "content": "물론이죠. 다음과 같이 JSON 형식을 사용할 수 있습니다:"
}

히스토리 활용: 문맥 유지 필수

다음과 같은 대화 흐름을 상상해보십시오:

[
  {"role": "system", "content": "너는 프로그래밍 질문에 답하는 어시스턴트야."},
  {"role": "user", "content": "클로저가 뭔가요?"},
  {"role": "assistant", "content": "클로저는 함수와 그 함수가 선언될 때의 렉시컬 환경의 조합입니다..."},
  {"role": "user", "content": "좀 더 쉬운 예로 설명해 줄래요?"}
]

이 때 모델은 위의 문맥을 파악해야 정확한 응답을 할 수 있습니다. 여기서 assistant 메시지는 단순한 출력이 아니라 ‘문맥의 일부’로 중요한 역할을 합니다.

Tip: 역할(role)은 출력의 품질에 영향을 준다

특히 system 메시지를 적절하게 사용할 경우, 다음과 같은 장점이 있습니다:

  • model의 답변 스타일을 통일시킬 수 있음

  • 대화의 방향성이 일관되게 유지됨

  • 오류 가능성을 줄이고, 사용자 경험 향상

전체 예시: 간단한 FAQ 챗봇 대화 구조

[
  {
    "role": "system",
    "content": "너는 정확하고 간결한 설명을 제공하는 IT 전문가야. 모든 대화는 한국어로 진행돼."
  },
  {
    "role": "user",
    "content": "Python의 리스트와 튜플은 어떻게 다른가요?"
  },
  {
    "role": "assistant",
    "content": "리스트는 변경 가능한(mutable) 시퀀스형이고, 튜플은 변경 불가능한(immutable) 시퀀스형입니다..."
  },
  {
    "role": "user",
    "content": "한 줄 요약해 줄 수 있나요?"
  }
]

위처럼 각 메시지에 역할을 명확히 설정하면, OpenAI 모델은 더 정확하고 일관된 대화를 생성할 수 있습니다.

정리: 메시지 역할 요약 표

역할(Role)
설명
사용 시기

system

모델의 행동, 스타일, 언어 등을 정의하는 초기 설정 프롬프트

대화 시작 전 또는 주요 변환 시점

user

사용자의 질문, 요청, 명령 등을 전달

평상시 입력

assistant

모델의 출력을 나타냄

응답 저장 및 문맥 연결 시

OpenAI의 Chat Completions API를 사용할 때, 이 역할 구조를 정확히 이해하고 적절히 활용하면 더 강력하고 똑똑한 대화형 AI 애플리케이션을 만들 수 있습니다. 다음 절에서는 이러한 구조를 활용하여 다양한 목적에 따라 프롬프트를 어떻게 최적화할 수 있는지를 다루게 됩니다.

Last updated