작성일 댓글 남기기

AI 에이전트 직접 만들기 – LangGraph·CrewAI 입문 실전 가이드

AI 에이전트가 여러 작업을 자동 처리하는 모습

AI 챗봇을 넘어, 스스로 판단하고 행동하는 AI 에이전트의 시대

2025년까지 우리가 주로 사용한 AI는 ‘질문하면 답하는’ 챗봇 형태였습니다. ChatGPT에 질문을 던지고, 답변을 복사해서 다른 곳에 붙여넣는 식이었죠. 하지만 2026년 현재, AI 기술의 화두는 완전히 달라졌습니다. 바로 AI 에이전트(AI Agent)입니다.

AI 에이전트란 단순히 한 번 답변하고 끝나는 것이 아니라, 주어진 목표를 달성하기 위해 스스로 계획을 세우고, 도구를 사용하고, 중간 결과를 평가하며, 필요하면 방향을 수정하는 자율적인 AI 시스템을 말합니다. 예를 들어 “이번 주 기술 뉴스를 수집해서 요약 리포트를 만들어 이메일로 보내줘”라고 지시하면, 에이전트가 웹 검색 → 내용 분석 → 요약 작성 → 이메일 발송까지 알아서 처리하는 것이죠.

이런 AI 에이전트를 직접 만들 수 있는 오픈소스 프레임워크가 이미 여러 개 나와 있고, Python만 조금 다룰 줄 알면 누구나 시작할 수 있습니다. 이 글에서는 2026년 현재 가장 널리 쓰이는 두 프레임워크인 LangGraphCrewAI를 중심으로, AI 에이전트의 핵심 개념부터 직접 만들어보는 과정까지 실전 위주로 안내하겠습니다.

AI 에이전트 핵심 구성요소 4가지 다이어그램

AI 에이전트, 정확히 뭐가 다른 걸까?

챗봇과 에이전트의 결정적 차이

일반 AI 챗봇과 AI 에이전트의 차이를 이해하는 것이 출발점입니다. 챗봇은 한 번의 입력에 한 번의 출력을 내는 단순한 구조입니다. 반면 에이전트는 다단계 추론(Multi-step Reasoning)을 수행합니다.

  • 챗봇: 사용자 질문 → LLM 응답 → 끝. 맥락 유지는 대화 기록에 의존합니다.
  • 에이전트: 사용자 목표 → 계획 수립 → 도구 호출(검색, API, 코드 실행 등) → 중간 결과 평가 → 필요시 재계획 → 최종 결과 도출. 하나의 목표를 위해 여러 단계를 자율적으로 반복합니다.

핵심은 루프(Loop)입니다. 에이전트는 “아직 목표를 달성하지 못했으니 다른 방법을 시도해보자”라는 판단을 스스로 내릴 수 있습니다. 이것이 단순 챗봇과의 가장 큰 차이점이죠.

에이전트의 핵심 구성 요소 4가지

어떤 프레임워크를 사용하든 AI 에이전트는 다음 네 가지 요소로 구성됩니다.

  • LLM (대규모 언어 모델): 에이전트의 두뇌입니다. GPT-4o, Claude, Gemini 등 원하는 모델을 선택할 수 있습니다.
  • 도구(Tools): 에이전트가 외부 세계와 상호작용하는 수단입니다. 웹 검색, 파일 읽기/쓰기, API 호출, 데이터베이스 쿼리, 코드 실행 등 다양한 도구를 장착할 수 있습니다.
  • 메모리(Memory): 단기 메모리(현재 작업의 중간 결과)와 장기 메모리(이전 작업에서 학습한 정보)를 관리합니다. 이를 통해 에이전트는 맥락을 유지하고 과거 경험을 활용합니다.
  • 계획 및 추론(Planning & Reasoning): 목표를 하위 작업으로 분해하고, 어떤 순서로 어떤 도구를 사용할지 결정하는 능력입니다. ReAct(Reasoning + Acting) 패턴이 가장 대표적입니다.

ReAct 패턴이란?

