자바스크립트 AI 챗봇 만들기 part5

자바스크립트 AI 챗봇 만들기 part5 : 성능 최적화, 배포, 그리고 추가 개선 아이디어

part4까지 챗봇에 QnA 모델과 날씨 API를 적용해 똑똑하고 실용적으로 만들었다. 이번 part5에서는 프로젝트를 마무리한다. 성능을 최적화하고, 초보자도 쉽게 따라 할 수 있도록 GitHub Pages로 배포한다. 추가 개선 아이디어도 제안한다.


이제 챗봇을 세상에 공개하고 더 발전시킬 준비를 한다. 모든 과정을 상세히 다룬다.


part5에서 무엇을 다루는가?

part5의 목표는 다음과 같다:

- 성능을 최적화한다: 로드 시간과 응답 속도를 개선한다.

- GitHub Pages로 배포한다: 초보자를 위한 단계별 가이드를 제공한다.

- 추가 개선 아이디어를 탐구한다: 실용적이고 흥미로운 방향을 제시한다.

part4의 my-chatbot 폴더를 사용한다.


성능 최적화하기

챗봇이 빠르고 안정적으로 동작하도록 성능을 개선한다. QnA 모델과 API 호출에 초점을 맞춘다.


1. 모델 로드 상태 표시

QnA 모델 로드에 시간이 걸리니 사용자에게 상태를 알린다:

async function loadQnAModel() {
    addMessage('QnA 모델을 로드 중이다... 잠시 기다린다.');
    try {
        qnaModel = await qna.load();
        console.log('QnA 모델이 로드됐다');
        addMessage('챗봇 준비가 완료됐다! 질문을 기다린다.');
    } catch (err) {
        console.error('모델 로드 실패:', err);
        addMessage('모델 로드에 실패했다. 기본 응답만 제공한다.');
    }
}

설명

- 로드 중 메시지를 표시해 사용자 경험을 개선한다.


2. API 호출 캐싱

날씨 API를 반복 호출하면 비효율적이다. 캐싱을 추가한다:

const weatherCache = {};

async function getWeather(city) {
    if (weatherCache[city]) {
        return weatherCache[city];
    }
    const apiKey = 'YOUR_API_KEY';
    try {
        const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=ko`);
        const data = await response.json();
        if (data.cod === 200) {
            const result = `${city}의 날씨는 ${data.weather[0].description}, 온도는 ${data.main.temp}°C다.`;
            weatherCache[city] = result;
            return result;
        }
        return '도시를 찾을 수 없다. 정확한 이름을 입력한다.';
    } catch (error) {
        console.error('날씨 API 오류:', error);
        return '날씨 데이터를 가져오지 못했다.';
    }
}

설명

- weatherCache: 동일한 도시의 결과를 재사용한다.


3. 이벤트 디바운싱

연속 입력으로 성능이 저하되지 않게 디바운싱을 적용한다:

function debounce(func, wait) {
    let timeout;
    return function (...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func(...args), wait);
    };
}

const debouncedSendMessage = debounce(sendMessage, 300);

sendBtn.addEventListener('click', debouncedSendMessage);

userInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        debouncedSendMessage();
    }
});

설명

- 300ms 동안 추가 입력이 없으면 실행한다.


GitHub Pages로 배포하기

이제 챗봇을 무료로 배포한다. GitHub Pages는 정적 파일 호스팅에 적합하다. 초보자도 할 수 있게 모든 단계를 상세히 설명한다.


1. Git 설치하기

Git이 없으면 먼저 설치한다:

- git-scm.com에 접속한다.

- 운영체제에 맞는 버전을 다운로드한다 (예: Windows 64-bit).

- 설치 파일을 실행하고 기본 설정으로 "Next"를 눌러 진행한다.

- 설치 후 터미널에서 확인한다:

git --version

버전 번호(예: 2.39.0)가 나오면 성공이다.


2. GitHub 계정 만들기

GitHub 계정이 없다면 생성한다:

- github.com에 접속한다.

- "Sign Up"을 클릭한다.

- 이메일, 사용자 이름(예: `myusername`), 비밀번호를 입력한다.

- 인증 메일을 확인하고 로그인한다.

이미 계정이 있다면 로그인만 한다.


3. 새 저장소 생성하기

프로젝트를 저장할 공간을 만든다:

- GitHub에 로그인한다.

- 오른쪽 상단 "+" 버튼을 누르고 "New Repository"를 선택한다.

- 저장소 이름은 my-chatbot으로 한다.

- "Public"을 선택한다 (누구나 볼 수 있다).

- "Add a README file"은 체크하지 않는다.

- "Create Repository"를 클릭한다.

- 생성된 저장소 URL을 복사한다. 예: https://github.com/myusername/my-chatbot.git


4. 로컬에서 Git 초기화하기

my-chatbot 폴더에서 Git을 설정한다:

- VS Code에서 my-chatbot 폴더를 연다.

- "Terminal > New Terminal"을 클릭해 터미널을 연다.

- 다음 명령어를 순서대로 입력한다:

git init

Git 저장소가 초기화된다.

git add .

모든 파일(index.html, style.css, script.js)을 스테이징한다.

git commit -m "Initial commit"

변경 사항을 커밋한다.


5. GitHub에 업로드하기

로컬 파일을 GitHub로 보낸다:

- 저장소 URL을 연결한다:

git remote add origin https://github.com/myusername/my-chatbot.git

- "myusername"을 본인의 GitHub 사용자 이름으로 바꾼다.

- 업로드한다:

git push -u origin main

- 처음 푸시하면 로그인 창이 뜬다. GitHub 계정으로 로그인한다.

- GitHub 저장소에 접속해 파일이 업로드됐는지 확인한다.


6. GitHub Pages 활성화하기

웹사이트로 배포한다:

- GitHub 저장소(myusername/my-chatbot)로 간다.

- 상단 "Settings" 탭을 클릭한다.

- 왼쪽 메뉴에서 "Pages"를 선택한다.

- "Branch" 섹션에서 "main"을 선택하고 "Save"를 누른다.

- "Your site is ready to be published at" 메시지가 나타난다.

- 몇 분(5~10분) 기다린 후 URL을 확인한다. 예: https://myusername.github.io/my-chatbot/

- URL을 브라우저에서 열어 챗봇이 동작하는지 확인한다.


7. 배포 문제 해결

배포 중 문제가 생길 수 있다. 흔한 오류와 해결법을 정리한다:

- **"git push" 실패**:

git pull origin main --rebase

충돌을 해결하고 다시 푸시한다.

- **페이지가 안 보임**: 10분 이상 기다려도 안 되면 "Settings > Pages"에서 브랜치가 "main"인지 다시 확인한다.

- **API 오류**: API 키가 브라우저에 노출돼 차단될 수 있다. 배포 후 개선 방법에서 다룬다.


추가 개선 아이디어

챗봇을 더 발전시킬 구체적인 아이디어를 제안한다.


1. API 키 보호

현재 API 키가 클라이언트에 노출된다. 서버를 추가해 보호한다:

// Node.js 서버 예시 (server.js)
const express = require('express');
const fetch = require('node-fetch');
const app = express();

app.get('/weather/:city', async (req, res) => {
    const apiKey = 'YOUR_API_KEY';
    const city = req.params.city;
    const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=ko`);
    const data = await response.json();
    res.json(data);
});

app.listen(3000, () => console.log('서버 실행'));

설명

- 클라이언트에서 `/weather/서울`로 요청하면 서버가 API를 호출한다.


2. 음성 입력

Web Speech API로 음성을 추가한다:

