Skip to main content

부록 B. Node.js와 Python 최소 예제

부록 B. Node.js와 Python 최소 예제

이 부록의 목표

이 부록의 목적은 단순하다. 언어를 고르는 데 시간을 쓰지 말고, 일단 한 번 실행해 보는 것이다. LLM 서비스 개발은 생각보다 빨리 감이 온다. 서버에서 프롬프트를 받아 모델에 보내고, 응답을 다시 클라이언트에 돌려주면 끝이다. 이 한 바퀴만 직접 돌려 보면 이후의 인증, 스트리밍, 구조화 출력, RAG, 운영 이야기가 훨씬 덜 낯설어진다.

여기서는 Node.js와 Python으로 각각 가장 짧게 시작할 수 있는 예제를 준비했다. 둘 다 같은 흐름이다. 서버는 /api/chat 하나만 만들고, 클라이언트는 그 엔드포인트로 POST 요청 하나만 보낸다. 복잡한 기능은 일부러 넣지 않았다. 처음엔 잘 돌아가는 한 줄의 응답이 가장 중요하다.

시작 전에 딱 세 가지만 준비하자

  • Node.js 18+ 또는 Python 3.10+ 환경을 준비한다.

  • API 키는 코드에 넣지 말고 환경 변수로 저장한다.

  • 처음에는 모델 하나, 엔드포인트 하나, 요청 형식 하나만 쓴다.

예를 들어 .env 파일은 이렇게 시작하면 된다.

OPENAI_API_KEY=your_openai_api_key
ANTHROPIC_API_KEY=your_anthropic_api_key
GEMINI_API_KEY=your_gemini_api_key

중요한 건 욕심을 줄이는 것이다. 로그인도 없고, DB도 없고, 스트리밍도 없는 상태에서 먼저 성공 경험을 만든다. AI 서비스 개발은 보통 여기서부터 탄력이 붙는다.

공통 구조를 먼저 머리에 넣기

Node.js든 Python이든 최소 예제의 구조는 같다.

사용자가 클라이언트에서 메시지를 보내면, 서버는 그 메시지를 받아 LLM API를 호출한다. 그리고 모델이 돌려준 텍스트만 뽑아서 다시 JSON으로 응답한다. 결국 핵심은 세 줄이다.

첫째, 요청 받기. 둘째, 모델 호출하기. 셋째, 텍스트만 꺼내 돌려주기.

이 흐름만 이해하면 언어를 바꾸든, 모델을 바꾸든, 프레임워크를 바꾸든 크게 흔들리지 않는다.

Node.js 최소 예제

Node.js 쪽은 "작은 API 서버 하나를 빠르게 띄우고 싶다"는 상황에 잘 맞는다. 특히 프런트엔드와 같은 자바스크립트 계열 언어를 쓰고 있다면 진입 장벽이 낮다.

설치

새 폴더를 만들고 필요한 패키지만 설치하자.

mkdir llm-node-min
cd llm-node-min
npm init -y
npm install express openai dotenv

서버 코드

파일 이름은 server.mjs로 두자. .mjs를 쓰면 복잡한 설정 없이 ESM 문법으로 바로 시작할 수 있다.

import "dotenv/config";
import express from "express";
import OpenAI from "openai";

const app = express();
app.use(express.json());

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

app.post("/api/chat", async (req, res) => {
  try {
    const message = req.body.message ?? "안녕하세요. 자기소개를 해주세요.";

    const response = await client.responses.create({
      model: "gpt-4.1-mini",
      input: [
        {
          role: "system",
          content: "당신은 친절한 한국어 도우미입니다.",
        },
        {
          role: "user",
          content: message,
        },
      ],
    });

    res.json({ text: response.output_text });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => {
  console.log("http://localhost:3000 에서 서버 실행 중");
});

이 코드는 정말 최소한만 한다. 사용자의 메시지를 받아 responses.create()로 모델을 호출하고, 결과에서 output_text만 꺼내서 반환한다. 여기까지 되면 이미 LLM 백엔드의 첫 발은 뗀 셈이다.

클라이언트 코드

이번에는 같은 프로젝트에 client.mjs를 만든다. 이 파일은 방금 만든 서버를 호출하는 아주 작은 클라이언트다.

const response = await fetch("http://localhost:3000/api/chat", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    message: "Node.js로 LLM 서비스를 시작하는 법을 3문장으로 설명해줘.",
  }),
});

