데브포일 홈
DEV MODE - 실서버 영향 없음 📦 배포 관리
AI 챗봇 만들기 - 실시간 대화 시스템
+250 XP
LEVEL 40 QUEST

AI 챗봇 만들기 - 실시간 대화 시스템

AI 챗봇 만들기 - 실시간 대화 시스템 — DevFoil 바이브코딩 Stage 9, Lv.40

대화 히스토리 관리 - AI가 맥락을 기억하게 하기
AI는 기본적으로 기억력이 없습니다
AI API는 매 요청이 독립적입니다. "아까 물어본 것에 대해 더 설명해줘"라고 하면 AI는 "아까"가 뭔지 모릅니다.

대화의 맥락을 유지하려면 이전 대화 내용 전체를 매번 함께 보내야 합니다. 이것이 "대화 히스토리 관리"의 핵심입니다.
<?php
// ===== 세션 기반 대화 히스토리 관리 =====
session_start();

// 대화 히스토리 초기화
if (!isset($_SESSION["chat_history"])) {
    $_SESSION["chat_history"] = [
        [
            "role" => "system",
            "content" => "당신은 친절한 한국어 AI 도우미입니다.
                          사용자의 질문에 명확하고 간결하게 답변합니다."
        ]
    ];
}

function addMessage($role, $content) {
    $_SESSION["chat_history"][] = [
        "role" => $role,
        "content" => $content
    ];

    // 토큰 절약: 최근 20개 메시지만 유지 (시스템 프롬프트는 항상 포함)
    if (count($_SESSION["chat_history"]) > 21) {
        $system = $_SESSION["chat_history"][0];
        $_SESSION["chat_history"] = array_merge(
            [$system],
            array_slice($_SESSION["chat_history"], -20)
        );
    }
}

function sendToAI($apiKey) {
    $ch = curl_init("https://api.openai.com/v1/chat/completions");
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode([
            "model" => "gpt-4o",
            "messages" => $_SESSION["chat_history"],
            "max_tokens" => 1000,
            "temperature" => 0.7
        ]),
        CURLOPT_HTTPHEADER => [
            "Content-Type: application/json",
            "Authorization: Bearer $apiKey"
        ],
        CURLOPT_TIMEOUT => 30,
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    $result = json_decode($response, true);
    return $result["choices"][0]["message"]["content"] ?? "응답 오류";
}

// 사용자 메시지 처리
if (!empty($_POST["message"])) {
    $userMsg = trim($_POST["message"]);
    addMessage("user", $userMsg);

    $aiResponse = sendToAI(getenv("OPENAI_API_KEY"));
    addMessage("assistant", $aiResponse);
}
?>
스트리밍 응답 - 글자가 타이핑되듯 표시
사용자 경험을 극적으로 향상시키는 스트리밍
기본 API 호출은 전체 응답이 완성될 때까지 기다려야 합니다 (수 초~수십 초). 스트리밍(Streaming)을 사용하면 ChatGPT처럼 글자가 하나씩 나타나는 효과를 구현할 수 있습니다.

API에 "stream": true를 추가하면 서버가 Server-Sent Events(SSE) 형태로 토큰 단위로 실시간 전송합니다.
<?php
// ===== stream_api.php - 스트리밍 응답 서버 =====
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
header("Connection: keep-alive");

$apiKey = getenv("OPENAI_API_KEY");
$messages = json_decode($_POST["messages"] ?? "[]", true);

$ch = curl_init("https://api.openai.com/v1/chat/completions");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode([
        "model" => "gpt-4o",
        "messages" => $messages,
        "stream" => true  // 스트리밍 활성화!
    ]),
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "Authorization: Bearer $apiKey"
    ],
    // 스트리밍: 데이터가 올 때마다 콜백 실행
    CURLOPT_WRITEFUNCTION => function($ch, $data) {
        $lines = explode("\n", $data);
        foreach ($lines as $line) {
            $line = trim($line);
            if (strpos($line, "data: ") === 0) {
                $json = substr($line, 6);
                if ($json === "[DONE]") {
                    echo "data: [DONE]\n\n";
                } else {
                    $parsed = json_decode($json, true);
                    $content = $parsed["choices"][0]["delta"]["content"] ?? "";
                    if ($content !== "") {
                        echo "data: " . json_encode(["content" => $content]) . "\n\n";
                    }
                }
                ob_flush();
                flush();
            }
        }
        return strlen($data);
    }
]);

curl_exec($ch);
curl_close($ch);
?>
// ===== 프론트엔드 JavaScript - SSE로 스트리밍 수신 =====

async function sendMessage(userMessage) {
    const chatBox = document.getElementById("chat-box");

    // 사용자 메시지 표시
    chatBox.innerHTML += `<div class="user-msg">${userMessage}</div>`;

    // AI 응답 영역 생성
    const aiDiv = document.createElement("div");
    aiDiv.className = "ai-msg";
    chatBox.appendChild(aiDiv);

    // Fetch + ReadableStream으로 스트리밍 수신
    const response = await fetch("stream_api.php", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: "messages=" + encodeURIComponent(JSON.stringify(messages))
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        const text = decoder.decode(value);
        const lines = text.split("\n");

        for (const line of lines) {
            if (line.startsWith("data: ") && line !== "data: [DONE]") {
                const data = JSON.parse(line.substring(6));
                aiDiv.textContent += data.content;  // 글자 하나씩 추가!
                chatBox.scrollTop = chatBox.scrollHeight;
            }
        }
    }
}
🔒
여기까지는 미리보기입니다
AI 챗봇 만들기 - 실시간 대화 시스템
무료 가입하면 이어서 볼 수 있고, 강의를 완료할 때마다 XP와 레벨이 쌓입니다.
Google로 3초 만에 시작 →🧵 Threads로 시작무료 공개 강의 둘러보기 (Lv.1~3)