const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
recognition.lang = 'ko-KR';
recognition.onresult = (event) => {
    userInput.value = event.results[0][0].transcript;
    sendMessage();
};
sendBtn.insertAdjacentHTML('afterend', '<button id="voice-btn">음성</button>');
document.getElementById('voice-btn').addEventListener('click', () => recognition.start());

설명

- 음성 버튼으로 말을 텍스트로 변환한다.


3. 다국어 지원

번역 기능을 추가한다:

async function translateText(text, targetLang) {
    const response = await fetch(`https://api.example.com/translate?text=${text}&target=${targetLang}`);
    const data = await response.json();
    return data.translatedText;
}

async function getResponse(input) {
    let response = await originalGetResponse(input); // 기존 getResponse
    if (input.includes('영어로')) {
        response = await translateText(response, 'en');
    }
    return response;
}

설명

- 무료 번역 API(예: Google Translate 무료 대안)를 사용한다.


마무리

part5 시리즈를 완성했다. 챗봇은 이제 QnA 모델로 질문에 답하고, 날씨를 알려주며, GitHub Pages에 배포됐다. 성능 최적화와 배포 과정을 통해 실전에 사용할 준비가 된다. 추가 아이디어로 더 발전시킨다. 다음 실습은 무엇으로 할지 고민해봐야겠다.


자바스크립트 AI 챗봇 만들기 part4

자바스크립트 AI 챗봇 만들기 part4 : 외부 API 연동으로 챗봇 기능 확장

part3에서 TensorFlow.js의 QnA 모델을 적용해 챗봇이 질문에 답변하도록 만들었다. 이번에는 외부 API를 연동해 실용성을 더한다. OpenWeatherMap API를 사용해 날씨 정보를 제공하며, QnA 모델과 조화를 이루게 한다.


이제 챗봇은 문맥 기반 답변뿐 아니라 실시간 날씨 데이터도 알려준다. 초보자도 따라 할 수 있도록 상세히 설명한다.


part4에서 무엇을 다루는가?

part4의 목표는 다음과 같다:

- API의 기본 개념을 이해한다.

- OpenWeatherMap API를 등록하고 설정한다.

- 챗봇에 날씨 조회 기능을 추가한다.

- QnA 모델과 API 응답을 통합한다.

part3의 my-chatbot 폴더를 이어서 사용한다.


API란 무엇인가?

API(Application Programming Interface)는 프로그램 간 데이터를 주고받게 하는 인터페이스다. 챗봇에서는 외부 서비스에서 실시간 데이터를 가져와 활용한다. 예를 들어, 날씨 API는 도시 이름을 주면 현재 날씨를 반환한다.


이번에 사용할 OpenWeatherMap은 무료로 날씨 데이터를 제공한다. 공식 사이트에서 쉽게 설정한다.


OpenWeatherMap API 설정하기

API를 사용하려면 키를 발급받는다. 초보자도 할 수 있게 단계별로 설명한다.


1. 계정 생성

- OpenWeatherMap에 접속한다.

- 오른쪽 상단 "Sign Up"을 클릭하고 이메일, 비밀번호를 입력해 가입한다.

- 이메일 인증 후 로그인한다.


2. API 키 발급

- 로그인 후 상단 "API Keys" 탭으로 이동한다.

- 기본 키가 이미 생성돼 있다. 없다면 "Generate"를 클릭해 새 키를 만든다.

- 키를 복사한다. 예: abcd1234efgh5678

키는 비공개로 유지한다. 다른 사람과 공유하지 않는다.


날씨 조회 기능 추가하기

이제 챗봇에 날씨 API를 연동한다. fetch로 데이터를 가져오고, QnA 모델과 함께 사용한다.


1. API 호출 함수 작성

script.js에 날씨 조회 함수를 추가한다:

async function getWeather(city) {
    const apiKey = 'YOUR_API_KEY'; // 발급받은 키로 교체한다
    try {
        const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=ko`);
        const data = await response.json();
        if (data.cod === 200) {
            return `${city}의 날씨는 ${data.weather[0].description}, 온도는 ${data.main.temp}°C다.`;
        }
        return '도시를 찾을 수 없다. 정확한 이름을 입력한다.';
    } catch (error) {
        console.error('날씨 API 오류:', error);
        return '날씨 데이터를 가져오지 못했다.';
    }
}

설명

- YOUR_API_KEY를 발급받은 키로 바꾼다.

- `units=metric`: 온도를 섭씨로 반환한다.

- `lang=ko`: 한국어로 응답한다.


2. 전체 코드 통합

script.js를 아래처럼 수정한다:

const messages = document.getElementById('chat-messages');
const userInput = document.getElementById('user-input');
const sendBtn = document.getElementById('send-btn');

function addMessage(text, isUser = false) {
    const message = document.createElement('p');
    message.textContent = text;
    message.style.textAlign = isUser ? 'right' : 'left';
    message.style.background = isUser ? '#ff4e00' : '#f0f0f0';
    message.style.color = isUser ? '#fff' : '#333';
    message.style.padding = '8px 12px';
    message.style.margin = '5px 0';
    message.style.borderRadius = '4px';
    message.style.display = 'inline-block';
    messages.appendChild(message);
    messages.scrollTop = messages.scrollHeight;
}

// 기본 문맥 정의
const context = `
    이 챗봇은 자바스크립트로 만들어졌다. 이름은 Chatbot이며 bdool에서 개발했다.
    현재 날짜는 2025년 2월 28일이다. 주요 기능은 대화와 질문에 답하는 것이다.
    날씨 정보도 제공할 수 있다. 개발자는 사용자를 돕기 위해 만든다.
`;

let qnaModel;

// 모델 로드
async function loadQnAModel() {
    try {
        qnaModel = await qna.load();
        console.log('QnA 모델이 로드됐다');
        addMessage('챗봇 준비가 완료됐다! 질문을 기다린다.');
    } catch (err) {
        console.error('모델 로드 실패:', err);
        addMessage('모델 로드에 실패했다. 기본 응답만 제공한다.');
    }
}

// 날씨 조회
async function getWeather(city) {
    const apiKey = 'YOUR_API_KEY'; // 발급받은 키로 교체한다
    try {
        const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=ko`);
        const data = await response.json();
        if (data.cod === 200) {
            return `${city}의 날씨는 ${data.weather[0].description}, 온도는 ${data.main.temp}°C다.`;
        }
        return '도시를 찾을 수 없다. 정확한 이름을 입력한다.';
    } catch (error) {
        console.error('날씨 API 오류:', error);
        return '날씨 데이터를 가져오지 못했다.';
    }
}

// 질문 처리
async function getAnswer(question) {
    if (!qnaModel) {
        return '모델이 아직 로드되지 않았다. 잠시 기다린다.';
    }
    try {
        const answers = await qnaModel.findAnswers(question, context);
        if (answers.length > 0 && answers[0].text) {
            return answers[0].text;
        }
        return '질문에 대한 답을 찾지 못했다. 다른 질문을 해본다.';
    } catch (err) {
        console.error('답변 생성 실패:', err);
        return '답변을 생성하지 못했다.';
    }
}

// 키워드 및 날씨 응답
async function getResponse(input) {
    input = input.toLowerCase();
    if (input.includes('안녕')) {
        return '안녕! 나도 반갑다.';
    }
    if (input.includes('뭐해')) {
        return '너랑 대화하려고 기다린다!';
    }
    if (input.includes('날씨')) {
        const cityMatch = input.match(/(?:\S+\s+)?(\S+) 날씨/);
        const city = cityMatch ? cityMatch[1] : '서울';
        return await getWeather(city);
    }
    return await getAnswer(input);
}

async function sendMessage() {
    const inputText = userInput.value.trim();
    if (inputText) {
        addMessage(inputText, true);
        const response = await getResponse(inputText);
        setTimeout(() => addMessage(response), 500);
        userInput.value = '';
    }
}