const data = await response.json();
console.log(data.text);

실행

터미널을 두 개 열면 편하다.

첫 번째 터미널에서 서버를 띄운다.

node server.mjs

두 번째 터미널에서 클라이언트를 실행한다.

node client.mjs

정상적으로 동작하면 콘솔에 한국어 답변이 출력된다. 이 순간이 작지만 중요하다. 이제 여러분은 "LLM API를 호출하는 서버"와 "그 서버를 쓰는 클라이언트"를 이미 하나씩 가진 상태다.

Node.js에서 Claude로 바꾸기

서버 구조는 그대로 두고, 모델 호출 부분만 Claude SDK로 바꾸면 된다.

먼저 설치한다.

npm install @anthropic-ai/sdk

그다음 호출부를 이렇게 바꾼다.

import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-20250514",
  max_tokens: 300,
  messages: [
    { role: "user", content: message },
  ],
});

const text = response.content
  .filter(block => block.type === "text")
  .map(block => block.text)
  .join("n");

핵심 차이는 응답 구조다. OpenAI 예제처럼 output_text 하나로 끝나지 않고, Claude는 content 배열 안의 텍스트 블록을 합쳐서 꺼내는 식으로 처리하는 경우가 많다.

Node.js에서 Gemini로 바꾸기

Gemini는 Google Gen AI SDK를 쓰면 빠르게 시작할 수 있다.1

npm install @google/genai

호출 코드는 이렇게 줄일 수 있다.

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({
  apiKey: process.env.GEMINI_API_KEY,
});

const response = await ai.models.generateContent({
  model: "gemini-2.5-flash",
  contents: message,
});

const text = response.text;

재미있는 점은 구조가 다 달라도 여러분의 서버 인터페이스는 그대로 둘 수 있다는 것이다. 바깥에서는 여전히 /api/chat에 message를 보내고 { text }를 받는다. 이 습관이 나중에 멀티 벤더 아키텍처에서 큰 힘을 발휘한다.

Python 최소 예제

Python은 AI 생태계와 붙을 일이 많고, 데이터 처리나 백엔드 자동화와도 궁합이 좋다. 무엇보다 코드가 짧고 읽기 쉽다. "조용히 잘 돌아가는 실험 서버"를 만들 때 참 든든한 언어다.

설치

이번에는 Python 프로젝트를 만든다.

mkdir llm-python-min
cd llm-python-min
python -m venv .venv
source .venv/bin/activate
pip install fastapi uvicorn openai python-dotenv requests

Windows라면 가상환경 활성화 명령만 환경에 맞게 바꾸면 된다.

서버 코드

server.py 파일을 만든다.

import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()

app = FastAPI()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

class ChatBody(BaseModel):
    message: str = "안녕하세요. 자기소개를 해주세요."

@app.post("/api/chat")
def chat(body: ChatBody):
    try:
        response = client.responses.create(
            model="gpt-4.1-mini",
            input=[
                {
                    "role": "system",
                    "content": "당신은 친절한 한국어 도우미입니다."
                },
                {
                    "role": "user",
                    "content": body.message
                }
            ]
        )
        return {"text": response.output_text}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

Node.js 예제와 거의 같은 흐름이다. 이 비슷함이 중요하다. 언어가 달라도 서비스 개발의 핵심은 크게 달라지지 않는다는 뜻이기 때문이다.

클라이언트 코드

이제 client.py를 만든다.

import requests

response = requests.post(
    "http://127.0.0.1:8000/api/chat",
    json={
        "message": "Python으로 LLM 서비스를 시작하는 법을 3문장으로 설명해줘."
    }
)

print(response.json()["text"])

실행

먼저 서버를 띄운다.

uvicorn server:app --reload --port 8000

그다음 클라이언트를 실행한다.

python client.py

응답이 잘 나오면 성공이다. 이제 Python으로도 최소 LLM 서버와 클라이언트를 한 번 끝까지 연결해 본 셈이다.

Python에서 Claude로 바꾸기

설치부터 아주 짧다.

pip install anthropic