ReAct는 현재 AI 에이전트에서 가장 보편적으로 사용되는 추론 패턴입니다. 이름 그대로 Reasoning(추론)Acting(행동)을 번갈아 수행합니다.

  • Thought(생각): “지금 상황에서 무엇을 해야 할까?” — LLM이 현재 상태를 분석합니다.
  • Action(행동): “웹에서 최신 정보를 검색하자” — 적절한 도구를 선택하고 실행합니다.
  • Observation(관찰): “검색 결과가 이렇게 나왔구나” — 도구 실행 결과를 확인합니다.
  • 이 세 단계를 목표 달성까지 반복합니다.

이 패턴 덕분에 에이전트는 한 번에 완벽한 답을 내지 못하더라도, 시행착오를 거치며 점진적으로 목표에 도달할 수 있습니다.

프레임워크 선택: LangGraph vs CrewAI

AI 에이전트를 만들 수 있는 프레임워크는 여러 가지가 있지만, 2026년 현재 실전에서 가장 활발히 쓰이는 것은 LangGraphCrewAI 두 가지입니다. 각각의 철학과 장단점이 뚜렷하므로, 자신의 목적에 맞는 것을 고르는 것이 중요합니다.

LangGraph와 CrewAI 프레임워크 비교표

LangGraph — 정밀한 워크플로우 제어가 필요할 때

LangGraph는 LangChain 팀에서 만든 에이전트 프레임워크로, 그래프(Graph) 기반의 상태 머신으로 에이전트의 동작 흐름을 정의합니다. 노드(Node)는 각 단계의 작업을, 엣지(Edge)는 단계 간 전환 조건을 나타냅니다.

  • 장점: 워크플로우를 세밀하게 제어할 수 있습니다. 조건 분기, 병렬 처리, 인간 승인 단계(Human-in-the-Loop) 삽입 등 복잡한 로직을 시각적으로 설계할 수 있습니다. 상태(State)를 명시적으로 관리하므로 디버깅이 수월합니다.
  • 장점: LangChain 생태계의 수백 가지 도구 통합(Tool Integration)을 그대로 활용할 수 있습니다.
  • 장점: 체크포인트(Checkpoint) 기능으로 긴 작업의 중간 상태를 저장하고 복구할 수 있습니다.
  • 단점: 러닝 커브가 상대적으로 높습니다. 그래프 구조, 상태 스키마, 엣지 조건 등을 직접 정의해야 하므로 초반 셋업 코드가 깁니다.
  • 적합한 경우: 정교한 제어가 필요한 프로덕션급 에이전트, 조건 분기가 복잡한 워크플로우, 에이전트 동작을 완전히 이해하고 커스터마이징하고 싶을 때.

CrewAI — 빠르게 멀티 에이전트를 조합하고 싶을 때

CrewAI는 역할 기반(Role-based) 접근법을 취합니다. 여러 에이전트에게 각각 다른 역할(예: 리서처, 작가, 편집자)을 부여하고, 이들이 팀처럼 협업하여 작업을 수행합니다.

  • 장점: 직관적인 API로 빠르게 시작할 수 있습니다. Agent, Task, Crew 세 가지 개념만 이해하면 됩니다.
  • 장점: 멀티 에이전트 협업이 기본 설계에 포함되어 있어, 여러 전문가 에이전트를 조합하는 것이 자연스럽습니다.
  • 장점: 순차(Sequential) 또는 계층(Hierarchical) 실행 모드를 선택할 수 있고, 에이전트 간 결과 전달이 자동으로 처리됩니다.
  • 단점: LangGraph 대비 세밀한 흐름 제어가 어렵습니다. 복잡한 조건 분기나 반복 루프를 넣으려면 추가 작업이 필요합니다.
  • 적합한 경우: 빠른 프로토타이핑, 역할 분담이 명확한 멀티 에이전트 시나리오, 에이전트 개발을 처음 시작하는 분.

어떤 걸 선택해야 할까?

입문자라면 CrewAI로 시작하는 것을 추천합니다. 개념이 직관적이고, 적은 코드로 동작하는 에이전트를 빠르게 만들어볼 수 있습니다. 이후 더 정밀한 제어가 필요해지면 LangGraph로 넘어가도 됩니다. 두 프레임워크 모두 Python 기반이고, OpenAI나 Anthropic 등 주요 LLM API를 지원하므로 전환 비용이 크지 않습니다.

실전 1: CrewAI로 뉴스 리서치 에이전트 만들기