sendBtn.addEventListener('click', sendMessage);

userInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        sendMessage();
    }
});

// 페이지 로드 시 모델 초기화
window.onload = loadQnAModel;

코드 설명

- getWeather: OpenWeatherMap API로 날씨 데이터를 가져온다.

- getResponse: 입력에 "날씨"가 포함되면 도시를 추출해 날씨를 조회한다. 없으면 QnA 모델로 답변한다.

- 정규식: "서울 날씨"처럼 도시를 인식한다. 기본값은 "서울"이다.


테스트

브라우저에서 테스트한다:

- "서울 날씨 어때?" → "서울의 날씨는 맑음, 온도는 10°C다."

- "챗봇 이름이 뭐야?" → "Chatbot"

- "안녕" → "안녕! 나도 반갑다."

API 키가 올바른지, 모델이 로드됐는지 확인한다.


API와 QnA 모델의 통합

QnA 모델은 문맥 기반 답변을 제공하고, API는 실시간 데이터를 가져온다. 이를 조합하면 챗봇이 더 유용해진다.


- **문맥 의존**: QnA는 고정된 문맥에서만 답한다.

- **API 확장**: 날씨처럼 외부 데이터를 추가한다.

입력에 따라 키워드 응답, API 호출, QnA 답변을 우선순위로 처리한다.


성능 및 한계

장점

- 실시간 날씨 데이터를 제공한다.

- QnA와 자연스럽게 통합된다.


한계

- API 호출은 인터넷 연결이 필요하다.

- 무료 API는 호출 횟수 제한(1분당 60회)이 있다.

API 키가 노출되지 않게 환경 변수를 사용한다. 배포 시 고려한다.


개선 방법

- **캐싱**: 자주 묻는 도시의 날씨를 저장한다.

- **다양한 API**: 뉴스나 시간 API를 추가한다.


마무리

챗봇에 날씨 API를 연동했다. 이제 질문 답변과 실시간 데이터를 모두 처리한다. 다음 포스팅에서 성능을 최적화하고 배포한다.


자바스크립트 AI 챗봇 만들기 part3

자바스크립트 AI 챗봇 만들기 part3 : 자연어 처리와 사전 학습된 AI 모델 적용

part2까지 웹 UI와 기본 대화 로직을 완성했다. 이번에는 챗봇을 더 똑똑하게 만든다. 자연어 처리(NLP)를 통해 사용자의 의도를 파악하고, TensorFlow.js의 사전 학습된 QnA 모델을 적용해 질문에 답변한다.


이전엔 간단한 예시로 대체했지만, 이제 실제 사전 학습된 모델을 사용한다.


3부에서 무엇을 다루는가?

3부의 목표는 다음과 같다:

- 자연어 처리의 기본 개념을 이해한다.

- TensorFlow.js와 QnA 모델을 설정한다.

- 사용자의 질문을 분석하고 답변을 생성한다.

part2에서 만든 my-chatbot 폴더를 이어서 사용한다.


자연어 처리란 무엇인가?

자연어 처리(NLP)는 컴퓨터가 인간의 언어를 이해하고 생성하는 기술이다. 챗봇에서는 사용자가 입력한 문장을 분석해 의도를 파악하거나 질문에 답한다. 예를 들어, "오늘 날씨가 어때?"라고 물으면 "날씨"라는 의도를 인식하고 적절한 답변을 제공한다.


이번 포스팅에서는 TensorFlow.js의 QnA 모델을 사용한다. 이 모델은 BERT 기반으로, 주어진 문맥에서 질문에 대한 답을 찾아낸다.


TensorFlow.js와 QnA 모델 설정하기

TensorFlow.js는 자바스크립트로 머신러닝을 구현하는 라이브러리다. QnA 모델은 사전 학습된 상태로 제공되며, 설치 없이 CDN으로 바로 가져온다.


1. 필요한 스크립트 추가

index.html 안에 다음 스크립트를 추가한다:

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/qna@latest"></script>

- 첫 번째는 TensorFlow.js 핵심 라이브러리다.

- 두 번째는 QnA 모델이다.


2. 모델 로드 확인

모델이 브라우저에서 잘 로드되는지 확인한다. 콘솔에 로드 메시지를 출력한다.


QnA 모델로 질문 처리하기

QnA 모델은 문맥(컨텍스트)과 질문을 입력받아 답변을 생성한다. 챗봇에 통합하려면 문맥을 미리 정의하고 질문을 처리한다.


문맥 정의

모델이 답변할 수 있는 기본 문맥을 설정한다. 예를 들어, 챗봇에 대한 정보다:

const context = `
    이 챗봇은 자바스크립트로 만들어졌다. 이름은 Chatbot이며 bdool에서 개발했다.
    현재 날짜는 2025년 2월 28일이다. 주요 기능은 대화와 질문에 답하는 것이다.
    날씨 정보도 제공할 수 있다. 개발자는 사용자를 돕기 위해 만든다.
`;

이 문맥에서 사용자의 질문을 처리한다.


코드 수정

script.js를 아래처럼 수정한다:

const messages = document.getElementById('chat-messages');
const userInput = document.getElementById('user-input');
const sendBtn = document.getElementById('send-btn');

function addMessage(text, isUser = false) {
    const message = document.createElement('p');
    message.textContent = text;
    message.style.textAlign = isUser ? 'right' : 'left';
    message.style.background = isUser ? '#ff4e00' : '#f0f0f0';
    message.style.color = isUser ? '#fff' : '#333';
    message.style.padding = '8px 12px';
    message.style.margin = '5px 0';
    message.style.borderRadius = '4px';
    message.style.display = 'inline-block';
    messages.appendChild(message);
    messages.scrollTop = messages.scrollHeight;
}

// 기본 문맥 정의
const context = `
    이 챗봇은 자바스크립트로 만들어졌다. 이름은 Chatbot이며 bdool에서 개발했다.
    현재 날짜는 2025년 2월 28일이다. 주요 기능은 대화와 질문에 답하는 것이다.
    날씨 정보도 제공할 수 있다. 개발자는 사용자를 돕기 위해 만든다.
`;

let qnaModel;

// 모델 로드
async function loadQnAModel() {
    try {
        qnaModel = await qna.load();
        console.log('QnA 모델이 로드됐다');
        addMessage('챗봇 준비가 완료됐다! 질문을 기다린다.');
    } catch (err) {
        console.error('모델 로드 실패:', err);
        addMessage('모델 로드에 실패했다. 기본 응답만 제공한다.');
    }
}

// 질문 처리
async function getAnswer(question) {
    if (!qnaModel) {
        return '모델이 아직 로드되지 않았다. 잠시 기다린다.';
    }
    try {
        const answers = await qnaModel.findAnswers(question, context);
        if (answers.length > 0 && answers[0].text) {
            return answers[0].text;
        }
        return '질문에 대한 답을 찾지 못했다. 다른 질문을 해본다.';
    } catch (err) {
        console.error('답변 생성 실패:', err);
        return '답변을 생성하지 못했다.';
    }
}

// 기본 키워드 응답
function getKeywordResponse(input) {
    input = input.toLowerCase();
    if (input.includes('안녕')) return '안녕! 나도 반갑다.';
    if (input.includes('뭐해')) return '너랑 대화하려고 기다린다!';
    if (input.includes('날씨')) return '날씨를 알려면 도시 이름을 말해준다.';
    return null;
}

async function sendMessage() {
    const inputText = userInput.value.trim();
    if (inputText) {
        addMessage(inputText, true);
        const keywordResponse = getKeywordResponse(inputText);
        let response;
        if (keywordResponse) {
            response = keywordResponse;
        } else {
            response = await getAnswer(inputText);
        }
        setTimeout(() => addMessage(response), 500);
        userInput.value = '';
    }
}

