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

AIKit #6 - React & Vue에서 AIKit 사용하기

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

AIKit — React & Vue 연동

자주 받는 질문

"React에서 어떻게 쓰나요?" — AIKit은 순수 JavaScript 라이브러리다. 모든 프레임워크에서 동일하게 동작한다. 핵심은 프레임워크의 상태 관리 패턴에 맞춰 감싸는 것이다.


React 연동

Custom Hook

// useAIKit.js
import { useState, useRef, useCallback } from 'react';

export function useAIKit(config) {
    const aiRef = useRef(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [messages, setMessages] = useState([]);

    // 초기화 (한 번만)
    if (!aiRef.current) {
        aiRef.current = new AIKit(config);
    }

    const sendMessage = useCallback(async (message) => {
        setLoading(true);
        setError(null);

        setMessages(prev => [...prev, { role: 'user', content: message }]);

        try {
            const response = await aiRef.current.chat(message);
            setMessages(prev => [...prev, {
                role: 'assistant',
                content: response.content
            }]);
            return response;
        } catch (err) {
            setError(err.message);
        } finally {
            setLoading(false);
        }
    }, []);

    return { messages, sendMessage, loading, error, ai: aiRef.current };
}

컴포넌트에서 사용

function ChatBot() {
    const { messages, sendMessage, loading, error } = useAIKit({
        provider: 'openai',
        apiKey: process.env.REACT_APP_API_KEY,
        enableCache: true
    });

    const [input, setInput] = useState('');

    const handleSend = async () => {
        if (!input.trim()) return;
        await sendMessage(input);
        setInput('');
    };

    return (
        <div>
            {messages.map((msg, i) => (
                <div key={i} className={msg.role}>{msg.content}</div>
            ))}
            {loading && <div>응답 생성 중...</div>}
            {error && <div className="error">{error}</div>}
            <input value={input} onChange={e => setInput(e.target.value)} />
            <button onClick={handleSend} disabled={loading}>전송</button>
        </div>
    );
}

Context API로 전역 관리

const AIKitContext = createContext(null);

function AIKitProvider({ children, config }) {
    const aikit = useAIKit(config);
    return (
        <AIKitContext.Provider value={aikit}>
            {children}
        </AIKitContext.Provider>
    );
}

// 어디서든 사용
function AnyComponent() {
    const { sendMessage, messages } = useContext(AIKitContext);
}

Vue 3 연동

Composable

// useAIKit.js
import { ref, shallowRef } from 'vue';

export function useAIKit(config) {
    const ai = shallowRef(new AIKit(config));
    const loading = ref(false);
    const error = ref(null);
    const messages = ref([]);

    async function sendMessage(message) {
        loading.value = true;
        error.value = null;

        messages.value.push({ role: 'user', content: message });

        try {
            const response = await ai.value.chat(message);
            messages.value.push({
                role: 'assistant',
                content: response.content
            });
            return response;
        } catch (err) {
            error.value = err.message;
        } finally {
            loading.value = false;
        }
    }

    return { messages, sendMessage, loading, error, ai };
}

컴포넌트에서 사용

<template>
  <div>
    <div v-for="(msg, i) in messages" :key="i" :class="msg.role">
      {{ msg.content }}
    </div>
    <div v-if="loading">응답 생성 중...</div>
    <input v-model="input" @keyup.enter="handleSend" />
    <button @click="handleSend" :disabled="loading">전송</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useAIKit } from './useAIKit';

const { messages, sendMessage, loading } = useAIKit({
    provider: 'openai',
    apiKey: import.meta.env.VITE_API_KEY
});

const input = ref('');

async function handleSend() {
    if (!input.value.trim()) return;
    await sendMessage(input.value);
    input.value = '';
}
</script>

프레임워크 비교

항목 React Vue 3
패턴 Custom Hook Composable
상태 관리 useState + useRef ref + shallowRef
전역 관리 Context API Provide/Inject
번들 크기 추가 +2KB +2KB
성능 차이 없음 없음

AIKit 자체는 프레임워크에 독립적이므로 번들 크기와 성능에 미치는 영향이 거의 없다.


핵심 포인트

  1. AIKit 인스턴스는 한 번만 생성한다 — React에서는 useRef, Vue에서는 shallowRef
  2. 대화 이력은 프레임워크 상태로 관리한다useState / ref
  3. 로딩과 에러 상태를 분리한다 — UX 품질을 위해
  4. 환경 변수로 API 키를 관리한다 — 하드코딩 금지

마무리

React든 Vue든 AIKit 사용법은 동일하다. 프레임워크의 상태 관리 패턴으로 감싸기만 하면 된다. 순수 JavaScript로 만든 이유가 여기서 빛을 발한다.

다음 편에서는 AI API 비용을 90% 줄이는 최적화 전략을 다룬다.


기술 스택: React, Vue 3, AIKit, JavaScript
소스 코드: GitHub

반응형