이론은 충분합니다. 이제 직접 만들어봅시다. 첫 번째 실전 예제로 CrewAI를 사용해 특정 주제의 최신 뉴스를 검색하고 요약 리포트를 작성하는 에이전트를 만들어보겠습니다.

사전 준비

Python 3.10 이상이 설치되어 있어야 합니다. 그리고 OpenAI API 키가 필요합니다(Claude API도 사용 가능하지만, CrewAI는 기본적으로 OpenAI를 가장 잘 지원합니다).

먼저 필요한 패키지를 설치합니다.

pip install crewai crewai-tools

환경 변수로 API 키를 설정합니다.

export OPENAI_API_KEY="your-api-key-here"

프로젝트 구조

간단한 단일 파일로 시작하겠습니다. news_crew.py 파일을 만듭니다.

from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool

# 검색 도구 준비 (Serper API 키 필요)
search_tool = SerperDevTool()

# 1단계: 에이전트 정의
researcher = Agent(
    role="기술 뉴스 리서처",
    goal="주어진 주제에 대한 최신 뉴스와 동향을 철저히 조사한다",
    backstory="""당신은 10년 경력의 IT 전문 기자입니다.
    정확한 팩트 체크와 핵심 트렌드 파악에 뛰어납니다.
    항상 1차 출처를 확인하고, 신뢰할 수 있는 정보만 수집합니다.""",
    tools=[search_tool],
    verbose=True
)

writer = Agent(
    role="기술 콘텐츠 작가",
    goal="리서치 결과를 바탕으로 읽기 쉽고 유익한 요약 리포트를 작성한다",
    backstory="""당신은 복잡한 기술 내용을 일반인도 이해할 수 있게
    풀어쓰는 능력이 뛰어난 테크 블로거입니다.
    항상 독자의 관점에서 '왜 이것이 중요한지'를 설명합니다.""",
    verbose=True
)

# 2단계: 태스크 정의
research_task = Task(
    description="""2026년 5월 기준 AI 에이전트 기술의 최신 동향을 조사하세요.
    - 주요 프레임워크 업데이트
    - 기업 도입 사례
    - 새로운 기술적 돌파구
    최소 5개 이상의 출처에서 정보를 수집하세요.""",
    expected_output="주요 뉴스 항목별 제목, 출처, 핵심 내용을 포함한 리서치 노트",
    agent=researcher
)

write_task = Task(
    description="""리서치 결과를 바탕으로 한국어 요약 리포트를 작성하세요.
    - 핵심 트렌드 3-5개를 선별
    - 각 트렌드별 의미와 시사점 설명
    - 전체 1000자 내외로 간결하게 정리""",
    expected_output="마크다운 형식의 한국어 요약 리포트",
    agent=writer
)

# 3단계: 크루 조합 및 실행
crew = Crew(
    agents=[researcher, writer],
    tasks=[research_task, write_task],
    process=Process.sequential,  # 순차 실행: 리서치 → 작성
    verbose=True
)

result = crew.kickoff()
print(result)

코드 핵심 포인트 해설

Agent 정의에서 backstory가 중요한 이유: backstory는 단순한 설명이 아닙니다. LLM이 해당 역할을 수행할 때의 페르소나를 결정합니다. “10년 경력의 IT 전문 기자”라고 설정하면, 모델은 실제로 더 전문적이고 체계적인 리서치 패턴을 보입니다. backstory를 구체적으로 작성할수록 에이전트의 출력 품질이 올라갑니다.

Task의 expected_output: 이 필드는 에이전트가 “언제 작업이 완료되었는지”를 판단하는 기준이 됩니다. 모호하게 적으면 에이전트가 불필요하게 반복하거나 너무 일찍 종료할 수 있으므로, 원하는 결과물의 형태를 구체적으로 명시하는 것이 좋습니다.

Process.sequential: 태스크를 순서대로 실행하며, 이전 태스크의 결과가 다음 태스크의 입력으로 자동 전달됩니다. 이 외에 Process.hierarchical 모드도 있는데, 이 경우 매니저 에이전트가 자동으로 생성되어 작업 분배를 관리합니다.

실행 결과 살펴보기