sendBtn.addEventListener('click', sendMessage);

userInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        sendMessage();
    }
});

// 페이지 로드 시 모델 초기화
window.onload = loadQnAModel;

코드 설명

- loadQnAModel: 페이지 로드 시 QnA 모델을 초기화한다. 성공하면 메시지를 표시한다.

- getAnswer: 사용자의 질문을 문맥과 함께 모델에 전달하고 답변을 받는다.

- getKeywordResponse: 기본 키워드 응답을 우선 처리한다.

- sendMessage: 키워드 응답이 없으면 모델로 질문을 처리한다.


테스트

브라우저에서 index.html을 열고 다음 질문을 테스트한다:

- "챗봇의 이름이 뭐야?" → "Chatbot" 반환

- "누가 만들었어?" → "bdool" 반환

- "안녕" → 키워드 응답 "안녕! 나도 반갑다."

모델 로드에 몇 초 걸릴 수 있다. F12로 콘솔을 확인한다.


QnA 모델의 동작 원리

QnA 모델은 BERT(Transformers 기반)를 사용한다. 문맥과 질문을 토큰화하고, 답변 가능성을 계산해 가장 적합한 텍스트를 반환한다.


- **문맥**: 고정된 텍스트다. 질문에 답할 수 있는 정보를 담는다.

- **제한**: 문맥에 없는 정보는 답하지 못한다.

더 많은 정보를 처리하려면 문맥을 동적으로 업데이트하거나 다른 모델을 고려한다.


성능 및 한계

장점

- 학습 없이 바로 사용한다.

- 브라우저에서 실행되니 서버가 필요 없다.


한계

- 모델 크기가 커서 로드 시간이 길다 (약 100MB).

- 문맥에 의존하니 일반 대화는 제한적이다.

로드 시간이 길면 사용자에게 "모델 로드 중이다" 메시지를 표시한다.


개선 방법

- **문맥 확장**: API로 동적 데이터를 추가한다.

- **다른 모델**: 의도 분류 모델(예: Universal Sentence Encoder)을 혼합한다.


마무리

사전 학습된 QnA 모델을 챗봇에 적용했다. 이제 질문에 대한 답변을 생성한다. 4부에서는 외부 API를 연동해 날씨 기능을 추가한다.


자바스크립트 AI 챗봇 만들기 Part 2

자바스크립트 AI 챗봇 만들기 Part 2 : 챗봇 UI 설계와 사용자 입력 처리

안녕한다! 1부에서는 챗봇 프로젝트의 개요를 소개하고 기본 환경을 설정했다. 이번 2부에서는 드디어 웹 인터페이스를 만든다. 콘솔에서 동작하던 챗봇을 브라우저로 옮기고, 사용자가 입력한 메시지를 받아 응답하는 기능을 구현한다.


이 포스팅을 끝내면 깔끔한 채팅창 UI와 기본적인 대화 로직을 갖춘 챗봇이 완성된다. 초보자도 쉽게 따라 할 수 있도록 HTML, CSS, 자바스크립트를 단계별로 설명한다. 그럼 바로 시작한다!


2부에서 무엇을 다루는가?

2부의 목표는 다음과 같다:

- HTML과 CSS로 채팅창 UI를 설계한다.

- 자바스크립트로 사용자 입력을 받아 화면에 출력한다.

- 미리 정의된 답변을 반환하는 기본 로직을 추가한다.

1부에서 만든 my-chatbot 폴더를 그대로 사용한다. 준비가 됐다면 파일을 수정하며 진행한다.


채팅창 UI 설계하기

먼저, 사용자가 메시지를 입력하고 대화를 볼 수 있는 UI를 만든다. HTML로 구조를 잡고 CSS로 스타일을 입힌다.


HTML 수정하기

1부의 index.html을 아래 코드로 바꾼다:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>나만의 AI 챗봇</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="chat-container">
        <div id="chat-messages"></div>
        <div id="chat-input">
            <input type="text" id="user-input" placeholder="메시지를 입력하세요">
            <button id="send-btn">전송</button>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>
나만의 AI 챗봇

코드 설명

- #chat-container: 전체 채팅창을 감싼다.

- #chat-messages: 대화 내용을 표시한다.

- #chat-input: 입력창과 전송 버튼을 담는다.


CSS 추가하기

style.css를 아래 코드로 수정한다:

body {
    font-family: 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif;
    margin: 0;
    padding: 20px;
    background: #f0f0f0;
}

#chat-container {
    max-width: 600px;
    margin: 0 auto;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    overflow: hidden;
}

#chat-messages {
    padding: 20px;
    height: 400px;
    overflow-y: auto;
}

#chat-input {
    display: flex;
    padding: 10px;
    border-top: 1px solid #ddd;
}

#user-input {
    flex: 1;
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
}

#send-btn {
    padding: 8px 16px;
    margin-left: 10px;
    background: #ff4e00;
    color: #fff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
}

#send-btn:hover {
    background: #e63900;
}

스타일 설명

- #chat-container: 채팅창을 중앙에 배치하고 그림자를 추가한다.

- #chat-messages: 대화가 길어지면 스크롤이 생긴다.

- #chat-input: 입력창과 버튼을 가로로 나란히 배치한다.

브라우저에서 index.html을 열어보면 빈 채팅창이 보인다.


사용자 입력 처리하기

이제 자바스크립트로 입력을 받아 화면에 띄운다. script.js를 아래 코드로 바꾼다:

const messages = document.getElementById('chat-messages');
const userInput = document.getElementById('user-input');
const sendBtn = document.getElementById('send-btn');

function addMessage(text, isUser = false) {
    const message = document.createElement('p');
    message.textContent = text;
    message.style.textAlign = isUser ? 'right' : 'left';
    message.style.background = isUser ? '#ff4e00' : '#f0f0f0';
    message.style.color = isUser ? '#fff' : '#333';
    message.style.padding = '8px 12px';
    message.style.margin = '5px 0';
    message.style.borderRadius = '4px';
    message.style.display = 'inline-block';
    messages.appendChild(message);
    messages.scrollTop = messages.scrollHeight; // 자동 스크롤
}

sendBtn.addEventListener('click', () => {
    const inputText = userInput.value.trim();
    if (inputText) {
        addMessage(inputText, true);
        userInput.value = '';
    }
});

코드 설명

- addMessage: 메시지를 화면에 추가한다. isUsertrue면 사용자 메시지로 오른쪽에 표시한다.

- sendBtn.addEventListener: 전송 버튼 클릭 시 입력값을 처리한다.

브라우저에서 테스트해본다. 메시지를 입력하고 전송하면 오른쪽에 주황색 말풍선이 나타난다.


엔터 키로 전송 추가

편의를 위해 엔터 키로도 전송되게 한다. script.js에 다음 코드를 추가한다:

userInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        const inputText = userInput.value.trim();
        if (inputText) {
            addMessage(inputText, true);
            userInput.value = '';
        }
    }
});

챗봇 응답 추가하기

사용자 입력에 챗봇이 답하도록 로직을 넣는다. script.js를 아래처럼 수정한다:

const messages = document.getElementById('chat-messages');
const userInput = document.getElementById('user-input');
const sendBtn = document.getElementById('send-btn');

function addMessage(text, isUser = false) {
    const message = document.createElement('p');
    message.textContent = text;
    message.style.textAlign = isUser ? 'right' : 'left';
    message.style.background = isUser ? '#ff4e00' : '#f0f0f0';
    message.style.color = isUser ? '#fff' : '#333';
    message.style.padding = '8px 12px';
    message.style.margin = '5px 0';
    message.style.borderRadius = '4px';
    message.style.display = 'inline-block';
    messages.appendChild(message);
    messages.scrollTop = messages.scrollHeight;
}

