티스토리 뷰

반응형

Python으로 LangChain 첫 실행하기 — 설치부터 첫 번째 invoke, 그리고 PromptTemplate까지

지난 글에서는 “LangChain이 왜 필요한가”를 이야기했죠.
이번 글부터는 진짜 손을 움직여보겠습니다.

이런 말 좀 웃기긴 한데… 처음 LangChain 볼 때 제일 헷갈렸던 건 어려운 개념이 아니라 오히려 너무 기본적인 거였어요.
“그래서 뭘 설치해야 하지?”
“langchain만 깔면 되나?”
“모델은 어디서 붙이지?”
“공식 예제가 예전 거랑 지금 거랑 왜 다르게 보이지?”

이게 은근히 스트레스예요.
특히 주니어일수록요. 괜히 내가 못하는 것 같고, 시작부터 꼬인 느낌이 들거든요.

그래서 이번 글은 딱 여기까지만 갑니다.

  • LangChain 실행 환경 만들기
  • OpenAI 기준으로 첫 모델 호출하기
  • 문자열 prompt와 메시지 prompt 차이 보기
  • ChatPromptTemplate으로 프롬프트를 코드화하기

LangChain 공식 문서 기준으로, Python에서 채팅 모델을 가장 쉽게 시작하는 방법 중 하나는 init_chat_model을 쓰는 방식이고, OpenAI를 붙일 때는 langchain-openai 또는 langchain[openai] 설치 경로가 안내됩니다. 또 모델 호출은 invoke()로 시작하고, 단순 요청은 문자열 prompt, 대화형 맥락이 필요하면 메시지 리스트를 쓰는 방식으로 설명돼요. (LangChain Docs)


오늘 만들 결과물

오늘 끝나면 최소한 이 정도는 할 수 있게 됩니다.

  1. 내 PC에서 LangChain 코드가 실행된다
  2. 모델에게 질문을 보내고 답을 받는다
  3. 프롬프트를 하드코딩 문자열에서 템플릿 형태로 바꿀 수 있다

아직 RAG도 아니고 Agent도 아닙니다.
근데 이상하게 이 단계가 제일 중요해요.

왜냐면 여기서부터 앞으로 할 모든 게 갈라지거든요.
프롬프트 템플릿, 체인, 구조화 출력, 문서 검색, 툴 호출… 전부 결국 여기서 출발합니다.


1. 개발 환경 준비하기

이번 글은 Python 기준으로 진행하겠습니다.
가상환경을 쓰는 걸 추천해요. 프로젝트마다 패키지 버전이 달라질 수 있어서, 그냥 전역에 막 깔다 보면 나중에 진짜 귀찮아집니다.

macOS / Linux

mkdir langchain-basic
cd langchain-basic

python3 -m venv .venv
source .venv/bin/activate

pip install -U pip
pip install -U "langchain[openai]"

Windows PowerShell

mkdir langchain-basic
cd langchain-basic

python -m venv .venv
.venv\Scripts\Activate.ps1

python -m pip install -U pip
pip install -U "langchain[openai]"

LangChain 공식 문서의 models 가이드에서는 OpenAI용 시작 예시로 pip install -U "langchain[openai]"를 안내하고 있고, OpenAI 통합 문서에서는 langchain-openai 설치도 별도로 안내합니다. 둘 다 OpenAI 모델 사용을 위한 공식 경로입니다. (LangChain Docs)


2. API 키 설정하기

OpenAI를 예시로 쓸게요.
이미 OpenAI API 키가 있다면 환경변수에 넣어주면 됩니다.

macOS / Linux

export OPENAI_API_KEY="your_api_key_here"

Windows PowerShell

$env:OPENAI_API_KEY="your_api_key_here"

OpenAI 통합 문서도 OPENAI_API_KEY 환경변수를 설정하는 방식을 기본으로 안내합니다. 필요하면 LangSmith API 키를 추가해 트레이싱도 켤 수 있다고 되어 있어요. (LangChain Docs)

여기서 한 가지.
처음엔 .env 파일을 쓰고 싶을 수도 있는데, 이번 글에서는 일부러 안 넣겠습니다.