위 코드를 실행하면 터미널에 에이전트의 사고 과정이 실시간으로 출력됩니다. 리서처 에이전트가 검색 도구를 여러 번 호출하며 정보를 수집하고, 그 결과를 작가 에이전트가 받아서 리포트를 작성하는 전체 과정을 관찰할 수 있습니다. 이 verbose 출력을 통해 에이전트가 어떤 판단을 내리고 있는지 이해하고, 필요하면 프롬프트나 도구를 조정할 수 있습니다.

실전 2: LangGraph로 조건 분기가 있는 에이전트 만들기

CrewAI가 직관적인 팀 편성에 강했다면, LangGraph는 복잡한 조건 분기와 반복 루프를 정밀하게 제어하는 데 강합니다. 두 번째 예제로 사용자 질문의 유형을 판별하여 다른 처리 경로로 분기하는 에이전트를 만들어보겠습니다.

사전 준비

pip install langgraph langchain-openai langchain-community

그래프 기반 에이전트 구현

from typing import TypedDict, Literal
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI

# 상태 스키마 정의
class AgentState(TypedDict):
    question: str
    category: str
    answer: str

llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 노드 1: 질문 분류
def classify_question(state: AgentState) -> AgentState:
    response = llm.invoke(
        f"""다음 질문을 'technical', 'general', 'creative' 중 하나로 분류하세요.
        질문: {state['question']}
        카테고리만 한 단어로 답하세요."""
    )
    return {"category": response.content.strip().lower()}

# 노드 2a: 기술 질문 처리
def handle_technical(state: AgentState) -> AgentState:
    response = llm.invoke(
        f"""당신은 시니어 소프트웨어 엔지니어입니다.
        다음 기술 질문에 코드 예제를 포함하여 상세히 답하세요.
        질문: {state['question']}"""
    )
    return {"answer": response.content}

# 노드 2b: 일반 질문 처리
def handle_general(state: AgentState) -> AgentState:
    response = llm.invoke(
        f"""친근하고 알기 쉬운 문체로 다음 질문에 답하세요.
        질문: {state['question']}"""
    )
    return {"answer": response.content}

# 노드 2c: 창의적 질문 처리
def handle_creative(state: AgentState) -> AgentState:
    response = llm.invoke(
        f"""당신은 창의적인 작가입니다.
        다음 질문에 상상력을 발휘하여 재미있게 답하세요.
        질문: {state['question']}"""
    )
    return {"answer": response.content}

# 조건 분기 함수
def route_by_category(state: AgentState) -> Literal["technical", "general", "creative"]:
    return state["category"]

# 그래프 구성
workflow = StateGraph(AgentState)

# 노드 추가
workflow.add_node("classify", classify_question)
workflow.add_node("technical", handle_technical)
workflow.add_node("general", handle_general)
workflow.add_node("creative", handle_creative)

# 엣지 연결
workflow.set_entry_point("classify")
workflow.add_conditional_edges(
    "classify",
    route_by_category,
    {
        "technical": "technical",
        "general": "general",
        "creative": "creative"
    }
)
workflow.add_edge("technical", END)
workflow.add_edge("general", END)
workflow.add_edge("creative", END)

# 컴파일 및 실행
app = workflow.compile()

result = app.invoke({
    "question": "Python에서 비동기 프로그래밍을 시작하려면 어떻게 해야 하나요?"
})
print(result["answer"])

코드 핵심 포인트 해설

StateGraph와 상태 스키마: LangGraph의 핵심은 상태(State)입니다. AgentState라는 TypedDict로 에이전트가 다루는 모든 데이터를 명시적으로 정의합니다. 각 노드는 현재 상태를 받아서 수정된 상태를 반환하는 순수 함수입니다. 이 구조 덕분에 디버깅이 쉽고, 각 단계에서 상태가 어떻게 변하는지 추적할 수 있습니다.

조건 분기(Conditional Edges): add_conditional_edges는 LangGraph의 핵심 기능입니다. 현재 상태를 보고 다음에 어떤 노드로 이동할지 동적으로 결정합니다. 위 예제에서는 질문 카테고리에 따라 서로 다른 전문가 노드로 분기합니다. 이것이 단순한 선형 파이프라인과의 결정적 차이입니다.