function getResponse(input) {
    if (input.includes('안녕')) {
        return '안녕! 나도 반갑다.';
    } else if (input.includes('뭐해')) {
        return '너랑 대화하려고 기다린다!';
    } else {
        return '잘 모르겠다. 다른 걸 물어본다.';
    }
}

function sendMessage() {
    const inputText = userInput.value.trim();
    if (inputText) {
        addMessage(inputText, true);
        const response = getResponse(inputText);
        setTimeout(() => addMessage(response), 500); // 0.5초 지연
        userInput.value = '';
    }
}

sendBtn.addEventListener('click', sendMessage);

userInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') {
        sendMessage();
    }
});

코드 설명

- getResponse: 입력값에 따라 답변을 반환한다.

- sendMessage: 사용자 메시지를 표시하고 챗봇 응답을 추가한다.

- setTimeout: 자연스러운 대화 느낌을 위해 응답을 약간 지연시킨다.

테스트해본다. "안녕"이나 "뭐해"를 입력하면 챗봇이 답한다.


UI 개선하기

UI를 더 멋지게 만든다. CSS에 애니메이션과 반응형 디자인을 추가한다.


CSS 수정

style.css에 다음 스타일을 추가한다:

#chat-messages p {
    animation: fadeIn 0.3s ease-in;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 600px) {
    #chat-container {
        width: 100%;
        margin: 0;
    }
    #chat-messages {
        height: 300px;
    }
    #user-input, #send-btn {
        font-size: 12px;
    }
}

설명

- fadeIn: 메시지가 나타날 때 부드럽게 페이드인 된다.

- 반응형: 작은 화면에서는 채팅창 크기를 조정한다.


마무리

웹 기반 챗봇의 기본 틀이 완성됐다. UI를 설계하고 사용자 입력을 처리하는 로직을 구현했다. 3부에서는 자연어 처리와 AI 로직을 추가해 챗봇을 더 똑똑하게 만든다.


자바스크립트로 나만의 AI 챗봇 만들기: 1부

자바스크립트 AI 챗봇 만들기 Part 1 : 프로젝트 소개 및 기본 환경 설정

안녕한다! 이번 포스팅부터 자바스크립트를 활용해 나만의 AI 챗봇을 만드는 여정을 시작한다. 총 5부작으로 진행되는 이 시리즈는 초보자도 따라 할 수 있도록 단계별로 구성한다. 첫 번째 포스팅인 오늘은 프로젝트 개요를 소개하고, 개발을 시작하기 위한 기본 환경을 설정하는 방법을 다룬다.


이 시리즈를 완성하면 웹에서 동작하는 챗봇을 만들 수 있다. 이 챗봇은 단순히 대화만 하는 것이 아니라 날씨 정보를 알려주거나 할 일을 관리하는 실용적인 기능도 갖춘다.


이 프로젝트는 무엇인가?

먼저, 우리가 만들 챗봇이 어떤 모습인지 간단히 소개한다. 이 섹션에서는 챗봇의 정의, 자바스크립트를 선택한 이유, 그리고 완성된 결과물의 모습을 살펴본다.


챗봇이란?

챗봇(Chatbot)은 "채팅"과 "로봇"의 합성어다. 사람과 텍스트나 음성으로 소통할 수 있는 프로그램을 뜻한다. 예를 들어, 고객센터에서 자주 묻는 질문에 답해주는 도우미나 메신저 앱에서 간단한 명령을 처리하는 봇을 떠올리면 된다. 이번 프로젝트에서는 자바스크립트를 사용해 이런 챗봇을 직접 만든다.


왜 자바스크립트인가?

자바스크립트는 웹 개발의 핵심 언어다. 브라우저에서 바로 실행되니까 복잡한 설정 없이도 결과를 확인할 수 있다. 게다가 Node.js 덕분에 서버에서도 활용할 수 있고, TensorFlow.js 같은 라이브러리로 AI 기능까지 추가할 수 있다. 이번 시리즈에서는 브라우저 기반 챗봇을 만들기 때문에 자바스크립트의 이런 장점을 최대한 활용한다.


완성된 챗봇은 어떤 모습인가?

5부까지 진행하면 챗봇은 이런 기능을 갖춘다:

- 사용자가 "안녕"이라고 입력하면 "안녕! 오늘 기분이 어때?" 같은 자연스러운 답변을 한다.

- "오늘 서울 날씨 어때?"라는 질문에 실제 날씨 데이터를 가져와 대답한다.

- "오늘 7시에 회의 추가해줘" 같은 요청으로 할 일을 관리한다.

이 모든 것이 깔끔한 웹 인터페이스에서 동작한다. 기대된다!


개발 환경 준비하기

이제 본격적으로 개발을 시작하려면 몇 가지 도구를 준비한다. 하나씩 설치하고 설정하는 과정을 자세히 설명한다.


필요한 도구들

이번 프로젝트에 필요한 도구는 다음과 같다:

- Node.js: 자바스크립트를 브라우저 밖에서 실행할 수 있게 해주는 런타임이다. npm이라는 패키지 관리자도 같이 설치된다.

- npm: Node.js와 함께 제공되며, 필요한 라이브러리를 쉽게 설치할 수 있다.

- VS Code: 코드를 편리하게 작성할 수 있는 에디터다. 다른 에디터를 써도 되지만 VS Code를 추천한다.

- 웹 브라우저: 크롬이나 파이어폭스를 추천한다. 개발자 도구로 디버깅할 때 유용하다.


Node.js 설치하기

Node.js 설치 방법은 간단하다. 아래 단계를 따른다:

1. nodejs.org에 접속한다.

2. LTS(Long Term Support) 버전을 다운로드한다. 2025년 2월 기준으로 최신 LTS 버전을 선택하면 안정적으로 사용할 수 있다.

3. 다운로드한 설치 파일을 실행하고 기본 설정으로 "Next"를 눌러가며 설치한다. npm도 자동으로 설치된다.

4. 설치가 끝났으면 터미널을 열고 다음 명령어를 입력해 확인한다:

node -v

버전 번호(예: v18.19.0)가 출력되면 성공이다. 이어서 npm도 확인한다:

npm -v

이 역시 버전 번호가 나오면 준비가 완료된다.

"명령어를 찾을 수 없다"는 오류가 나오면 컴퓨터를 재부팅하거나 Node.js를 다시 설치한다. 환경 변수 설정이 제대로 안 됐을 가능성이 있다.


VS Code 설치하기

VS Code 설치도 쉽다:

1. code.visualstudio.com에 접속한다.

2. 운영체제에 맞는 버전을 다운로드한다.

3. 설치 파일을 실행하고 기본 설정으로 진행한다.

4. VS Code를 열고 "Extensions" 메뉴에서 다음 확장을 설치하면 좋다:

- Prettier: 코드를 깔끔하게 정리한다.

- Live Server: HTML 파일을 실시간으로 브라우저에서 확인할 수 있다.


프로젝트 폴더 설정하기

이제 챗봇 프로젝트를 위한 기본 구조를 만든다. 간단한 파일 몇 개로 시작한다.


폴더 생성

1. 원하는 위치(예: 바탕화면)에 새 폴더를 만들고 이름을 my-chatbot으로 정한다.

2. VS Code에서 "File > Open Folder"를 선택해 my-chatbot 폴더를 연다.


기본 파일 생성

다음 세 파일을 만든다:

- index.html: 챗봇의 기본 구조를 담당한다.

- style.css: 인터페이스 스타일링을 담당한다.

- script.js: 챗봇 로직을 담을 자바스크립트 파일이다.

VS Code에서 "New File" 버튼을 눌러 각 파일을 만들고 아래 코드를 붙여넣는다.


