본문 바로가기
프로젝트/AIKit

AIKit #5 - PHP 프로젝트에서 AIKit 연동하기

by 루까(Luka) 2026. 2. 8.
반응형

AIKit — PHP 연동 가이드

왜 클라이언트 사이드 AI인가

"JavaScript 라이브러리를 PHP 프로젝트에 어떻게 쓰지?"라는 질문을 받는다. 답은 클라이언트 사이드에서 AI를 처리하고, PHP는 데이터 저장만 담당하는 구조다.

전통적 방식 vs 클라이언트 사이드 AI

항목 서버 사이드 AI 클라이언트 사이드 AI (AIKit)
API 호출 PHP → AI API 브라우저 → AI API
서버 부하 모든 요청이 서버 경유 서버 부하 0
응답 속도 서버 왕복 추가 직접 통신 (빠름)
프로바이더 변경 백엔드 재배포 프론트엔드만 수정

아키텍처

브라우저
├── AIKit (CDN) → AI API 직접 통신
└── AJAX → PHP 서버 → DB 저장
  • PHP: 인증, 데이터 저장, 비즈니스 로직
  • AIKit: AI 통신, 응답 처리, 클라이언트 캐싱
  • DB: 대화 이력, 사용자 설정

프로젝트 구조

php-ai-app/
├── public/
│   ├── index.php          ← 메인 페이지
│   └── api/
│       ├── save-chat.php  ← 대화 저장 API
│       └── load-chats.php ← 대화 불러오기 API
├── config/
│   └── database.php       ← DB 설정
└── vendor/

DB 스키마

CREATE TABLE conversations (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(255),
    provider VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE messages (
    id INT AUTO_INCREMENT PRIMARY KEY,
    conversation_id INT NOT NULL,
    role ENUM('user', 'assistant') NOT NULL,
    content TEXT NOT NULL,
    tokens_used INT DEFAULT 0,
    cost DECIMAL(10, 6) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

API 키는 DB에 저장하지 않는다. 사용자의 브라우저(localStorage)에만 존재한다.


PHP API 엔드포인트

대화 저장

// api/save-chat.php
$data = json_decode(file_get_contents('php://input'), true);

$stmt = $pdo->prepare('
    INSERT INTO messages (conversation_id, role, content, tokens_used, cost)
    VALUES (:conv_id, :role, :content, :tokens, :cost)
');

$stmt->execute([
    ':conv_id' => $data['conversation_id'],
    ':role'    => $data['role'],
    ':content' => $data['content'],
    ':tokens'  => $data['tokens_used'] ?? 0,
    ':cost'    => $data['cost'] ?? 0
]);

echo json_encode(['success' => true]);

Prepared Statement를 반드시 사용한다. SQL Injection 방지는 기본이다.

대화 불러오기

// api/load-chats.php
$stmt = $pdo->prepare('
    SELECT m.* FROM messages m
    WHERE m.conversation_id = :conv_id
    ORDER BY m.created_at ASC
');
$stmt->execute([':conv_id' => $_GET['id']]);

echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));

프론트엔드 연동

// AIKit 초기화
const ai = new AIKit({
    provider: 'openai',
    apiKey: localStorage.getItem('apiKey'),
    enableCostTracking: true
});

// 메시지 전송 + 서버 저장
async function sendMessage(message) {
    const response = await ai.chat(message);

    // AI 응답을 서버에 저장
    await fetch('/api/save-chat.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            conversation_id: currentConvId,
            role: 'assistant',
            content: response.content,
            tokens_used: response.usage?.total_tokens || 0,
            cost: ai.getCostReport().total
        })
    });

    return response;
}

AI 통신은 브라우저에서 직접 하고, 결과만 PHP 서버에 저장한다.


보안 원칙

원칙 설명
API 키 서버 미저장 localStorage에만 보관, 서버로 전송하지 않음
Prepared Statement 모든 DB 쿼리에 바인딩 사용
Input Escape htmlspecialchars()로 출력 시 이스케이프
CSRF 토큰 폼/AJAX 요청에 토큰 검증

Laravel 연동

Laravel 프로젝트라면 라우트와 컨트롤러를 이용한다.

// routes/web.php
Route::middleware('auth')->group(function () {
    Route::post('/chat/save', [ChatController::class, 'save']);
    Route::get('/chat/history', [ChatController::class, 'history']);
});
// ChatController.php
public function save(Request $request) {
    $validated = $request->validate([
        'conversation_id' => 'required|integer',
        'role' => 'required|in:user,assistant',
        'content' => 'required|string|max:10000',
    ]);

    Message::create($validated);
    return response()->json(['success' => true]);
}

마무리

PHP + AIKit 조합의 핵심은 역할 분리다. AI 통신은 클라이언트에서, 데이터 저장은 서버에서. 서버 부하는 줄이고 응답 속도는 높인다.

다음 편에서는 React와 Vue에서 AIKit을 사용하는 방법을 다룬다.


기술 스택: PHP, JavaScript, AIKit, MySQL, Laravel
소스 코드: GitHub

반응형