컴파일과 실행: workflow.compile()으로 그래프를 실행 가능한 앱으로 변환합니다. 이 앱은 일반 함수처럼 invoke()로 호출할 수 있고, stream()으로 각 노드의 출력을 스트리밍으로 받을 수도 있습니다.

LangGraph 조건 분기 워크플로우 다이어그램

에이전트를 더 똑똑하게 만드는 실전 팁

1. 도구(Tool)를 잘 설계하는 것이 핵심

에이전트의 능력은 장착한 도구의 품질에 직결됩니다. 도구를 만들 때 지켜야 할 원칙이 있습니다.

  • 이름을 명확하게 지으세요: 에이전트(LLM)는 도구의 이름과 설명을 보고 어떤 도구를 사용할지 결정합니다. search보다 search_recent_tech_news가 훨씬 정확한 선택을 유도합니다.
  • 설명(description)에 사용 조건을 명시하세요: “이 도구는 최근 7일 이내의 뉴스만 검색합니다” 같은 제약 조건을 적어두면 에이전트가 더 적절한 상황에서 도구를 사용합니다.
  • 에러 처리를 도구 안에 넣으세요: 도구가 실패했을 때 에러 메시지를 에이전트가 이해할 수 있는 형태로 반환하면, 에이전트가 알아서 대안을 찾습니다. 예를 들어 “검색 결과가 없습니다. 다른 키워드로 시도해보세요.”라고 반환하면 됩니다.

2. 가드레일(Guardrails)을 설정하세요

AI 에이전트는 자율적으로 동작하므로, 의도하지 않은 행동을 할 수 있습니다. 반드시 안전장치를 마련해야 합니다.

  • 최대 반복 횟수 제한: 에이전트가 무한 루프에 빠지지 않도록 max_iterations를 설정합니다. CrewAI는 max_iter 파라미터로, LangGraph는 recursion_limit으로 제한할 수 있습니다.
  • 비용 제한: API 호출 횟수나 토큰 사용량에 상한을 두세요. 특히 개발 단계에서 에이전트가 불필요하게 도구를 반복 호출하면 비용이 급증할 수 있습니다.
  • Human-in-the-Loop: 중요한 의사결정(이메일 발송, 파일 삭제 등) 전에 사람의 승인을 받도록 설정할 수 있습니다. LangGraph는 이 기능을 기본으로 지원합니다.

3. 프롬프트 최적화 전략

에이전트의 성능은 결국 프롬프트의 품질에 좌우됩니다. 몇 가지 검증된 전략을 소개합니다.

  • 역할과 제약 조건을 분리하세요: “당신은 ~입니다”(역할)와 “~하지 마세요”(제약)를 명확히 구분하여 작성하면 에이전트가 지시를 더 잘 따릅니다.
  • 출력 형식을 지정하세요: 에이전트의 중간 결과물 형식을 JSON이나 마크다운 등으로 고정하면, 다음 단계에서의 파싱이 안정적으로 됩니다.
  • Few-shot 예시를 활용하세요: 원하는 동작의 예시를 1~2개 포함하면 에이전트의 행동 패턴이 훨씬 일관됩니다.

4. 디버깅과 관찰성(Observability)

에이전트가 복잡해질수록 무엇이 잘못되었는지 파악하기 어렵습니다. 다음 도구들이 디버깅에 도움이 됩니다.

  • LangSmith: LangChain/LangGraph와 통합되는 관찰성 플랫폼입니다. 에이전트의 각 단계별 입출력, 토큰 사용량, 지연 시간을 시각적으로 추적할 수 있습니다.
  • verbose 모드 활용: CrewAI와 LangGraph 모두 verbose 옵션을 켜면 에이전트의 사고 과정을 실시간으로 확인할 수 있습니다. 개발 중에는 항상 켜두세요.
  • 단계별 테스트: 전체 워크플로우를 한 번에 테스트하지 말고, 각 노드/에이전트를 개별적으로 테스트한 후 조합하세요.

실전 활용 아이디어: 일상에서 쓸 수 있는 에이전트