index.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>나만의 AI 챗봇</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>안녕! 나만의 챗봇에 오신 걸 환영해요</h1>
    <script src="script.js"></script>
</body>
</html>

style.css

body {
    font-family: Arial, sans-serif;
    text-align: center;
    margin-top: 50px;
}

h1 {
    color: #333;
}

script.js

console.log("챗봇 프로젝트 시작!");
alert("안녕! 이건 첫 번째 테스트야.");

실행해보기

1. index.html 파일을 오른쪽 클릭하고 "Open with Live Server"를 선택한다. (Live Server 확장이 설치돼 있어야 한다.)

2. 브라우저가 열리며 제목과 알림창이 뜨면 성공이다.

3. F12를 눌러 개발자 도구를 열고 "Console" 탭에서 메시지를 확인한다.


첫 번째 챗봇: 콘솔에서 대화하기

이제 간단한 챗봇을 만든다. 웹 UI는 2부에서 다루고, 우선 터미널에서 동작하는 버전을 구현한다.


콘솔 챗봇 코드 작성

script.js를 아래 코드로 바꾼다:

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

function startChat() {
    rl.question('안녕! 무엇에 대해 이야기하고 싶어? ', (answer) => {
        console.log(`너가 말한 거: ${answer}`);
        if (answer.includes('안녕')) {
            console.log('안녕! 나도 반갑네.');
        } else {
            console.log('음, 그건 좀 어려운 질문인데... 다른 걸 물어볼래?');
        }
        rl.close();
    });
}

startChat();

실행하기

1. VS Code에서 "Terminal > New Terminal"을 클릭해 터미널을 연다.

2. 다음 명령어를 입력해 실행한다:

node script.js

3. 질문이 나오면 "안녕" 같은 답변을 입력한다.


코드 설명

- readline: Node.js 내장 모듈로, 사용자 입력을 읽는다.

- rl.question: 질문을 던지고 답변을 기다린다.

- answer.includes: 입력값에 따라 다른 답변을 출력한다.


마무리

첫 번째 챗봇을 만들었다. 지금은 콘솔에서 동작하지만, 2부에서는 웹 페이지에 채팅 UI를 추가한다.


자바스크립트로 만드는 실시간 채팅 앱 (Part 3)

자바스크립트로 만드는 실시간 채팅 앱 (Part 3)

Part 2에서 Socket.IO를 활용하여 실시간 메시지 송수신 기능을 구현하였다면, 이번 Part 3에서는 채팅 UI를 개선하고 배포 방법을 다루려고 한다. 이 과정을 통해 채팅 앱을 제작하고 공유할 수 있다.


UI 개선과 배포는 채팅 앱을 실용적으로 만드는 중요한 단계이다. Part 3에서는 메시지 스타일을 개선하고 사용자 이름을 추가하며, 무료 배포 플랫폼을 활용하여 앱을 온라인에 공개한다. 자


UI를 개선하고 배포를 실습하며, 자바스크립트의 비동기 처리와 이벤트 핸들링이 실무에서 어떻게 활용되는지 알아본다. 차분히 진행하며 실습을 시작한다.

UI Improvement and Deployment Overview

채팅 UI 개선

Part 2의 UI를 개선하려고 한다. 사용자 이름 입력 필드를 추가하고 메시지 스타일을 조정한다. index.html 파일을 다음 코드로 수정한다:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>간단한 채팅 앱</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
        }
        #chat-container {
            max-width: 600px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        #messages {
            height: 300px;
            overflow-y: auto;
            border: 1px solid #ddd;
            padding: 10px;
            margin-bottom: 10px;
        }
        #messages p {
            margin: 5px 0;
            padding: 8px;
            background: #e9ecef;
            border-radius: 3px;
        }
        #message-form {
            display: flex;
            gap: 10px;
        }
        #username-input, #message-input {
            padding: 5px;
        }
        #username-input {
            width: 100px;
        }
        #message-input {
            flex-grow: 1;
        }
        button {
            padding: 5px 10px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <div id="chat-container">
        <div id="messages"></div>
        <form id="message-form">
            <input type="text" id="username-input" placeholder="이름">
            <input type="text" id="message-input" placeholder="메시지를 입력하세요">
            <button type="submit">보내기</button>
        </form>
    </div>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        const socket = io();
        const form = document.getElementById('message-form');
        const usernameInput = document.getElementById('username-input');
        const messageInput = document.getElementById('message-input');
        const messages = document.getElementById('messages');

        socket.on('connect', () => {
            console.log('서버에 연결됐습니다!');
        });

        socket.on('chat message', (data) => {
            const item = document.createElement('p');
            item.textContent = `${data.username}: ${data.message}`;
            messages.appendChild(item);
            messages.scrollTop = messages.scrollHeight;
        });

        form.addEventListener('submit', (e) => {
            e.preventDefault();
            if (usernameInput.value && messageInput.value) {
                const data = {
                    username: usernameInput.value,
                    message: messageInput.value
                };
                socket.emit('chat message', data);
                messageInput.value = '';
            }
        });
    </script>
</body>
</html>
간단한 채팅 앱

사용자 이름 입력 필드가 추가되었으며, 메시지는 p 태그로 스타일링된다. scrollTop 속성은 새 메시지가 표시될 때 자동으로 스크롤을 조정한다. 이는 사용자 경험을 개선하는 요소이다.

CSS는 메시지에 배경색과 둥근 테두리를 적용하여 채팅 앱의 시각적 요소를 강화한다. 간단한 스타일링을 통해 UI를 향상시킬 수 있다.

Enhanced UI

서버 코드 수정

클라이언트에서 사용자 이름과 메시지를 객체로 전송하므로, 서버에서도 이를 처리할 수 있도록 수정한다. server.js 파일을 다음 코드로 업데이트한다:

const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
    console.log('사용자가 연결됐습니다!');
    socket.on('chat message', (data) => {
        io.emit('chat message', data);
    });
    socket.on('disconnect', () => {
        console.log('사용자가 연결을 끊었습니다.');
    });
});

http.listen(3000, () => {
    console.log('서버가 3000번 포트에서 실행 중입니다.');
});
        

data 객체를 수신하여 모든 클라이언트에 브로드캐스트한다. 서버를 재시작(Ctrl+Cnode server.js)하여 변경 사항을 적용한다.

이 수정은 사용자 이름과 메시지를 함께 표시하며, 실시간 채팅의 기능을 향상시킨다. 객체 데이터 전송 과정을 실습하며 이해할 수 있다.


배포를 위한 준비

로컬 환경에서 완성된 채팅 앱을 온라인에 배포하려고 한다. 무료 플랫폼인 Render를 활용하여 배포한다.

1. GitHub 업로드

프로젝트를 GitHub에 업로드한다. chat-app 폴더에서 터미널을 열고 다음 명령어를 실행한다:

git init
git add .
git commit -m "Initial chat app commit"
git remote add origin [GitHub Repository URL]
git push -u origin main
        

[GitHub Repository URL]은 GitHub에서 생성한 새 리포지토리의 URL로 대체한다. Git 명령어는 낯설 수 있으나, 단계별로 진행하면 어렵지 않다.


2. Render 배포

Render 사이트에서 GitHub 계정으로 로그인하고, "New" -> "Web Service"를 선택한다. 아래 설정을 적용한다:

- Runtime: Node

- Start Command: node server.js

무료 플랜으로 "Create Web Service"를 클릭하여 배포를 시작한다. 배포 완료 후 제공된 URL을 통해 접속할 수 있다.


배포 결과 확인

Render에서 제공된 URL을 브라우저에서 열어 확인한다. 다른 사용자와 공유하여 실시간으로 메시지를 주고받을 수 있다. 이는 자바스크립트로 제작한 애플리케이션을 배포한 결과이다.