호출 부분은 이렇게 바꾸면 된다.

from anthropic import Anthropic

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=300,
    messages=[
        {"role": "user", "content": body.message}
    ]
)

text = "n".join(
    block.text for block in response.content if block.type == "text"
)

Python에서 Gemini로 바꾸기

Python에서도 공식 SDK로 빠르게 시작할 수 있다.1

pip install google-genai

예제는 다음처럼 단순하다.

from google import genai

client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=body.message,
)

text = response.text

API 키 없이 로컬 모델로 먼저 연습하는 방법

처음부터 과금이 신경 쓰인다면 로컬 모델로 감을 잡아도 좋다. Ollama 같은 로컬 런타임은 HTTP API를 제공하고, OpenAI 호환 엔드포인트도 지원해서 기존 클라이언트를 거의 그대로 재사용할 수 있다.2 Lemonade Server도 비슷하게 OpenAI 호환 방식으로 로컬 모델을 붙일 수 있다.3

예를 들어 Python에서는 이렇게 시작할 수 있다.

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama"
)

response = client.chat.completions.create(
    model="llama3.2:3b",
    messages=[
        {"role": "user", "content": "안녕하세요"}
    ]
)

print(response.choices[0].message.content)

Node.js도 비슷하다.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "http://localhost:11434/v1",
  apiKey: "ollama",
});

const response = await client.chat.completions.create({
  model: "llama3.2:3b",
  messages: [
    { role: "user", content: "안녕하세요" },
  ],
});

console.log(response.choices[0].message.content);

이 방식의 장점은 아주 분명하다. 서버 코드는 크게 바꾸지 않고도, 클라우드 모델과 로컬 모델을 번갈아 실험할 수 있다. 비용을 아끼면서 손에 익히기엔 꽤 좋은 출발점이다.

처음엔 이 정도만 되면 충분하다

처음부터 스트리밍, 대화 히스토리, 재시도, 관측성, 세션 저장까지 넣으려고 하면 금방 숨이 찬다. 부록 B의 목표는 거기까지가 아니다. 여기서는 다음 네 가지만 되면 합격이다.

  • 서버가 JSON 요청을 받는다.

  • 서버가 모델을 호출한다.

  • 서버가 텍스트를 JSON으로 돌려준다.

  • 클라이언트가 그 결과를 출력한다.

이 네 단계를 Node.js와 Python 양쪽에서 한 번씩만 해보면, 언어 때문에 시작이 늦어지는 문제는 거의 사라진다. 그다음부터는 취향의 영역이다. 프런트엔드와 더 가깝게 가고 싶으면 Node.js가 편하고, 데이터 처리와 백엔드 자동화를 더 밀고 싶으면 Python이 편하다. 어느 쪽을 골라도 괜찮다. 중요한 건 오늘 한 번이라도 실행해 보는 것이다.

막히면 가장 먼저 확인할 것

이상하게도 LLM 예제의 실패 원인은 늘 비슷하다. 모델이 어려워서가 아니라, 사소한 연결 실수 때문이다.

첫째, API 키가 실제로 로드됐는지 확인하자. .env 파일 이름이 틀리거나, 터미널 위치가 달라서 안 읽히는 경우가 많다.

둘째, 요청 본문의 키 이름이 맞는지 확인하자. message라고 보내기로 했으면 서버와 클라이언트 모두 message를 써야 한다.

셋째, 포트를 헷갈리지 말자. Node.js 예제는 3000번 포트, Python 예제는 8000번 포트다.

넷째, 처음엔 응답을 예쁘게 가공하지 말자. 있는 그대로 console.log나 print부터 해보는 쪽이 디버깅이 훨씬 쉽다.

LLM 개발을 처음 시작할 때 가장 좋은 전략은 멋진 구조를 만드는 것이 아니라, 가장 작은 성공을 빨리 만드는 것이다. 이 부록의 예제는 바로 그 작은 성공을 위한 발판이다.

참고

1Gemini API quickstart

2Integrate Ollama REST API Local LLMs in Any App 2026

3Getting Started with Lemonade Server

책 목록

실전 LLM 서비스 개발: ChatGPT·Claude·Gemini API로 만드는 AI 웹 서비스의 설계부터 운영까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기