이유는 단순해요.
처음부터 한 번에 너무 많은 걸 넣으면 오히려 핵심이 흐려집니다.
오늘은 LangChain 호출이 실제로 되는지에만 집중할게요.


3. 가장 먼저 실행해볼 코드

파일 이름은 app.py로 하겠습니다.

import os
from langchain.chat_models import init_chat_model


def main() -> None:
    if not os.environ.get("OPENAI_API_KEY"):
        raise ValueError("OPENAI_API_KEY 환경변수가 설정되어 있지 않습니다.")

    model = init_chat_model("gpt-5-nano", model_provider="openai")

    response = model.invoke("LangChain이 무엇인지 주니어 개발자 눈높이로 3문장만 설명해줘.")
    print(response.content)


if __name__ == "__main__":
    main()

실행:

python app.py

LangChain 공식 models 문서에서는 init_chat_model()을 사용해 공급자별 채팅 모델을 초기화하는 방식을 소개하고 있고, invoke()가 가장 기본적인 호출 방식이라고 설명합니다. OpenAI 통합 문서 예시도 ChatOpenAI 인스턴스를 만든 뒤 응답을 생성하는 흐름을 보여줍니다. (LangChain Docs)


4. 코드가 왜 이렇게 생겼는지 하나씩 보기

처음 보는 사람 입장에서는 코드가 짧을수록 더 불안할 수 있어요.
“이게 진짜 다야?” 싶은 느낌.

근데 네, 시작은 이게 거의 다입니다.

init_chat_model

이 함수는 LangChain에서 채팅 모델을 통일된 인터페이스로 다루기 쉽게 만들어줍니다.
OpenAI든 Anthropic이든 Gemini든, 시작 방식의 감각을 어느 정도 비슷하게 가져갈 수 있어요. 공식 문서는 이 방식을 standalone model의 가장 쉬운 시작점으로 설명합니다. (LangChain Docs)

model_provider="openai"

지금은 OpenAI를 붙이겠다는 뜻입니다.
나중에는 이 부분을 바꿔서 다른 공급자로 확장할 수도 있어요.

invoke(...)

모델 실행입니다.
가장 단순한 형태에서는 문자열 하나를 넣으면 됩니다. 공식 messages 가이드도 “단일 독립 요청”에는 문자열 prompt가 적합하다고 설명합니다. (LangChain Docs)

response.content

모델 응답 객체에서 실제 텍스트 내용을 꺼내는 부분입니다.


5. 문자열 prompt와 메시지 prompt는 뭐가 다를까

반응형

처음에는 그냥 문자열 하나 넣는 게 편합니다.

response = model.invoke("봄을 주제로 한 짧은 문장을 2개 써줘.")
print(response.content)

이 방식은 아주 단순한 요청에는 충분해요.
LangChain 공식 messages 문서도 문자열 prompt는 단일 요청, 대화 히스토리 불필요, 최소한의 코드 복잡도에 적합하다고 설명합니다. (LangChain Docs)

그런데 조금만 지나면 이런 요구가 생깁니다.

  • 시스템 지시를 넣고 싶다
  • 이전 대화 맥락을 함께 전달하고 싶다
  • 사용자/AI 역할을 나눠서 관리하고 싶다

그럴 땐 메시지 형태가 더 자연스럽습니다.

from langchain.chat_models import init_chat_model
from langchain.messages import SystemMessage, HumanMessage

model = init_chat_model("gpt-5-nano", model_provider="openai")

messages = [
    SystemMessage("너는 친절한 Python 튜터다. 설명은 쉽게 하고, 예시는 짧게 들어라."),
    HumanMessage("for문을 주니어 개발자 눈높이로 설명해줘."),
]

response = model.invoke(messages)
print(response.content)

LangChain 공식 messages 문서는 메시지 리스트를 사용하면 시스템 지시, 멀티턴 대화, 멀티모달 입력 같은 상황을 다루기 좋다고 설명합니다. (LangChain Docs)

이 차이를 지금 당장 완벽하게 외울 필요는 없어요.
그냥 이렇게만 기억하면 됩니다.

  • 문자열 prompt: 한 번 물어보고 한 번 답받는 간단한 요청
  • 메시지 prompt: 역할과 문맥이 필요한 대화형 요청

6. 이제 PromptTemplate을 써보자