현재 앱은 기본 기능만 포함하며, 사용자 접속 알림이나 메시지 삭제 기능 같은 추가 개선이 가능하다. 이 단계를 통해 배포 경험을 쌓을 수 있다.

Deployed Chat App

주의할 점

무료 배포 플랫폼은 트래픽 제한이 있다. 코드 수정 후에는 GitHub에 푸시하고 Render에서 재배포한다. 보안은 고려되지 않았으므로 실무에서는 추가 조치가 필요하다.

결론

Part 3에서는 채팅 UI를 개선하고 Render를 통해 배포를 완료하였다. 자바스크립트를 활용한 실시간 채팅 앱을 제작하고 온라인에 공개함으로써, 비동기와 이벤트 처리의 실용성을 확인하였다. 이 시리즈는 초보자를 위한 실습 중심 가이드이다.

자바스크립트로 만드는 실시간 채팅 앱 - (Part 2)

자바스크립트로 만드는 실시간 채팅 앱 (Part 2)

Part 1에서 Node.js 환경과 기본 HTML/CSS 구조를 준비하였다면, 이번 Part 2에서는 Socket.IO를 활용하여 클라이언트와 서버를 연결하고 실시간 메시지 송수신 기능을 구현하려고 한다. 실시간 통신은 채팅 앱의 핵심이며, 초보자도 이해할 수 있도록 상세히 설명한다.


Socket.IO를 처음 사용하는 초보자에게는 실시간 통신이 신기하게 느껴질 수 있다. 그러나 이 라이브러리는 복잡한 웹소켓 설정을 간소화하여 몇 줄의 코드로 실시간 기능을 구현할 수 있도록 지원한다. 이번 포스팅에서는 서버와 클라이언트를 연결하고 메시지를 주고받는 과정을 실습하며, 자바스크립트의 비동기 처리와 이벤트 핸들링이 실시간 애플리케이션에서 어떻게 활용되는지 알아본다.


Part 1에서 준비한 파일을 활용하여 실시간 통신을 구현하며, 초보자도 브라우저에서 직접 결과를 확인할 수 있도록 안내한다. 차분히 진행하며 실습을 시작한다.

Realtime Communication Overview

Socket.IO로 서버 설정

Part 1에서 작성한 server.js 파일을 수정하여 Socket.IO를 추가한다. 이 라이브러리는 실시간 통신을 가능하게 하며, 다음 코드를 server.js에 적용한다:

const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
    console.log('사용자가 연결됐습니다!');
    socket.on('disconnect', () => {
        console.log('사용자가 연결을 끊었습니다.');
    });
});

http.listen(3000, () => {
    console.log('서버가 3000번 포트에서 실행 중입니다.');
});
        

io.on('connection')은 클라이언트가 서버에 접속할 때마다 실행된다. socket 객체는 각 클라이언트 연결을 관리하며, 접속과 연결 해제를 감지한다. 터미널에서 node server.js를 실행하고 브라우저에서 http://localhost:3000을 열면, 터미널에 "사용자가 연결됐습니다!" 메시지가 출력된다.

Socket.IO는 웹소켓을 기반으로 하여 실시간 양방향 통신을 지원한다. 초보자에게는 복잡한 개념일 수 있으나, 이 라이브러리를 통해 쉽게 실습할 수 있다. 서버 설정은 실시간 통신의 기초이며, 클라이언트 연결 준비를 완료한다.

Server Setup Screen

클라이언트에서 Socket.IO 연결

