
AI를 공부한다고 하면 보통 프롬프트 엔지니어링, RAG, 파인튜닝 같은 키워드부터 떠올리기 쉽다.
하지만 그 전에 가장 기본적으로 해야할 것이 있다.
AI에게 말을 걸 수 있어야 한다.
오늘은 복잡한 이론이나 구조 이야기는 잠시 미뤄두고,
OpenAI API를 이용해 원하는 LLM 모델에 프롬프트를 보내고, 응답을 받아보려고 한다.
그리고 간단히 LangChain에 대해 알아보고 실습하고자 한다.
🔑 OpenAI API Key 준비
API를 호출하려면 당연히 OpenAI API Key가 필요하다.
Key 발급 과정은 이미 잘 정리된 글들이 많으니 이 글에서는 생략한다.
간략하게 말하자면 .env에 내 API key를 세팅하고
아래와 같이 OpenAI API를 호출하기 위한 환경변수 설정을 완료한다.
🔨 LLM 객체 생성
LangChain에서 OpenAI의 Chat 모델을 사용하기 위해
ChatOpenAI 클래스를 사용한다.
ChatOpenAI 클래스는 여러가지 파라미터를 설정해줄 수 있는데,
대표적인 두 가지(temperature, model_name)이 있다.
temperature (0.0 ~ 2.0 설정 가능)
- 낮을수록 답변이 안정적이고 사실 위주로 답변한다.
- 높을수록 창의적이지만 다소 산만해질 수 있다고 한다.
model_name
- 말 그대로, 어떤 LLM 모델을 호출할지 설정하는 파라미터이다.
물론 모델별로 API 호출 시, 토큰 사용량이 다르다.
📨 응답 객체로 받아보기
이제 간단한 질문을 던져보자.
질문을 question 변수로 만들고,
ChatOpenAI 클래스를 통해 생성된 객체를 활용하여
invoke 메소드안에 question 변수를 담아 호출할 수 있다.
그럼 아래와 같이 LLM으로 부터 답변을 수신하는 것을 볼 수 있다.

📶 스트리밍 방식으로 응답 받기
invoke를 통해 답변을 받는 것은 조금의 딜레이가 발생하여 답답함이 느껴질 수 있다.
그런 이유 때문에 ChatOpenAI 객체는 stream 방식도 제공한다.
이를 통해 응답을 실시간으로 토큰 단위로 받을 수 있다.

⚒️ PromptTemplate로 프롬프트 구조화하기
지금까지는 문자열을 바로 LLM에게 질문으로 넘겼지만,
실무에서는 프롬프트를 템플릿화하는 것이 훨씬 중요하다고 한다.
그렇기 때문에 프롬프트템플릿이 존재한다.
따라서 프롬프트에서 동적으로 값을 할당해 줄 부분을 {변수} 로 표현할 수 있다.
그런 다음
PromptTemplate.from_template 로 프롬프트 템플릿 객체를 생성한다.
그리고 format 메서드를 사용해 템플릿 내, 변수값을 할당해줄 수 있다.
결론적으로 우리는 입력 값만 바꿔서 재사용 가능한 프롬프트를 만들 수 있게 됐다!
⛓️ LCEL로 체인 구성하기
LangChain의 핵심 개념 중 하나가 바로
LCEL(LangChain Expression Language) 이다.
우리의 이전 실습에서는 대부분 단일 컴포넌트 단위로 동작을 확인했다.
- 프롬프트를 만들어 보고
- 모델에 직접 invoke(), stream() 로 질의하고
- 응답을 출력하거나 스트리밍으로 받아본다.
이러한 단일 호출 방식은 로직이 복잡해지면 한계에 부딪힌다.
예를들어,
- 입력 값을 가공한 프롬프트를 만들고
- 특정 모델에 전달한 뒤
- 결과를 문자열로 파싱하고
- 경우에 따라 스트리밍으로 출력하고 싶다.
이걸 전부 코드로 하나하나 연결하면 다음과 같은 문제가 생긴다.
1. 코드 가독성이 떨어진다.
2. 프롬프트, 모델, 출력 로직이 강하게 결합된다.
3. 단계들의 확장성이 낮아진다.
LCEL은 이 문제를 해결하기 위해 등장했고, 정의하면
"LCEL은 LLM 애플리케이션을 구성하는 각 단계를 하나의 파이프라인으로 표현하는 문법이다."
아래 구조가 가장 기본 형태이다.
여기서 각 요소는 역할이 명확한 독립 컴포넌트다.

| 연산자는 유닉스 파이프와 동일한 개념으로,
앞 단계의 출력을 다음 단계의 입력으로 전달한다.
prompt : 사용자 입력을 기반으로 프롬프트 생성
model(ChatOpenAI) : 프롬프트를 받아 LLM 호출
OutputParser : 모델의 출력을 원하는 형태로 변환
🌊 데이터 흐름 관점에서 이해하기
위와 같은 체인을 풀어서 보면 내부적으로는 다음과 같은 흐름이다.
1. 사용자가 input을 전달한다.
2. PromptTemplate이 이를 문자열 프롬프트로 변환한다.
3. 모델이 프롬프트를 받아 응답 메세지를 수신한다.
4. OutputParse가 결과를 가공한다.
5. 최종 결과를 반환한다.
하지만 개발자는 이 모든 흐름을 하나의 체인으로 선언하기만 하면 되게 된 것이다.
⁉️ 왜 LCEL이 중요한가?
LCEL의 진짜 가치는 확장성과 조합성에 있다.
- 체인 중간에 다른 컴포넌트를 쉽게 끼워 넣을 수 있고
- 동일한 프롬프트 + 다른 모델 조합도 가능하며
- RAG, 메모리, 툴 호출, 분기 로직까지 자연스럽게 확장된다.
예를들어 나중에 배우게 될 retriever를 적용한다면
이렇게 사이에 쏘옥 끼워주기만 하면 된다.
또는 조건에 따라 체인이 달라지는 구조도 만들 수 있다.
✅ 실전 예제 : 상황 기반 영어 회화 생성
오늘 배운 것을 정리하며 예제를 만들어보자

감사합니다.
'AI' 카테고리의 다른 글
| 왜 우리는 RAG를 배워야 할까? - ChatGPT의 한계와 나만의 LLM (0) | 2026.02.09 |
|---|