여기서부터 슬슬 LangChain다운 맛이 납니다.

처음엔 보통 이런 식으로 코드를 짜요.

topic = "LangChain"
level = "주니어 개발자"

prompt = f"{topic}을 {level} 눈높이로 설명해줘."
response = model.invoke(prompt)

이 코드가 틀린 건 아닙니다.
근데 프로젝트가 커질수록 정말 금방 지저분해져요.

  • 문자열 조합이 많아짐
  • 실수로 변수 빠뜨림
  • 프롬프트 재사용 어려움
  • 시스템 지시와 사용자 입력이 뒤섞임

이럴 때 ChatPromptTemplate이 들어옵니다.

import os
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate


def main() -> None:
    if not os.environ.get("OPENAI_API_KEY"):
        raise ValueError("OPENAI_API_KEY 환경변수가 설정되어 있지 않습니다.")

    model = init_chat_model("gpt-5-nano", model_provider="openai")

    prompt = ChatPromptTemplate.from_messages(
        [
            ("system", "너는 {target}를 가르치는 친절한 멘토다. 설명은 쉽고 실무적으로 해라."),
            ("human", "{topic}이 무엇인지 예시 1개와 함께 설명해줘."),
        ]
    )

    chain = prompt | model

    response = chain.invoke(
        {
            "target": "주니어 개발자",
            "topic": "LangChain",
        }
    )

    print(response.content)


if __name__ == "__main__":
    main()

LangChain 문서들에서는 ChatPromptTemplate을 이용해 시스템 메시지와 사용자 메시지를 템플릿화하고, prompt | llm 형태로 체인을 연결하는 예시를 반복적으로 보여줍니다. (LangChain Docs)


7. 여기서 처음 보는 | 는 뭐지?

처음 보면 좀 당황합니다.
파이썬 비트 연산자처럼 생겼으니까요.

근데 LangChain에서는 이게 꽤 중요한 감각이에요.

chain = prompt | model

이건 대충 이런 뜻입니다.

  1. 먼저 prompt가 입력값을 받아 메시지 형태로 만든다
  2. 그 결과를 model이 받아 응답을 생성한다

즉, 출력과 입력을 연결하는 파이프라인처럼 생각하면 됩니다.
이 감각이 나중에 LCEL, 파서, 리트리버, 후처리로 이어져요.

지금은 깊게 안 들어가겠습니다.
오늘은 “아, LangChain은 이런 식으로 흐름을 연결하는구나” 정도만 잡으면 충분해요.


8. 이번 글에서 꼭 체감해야 하는 포인트

오늘 코드 몇 줄 보면서 가장 중요한 건 사실 이것입니다.

첫째, LangChain은 “모델 호출”을 구조화하기 시작하는 지점이다

그냥 SDK 호출과 완전히 다른 세계는 아직 아니에요.
하지만 프롬프트 템플릿과 체인 개념이 들어오면서, 코드가 “확장 가능한 형태”가 됩니다.

둘째, 메시지 구조는 앞으로 계속 나온다

나중에 대화 기록, 시스템 프롬프트, RAG 문맥 주입, 툴 호출까지 가면 메시지 구조 이해가 필수예요.

셋째, PromptTemplate은 귀찮음을 줄이는 도구가 아니라 사고방식을 바꾸는 도구다

이거 좀 과장처럼 들릴 수 있는데 진짜 그래요.
프롬프트를 문자열이 아니라 입력값이 있는 구성요소로 보기 시작하면, 그때부터 서비스 코드처럼 보이기 시작합니다.


9. 실습할 때 자주 터지는 문제들

이건 미리 적어두는 게 좋겠어요.
처음 하면 거의 한 번씩은 겪습니다.

OPENAI_API_KEY 환경변수가 설정되어 있지 않습니다

가장 흔합니다.
터미널 세션에서 환경변수를 넣었는지 다시 확인하세요.

ModuleNotFoundError

가상환경이 활성화되지 않았거나 패키지 설치가 안 된 경우가 많아요.

모델 이름 오류

공급자 쪽에서 접근 가능한 모델 이름인지 확인해야 합니다.
공식 문서 예시는 시점에 따라 달라질 수 있으니, 사용 중인 공급자의 최신 모델명을 같이 확인하는 습관이 좋아요. LangChain 모델/통합 문서도 공급자별 모델과 추가 파라미터가 달라질 수 있다고 안내합니다. (LangChain Docs)