AI 에이전트는 거창한 프로젝트에만 쓰는 것이 아닙니다. 개인의 일상에서도 유용하게 활용할 수 있습니다.

  • 주간 기술 뉴스 큐레이터: 관심 키워드의 최신 기사를 자동으로 수집·요약하여 매주 월요일 아침 이메일이나 텔레그램으로 전송합니다.
  • 블로그 초안 작성 어시스턴트: 주제 키워드를 입력하면 관련 자료를 검색하고, SEO를 고려한 글 구조를 잡아주며, 초안을 작성해주는 에이전트입니다.
  • 코드 리뷰 에이전트: GitHub에 PR이 올라오면 자동으로 코드를 분석하고, 버그 가능성·보안 이슈·성능 개선점을 코멘트로 달아주는 에이전트입니다.
  • 가계부 분석 에이전트: 은행 거래 내역 CSV를 읽고, 카테고리별 지출을 분석하여 절약 포인트를 찾아주는 에이전트입니다.
  • 여행 계획 에이전트: 예산, 기간, 선호도를 입력하면 항공편·숙소·관광지를 검색하고 최적 일정을 짜주는 에이전트입니다.

위 아이디어들은 모두 CrewAI나 LangGraph로 구현 가능하며, 검색 도구, 파일 읽기 도구, API 호출 도구 등을 조합하면 됩니다. 처음에는 간단한 것부터 시작하고, 점차 도구와 에이전트를 추가해가면 자연스럽게 실력이 늘어납니다.

시작하기 전에 알아두면 좋은 현실적인 조언

AI 에이전트는 분명 강력한 기술이지만, 몇 가지 현실적인 제약도 알아둬야 합니다.

첫째, 비용을 주시하세요. 에이전트는 내부적으로 LLM API를 여러 번 호출합니다. 간단한 에이전트도 한 번 실행에 GPT-4o 기준 수천~수만 토큰을 소비할 수 있습니다. 개발 단계에서는 더 저렴한 모델(GPT-4o-mini, Claude Haiku 등)로 테스트하고, 프로덕션에서만 고성능 모델을 사용하는 전략이 현명합니다.

둘째, 환각(Hallucination)에 대비하세요. 에이전트가 도구를 사용하더라도 LLM의 본질적인 한계인 환각은 여전히 존재합니다. 특히 검색 결과를 요약할 때 없는 내용을 추가하거나, 날짜·수치를 잘못 인용하는 경우가 있습니다. 중요한 결과물은 반드시 사람이 검증하는 단계를 포함하세요.

셋째, 작게 시작하세요. 처음부터 10개의 도구를 장착한 5명의 에이전트를 만들려고 하지 마세요. 도구 1개, 에이전트 1개로 시작하여 동작을 확인한 뒤 점진적으로 확장하는 것이 디버깅도 쉽고 결과도 좋습니다.

넷째, 에이전트가 꼭 필요한지 먼저 판단하세요. 단순한 API 호출 체인이면 에이전트 없이 일반 코드로 충분합니다. 에이전트는 동적 판단과 분기가 필요한 상황에서 진가를 발휘합니다. “이 작업에 사람의 판단이 매번 개입해야 하는가?”라는 질문에 “예”라고 답할 수 있을 때, 에이전트 도입을 고려하세요.

마무리: AI 에이전트, 지금이 시작하기 가장 좋은 타이밍

2026년은 AI 에이전트 기술이 초기 실험 단계를 지나 실용적인 성숙기에 접어든 시점입니다. CrewAI와 LangGraph 같은 프레임워크가 안정화되었고, LLM의 도구 사용 능력이 비약적으로 향상되었으며, 커뮤니티와 학습 자료도 풍부해졌습니다.

이 글에서 소개한 두 가지 프레임워크와 코드 예제를 직접 실행해보면서, 자신만의 자동화 시나리오를 하나씩 만들어보시길 권합니다. 처음에는 “이런 것까지 AI가 할 수 있어?”라는 놀라움이, 곧 “이걸 왜 지금까지 손으로 했지?”라는 깨달음으로 바뀔 것입니다.

다음 단계로는 MCP(Model Context Protocol)를 활용해 에이전트에 더 다양한 도구를 연결하거나, n8n 같은 워크플로우 자동화 플랫폼과 결합해 24시간 자동 실행되는 시스템을 구축해볼 수 있습니다. 한 걸음씩, 자신의 반복 업무를 AI 에이전트에게 넘겨보세요.

이미지는 Leonardo AI 로 생성되었습니다.

이미지는 Claude AI 로 생성되었습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다