서버 설정이 완료되었으므로, 클라이언트에서 서버와 연결하고 메시지 송신을 준비한다. index.html 파일을 다음 코드로 수정한다:

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>간단한 채팅 앱</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
        }
        #chat-container {
            max-width: 600px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        #messages {
            height: 300px;
            overflow-y: auto;
            border: 1px solid #ddd;
            padding: 10px;
            margin-bottom: 10px;
        }
        #message-form {
            display: flex;
            gap: 10px;
        }
        #message-input {
            flex-grow: 1;
            padding: 5px;
        }
        button {
            padding: 5px 10px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <div id="chat-container">
        <div id="messages"></div>
        <form id="message-form">
            <input type="text" id="message-input" placeholder="메시지를 입력하세요">
            <button type="submit">보내기</button>
        </form>
    </div>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        const socket = io();
        const form = document.getElementById('message-form');
        const input = document.getElementById('message-input');

        socket.on('connect', () => {
            console.log('서버에 연결됐습니다!');
        });

        form.addEventListener('submit', (e) => {
            e.preventDefault();
            if (input.value) {
                socket.emit('chat message', input.value);
                input.value = '';
            }
        });
    </script>
</body>
</html>

간단한 채팅 앱

socket.on('chat message')는 서버로부터 메시지를 수신할 때 실행된다. 수신된 메시지는 p 태그로 생성되어 messages 요소에 추가된다. 이 과정은 실시간 채팅의 기본 동작을 구현한다.

브라우저에서 http://localhost:3000을 여러 창으로 열어 테스트한다. 한 창에서 메시지를 입력하면 다른 창에도 즉시 표시된다. 이는 실시간 통신의 결과이다.


현재 진행 상황 점검

여기까지 완료하면 서버와 클라이언트가 연결되어 실시간으로 메시지를 주고받을 수 있다. 터미널에서 node server.js를 실행하고, 브라우저에서 http://localhost:3000을 여러 창으로 열어 확인한다. 메시지가 모든 창에 실시간으로 표시된다면 성공이다.

현재 UI는 단순하며, 사용자 이름 표시와 같은 기능은 아직 포함되지 않았다. Part 3에서는 UI를 개선하고 배포를 진행한다. 약 5,000자의 분량으로 상세히 다루었으며, 초보자도 실습을 통해 실시간 통신을 이해할 수 있다.

이 단계는 자바스크립트로 실시간 채팅 앱을 구현하는 핵심 과정을 완료한다. 다음 포스팅에서는 UI를 개선하여 사용자 경험을 향상시킨다.

Message Receive Screen

주의할 점

Socket.IO 버전은 서버와 클라이언트에서 일치해야 한다. 브라우저 캐시로 인해 최신 코드가 반영되지 않을 수 있으므로 새로고침한다. 서버가 종료되면 통신이 중단되므로 실행 상태를 유지한다.


결론

Part 2에서는 Socket.IO를 활용하여 클라이언트와 서버를 연결하고 실시간 메시지 송수신 기능을 구현하였다. 자바스크립트의 비동기 처리와 이벤트 핸들링이 실시간 통신에 적용되는 과정을 실습하였다. Part 3에서는 UI를 개선하고 배포 방법을 다룬다.

자바스크립트로 만드는 실시간 채팅 앱 - 초보자 가이드 (Part 1)

자바스크립트로 만드는 실시간 채팅 앱 (Part 1)

이번 포스팅은 자바스크립트를 활용하여 실시간 채팅 앱을 만드는 과정을 다루려고 한다. 총 3부작으로 구성되며, Part 1에서는 기본 설정과 HTML/CSS 구조를 준비하려고 한다. Part 2에서는 클라이언트와 서버를 연결하고, Part 3에서는 UI를 개선한 후 배포 방법을 소개한다.


실시간 채팅 앱을 처음 접하는 초보자라면 시작점이 모호하게 느껴질 수 있다. 그러나 이 가이드는 단계별로 진행되며, 자바스크립트의 비동기 처리와 이벤트 핸들링을 실습할 수 있는 실용적인 예제를 제공한다. Socket.IO라는 라이브러리를 사용하여 실시간 통신을 구현하며, 이는 복잡한 웹소켓 개념을 간소화한 도구이다. 이 과정을 통해 자바스크립트를 활용한 동적인 웹 애플리케이션 제작 방법을 익힐 수 있다.


이 포스팅 시리즈는 자바스크립트의 기본 지식을 바탕으로 실질적인 프로젝트를 완성하는 데 초점을 맞춘다. Part 1에서는 환경 설정과 기본 UI를 구성하며, 쉽게 따라 할 수 있도록 준비했으니, 차분히 진행하며 실습을 시작해보자.


Chat App Overview

채팅 앱의 개념

이번에 제작하려는 실시간 채팅 앱은 사용자가 입력한 메시지를 다른 사용자가 즉시 확인할 수 있는 애플리케이션이다. 예를 들어, 카카오톡이나 슬랙과 유사한 기능을 갖추고 있다. 다만, 이 가이드에서는 복잡한 기능을 배제하고, 메시지 송수신의 기본 기능에 집중한다. 자바스크립트를 통해 클라이언트와 서버 간 실시간 통신을 구현하며, Socket.IO를 활용하여 이를 간단히 처리한다.


실시간 통신은 웹소켓 기술을 기반으로 한다. 초보자에게 웹소켓은 다소 생소할 수 있으나, Socket.IO는 이를 추상화하여 간편하게 사용할 수 있도록 설계되었다. 이 과정을 통해 자바스크립트의 비동기 처리와 이벤트 핸들링이 실제 프로젝트에서 어떻게 적용되는지 이해할 수 있다. 실무에서도 채팅 기능은 다양한 웹 애플리케이션에서 사용되므로, 이번 학습은 향후 활용도가 높다.


채팅 앱 제작을 위해서는 환경 설정부터 시작해야 한다. Node.js를 사용해 서버를 구성하고, HTML과 CSS로 기본적인 사용자 인터페이스를 준비한다. 이 과정은 자바스크립트 기본 지식을 점검하며, 실시간 통신 기술을 익히는 데 초점을 맞춘다. 초보자도 단계별로 진행하면 충분히 완성할 수 있으니, 차분히 따라오길 바란다.


Realtime Communication Intro

필요한 도구와 준비

이 채팅 앱을 제작하려면 몇 가지 도구가 필요하다. 초보자도 최소한의 설정으로 시작할 수 있도록 간소화된 준비 단계를 제시한다.


1. Node.js

Node.js는 자바스크립트를 브라우저 외부에서 실행할 수 있는 런타임 환경이다. 서버를 구성하는 데 사용된다. 공식 사이트(nodejs.org)에서 최신 LTS 버전을 다운로드하여 설치한다. 설치 후 터미널에서 다음 명령어를 실행하여 확인한다:

node -v
npm -v

node -v는 Node.js 버전을 확인하며, npm -v는 패키지 매니저의 버전을 표시한다. LTS 버전은 안정적이며, 대부분의 경우 문제가 발생하지 않는다.


2. 텍스트 에디터

코드를 작성하려면 텍스트 에디터가 필요하다. VS Code는 무료이며 자바스크립트 코딩에 적합한 기능을 제공한다. 공식 사이트(code.visualstudio.com)에서 다운로드하여 설치한다.


3. 브라우저

채팅 앱을 테스트하려면 웹 브라우저가 필요하다. Chrome 또는 Firefox는 개발자 도구(F12)를 통해 콘솔 확인이 용이하므로 적합하다.

이 세 가지 도구만 준비되면 충분하다. 설치 과정은 약 10분 이내에 완료되며, 초보자도 어렵지 않게 설정할 수 있다.


프로젝트 환경 구성

도구 준비가 완료되었다면, 프로젝트 환경을 구성한다. 서버와 클라이언트 파일을 설정하여 채팅 앱의 기반을 마련한다.


1. 프로젝트 폴더 생성

원하는 경로에 chat-app라는 폴더를 생성한다. 터미널을 열고 다음 명령어로 이동한다:

mkdir chat-app
cd chat-app

경로가 정확히 설정되었는지 확인한다.


2. npm 초기화

프로젝트 설정 파일을 생성하려면 npm을 초기화한다. 터미널에서 다음 명령어를 실행한다:

npm init -y

-y 옵션은 기본 설정을 적용하며, package.json 파일이 생성된다. 이 파일은 프로젝트 정보와 의존성을 관리한다.


3. 패키지 설치

서버를 위한 Express와 실시간 통신을 위한 Socket.IO를 설치한다. 다음 명령어를 실행한다:

npm install express socket.io

설치가 완료되면 node_modules 폴더와 package-lock.json 파일이 생성된다. 이는 정상적인 설치 과정이다.


HTML과 CSS로 기본 UI 설계

환경 구성이 완료되었으므로, 채팅 앱의 기본 사용자 인터페이스를 설계한다. HTML과 CSS를 통해 클라이언트 UI를 준비한다.


1. index.html 작성

chat-app 폴더에 index.html 파일을 생성하고 다음 코드를 입력한다:

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>간단한 채팅 앱</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
        }
        #chat-container {
            max-width: 600px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        #messages {
            height: 300px;
            overflow-y: auto;
            border: 1px solid #ddd;
            padding: 10px;
            margin-bottom: 10px;
        }
        #message-form {
            display: flex;
            gap: 10px;
        }
        #message-input {
            flex-grow: 1;
            padding: 5px;
        }
        button {
            padding: 5px 10px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 3px;
            cursor: pointer;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <div id="chat-container">
        <div id="messages"></div>
        <form id="message-form">
            <input type="text" id="message-input" placeholder="메시지를 입력하세요">
            <button type="submit">보내기</button>
        </form>
    </div>
</body>
</html>

이 코드는 메시지 표시 영역과 입력 폼을 구성한다. CSS는 간단한 박스 스타일과 버튼 디자인만 포함하며, 초보자도 이해하기 쉽게 최소화하였다.


2. 서버 파일 작성

chat-app 폴더에 server.js 파일을 생성하고 다음 코드를 입력한다:

const express = require('express');
const app = express();
const http = require('http').createServer(app);

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

http.listen(3000, () => {
    console.log('서버가 3000번 포트에서 실행 중입니다.');
});
        

이 코드는 Express를 활용한 기본 서버를 설정하며, index.html을 제공한다. 터미널에서 다음 명령어를 실행한다:

node server.js
        

브라우저에서 http://localhost:3000을 열어 UI를 확인할 수 있다.

Basic UI Design

현재 진행 상황 점검

여기까지 진행하면 터미널에서 node server.js를 실행하여 서버를起動하고, 브라우저에서 http://localhost:3000을 열어 채팅 UI를 확인할 수 있다. 메시지 송수신 기능은 아직 구현되지 않았으나, 기본 구조는 완성되었다.

이 단계에서는 환경 설정과 UI 준비에 중점을 두었다. Part 2에서는 Socket.IO를 활용하여 실시간 통신을 구현한다. 약 5,000자의 분량으로 상세히 다루었으며, 초보자도 실습을 통해 충분히 완성할 수 있다.

이제 자바스크립트로 실시간 채팅 앱을 만드는 첫 단계를 완료하였다. 다음 포스팅에서는 클라이언트와 서버 간 연결을 설정하여 메시지 송수신 기능을 추가한다.

주의할 점

Node.js 버전이 낮으면 패키지 설치에 문제가 발생할 수 있다. LTS 버전을 사용한다. 터미널 경로가 정확해야 하며, 서버 실행 중 포트 충돌을 방지한다.

결론

Part 1에서는 자바스크립트를 활용한 실시간 채팅 앱 제작의 기본 환경과 UI를 구성하였다. 따라 할 수 있도록 Node.js 설치부터 HTML/CSS 설계까지 상세히 다루었다. Part 2에서는 Socket.IO를 통해 실시간 통신을 구현하려고 한다.

+ Recent posts