응답은 오는데 결과가 마음에 안 든다

아직 정상입니다.
지금 단계에서는 프롬프트를 더 잘 설계하는 연습이 필요해요.
이걸 다음 글에서 본격적으로 다룹니다.


10. 이번 글의 전체 예제 코드

복붙해서 한 파일로 실행할 수 있게 다시 정리해둘게요.

import os
from langchain.chat_models import init_chat_model
from langchain.messages import SystemMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate


def check_env() -> None:
    if not os.environ.get("OPENAI_API_KEY"):
        raise ValueError("OPENAI_API_KEY 환경변수가 설정되어 있지 않습니다.")


def run_simple_invoke() -> None:
    model = init_chat_model("gpt-5-nano", model_provider="openai")
    response = model.invoke("LangChain을 한 문단으로 쉽게 설명해줘.")
    print("=== simple invoke ===")
    print(response.content)
    print()


def run_message_invoke() -> None:
    model = init_chat_model("gpt-5-nano", model_provider="openai")
    messages = [
        SystemMessage("너는 친절한 백엔드 개발 멘토다."),
        HumanMessage("REST API를 주니어 개발자 눈높이로 설명해줘."),
    ]
    response = model.invoke(messages)
    print("=== message invoke ===")
    print(response.content)
    print()


def run_prompt_template() -> None:
    model = init_chat_model("gpt-5-nano", model_provider="openai")

    prompt = ChatPromptTemplate.from_messages(
        [
            ("system", "너는 {target}를 위한 친절한 AI 개발 멘토다."),
            ("human", "{topic}을 설명하고, 실무 예시를 1개 들어줘."),
        ]
    )

    chain = prompt | model

    response = chain.invoke(
        {
            "target": "주니어 개발자",
            "topic": "LangChain",
        }
    )

    print("=== prompt template chain ===")
    print(response.content)
    print()


def main() -> None:
    check_env()
    run_simple_invoke()
    run_message_invoke()
    run_prompt_template()


if __name__ == "__main__":
    main()

마무리

오늘은 진짜 기초였습니다.
그런데 이상하게 이런 기초가 제일 오래 갑니다.

저도 처음엔 “이런 건 너무 쉬운 거 아닌가?” 싶었는데,
나중에 RAG 만들고 Agent 붙이고 서비스화할 때 돌아보면 결국 여기였어요.

  • 모델을 어떻게 초기화하는지
  • 문자열과 메시지의 차이가 뭔지
  • 프롬프트를 어떻게 코드로 관리하는지

이 세 가지를 제대로 안 잡으면, 뒤로 갈수록 계속 흔들립니다.

그러니까 오늘 단계가 단순해 보여도 괜찮아요.
오히려 지금은 단순해야 합니다.
이걸 손에 익히는 게 먼저예요.


다음 글 예고

다음 글에서는
“PromptTemplate을 더 제대로 써보기 — 입력값 관리, 역할 분리, 재사용 가능한 프롬프트 만들기”
이 주제로 이어가겠습니다.

그때부터는 정말 “프롬프트를 코드처럼 다루는 감각”이 생기기 시작할 거예요.


출처

  • LangChain Models 공식 문서: init_chat_model()로 공급자별 채팅 모델을 초기화하고, invoke()를 기본 호출 방식으로 설명. (LangChain Docs)
  • LangChain OpenAI 통합 문서: langchain-openai 설치, OPENAI_API_KEY 설정, ChatOpenAI 인스턴스 생성 예시 제공. (LangChain Docs)
  • LangChain Messages 공식 문서: 문자열 prompt와 메시지 리스트 사용 구분, SystemMessage/HumanMessage 예시 제공. (LangChain Docs)
  • LangChain 공식 문서의 prompt/chaining 예시: ChatPromptTemplate과 prompt | model 형태의 체인 예시 제공. (LangChain Docs)


LangChain, LangChain Python, PromptTemplate, ChatPromptTemplate, 생성형AI, LLM, OpenAI API, AI개발입문, 주니어개발자, Python튜토리얼

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함
반응형