1. 개요
저번 글에 이어서 Web부분을 마저 알아보도록 하겠습니다.
저번글을 읽지 않으신 분들은 저번 글을 읽고 와주시면 흐름을 이해하실 수 있습니다.
2024.10.06 - [AI/LLM] - 누구나 쉽게 만드는 LLM을 활용한 챗봇(Web)
누구나 쉽게 만드는 LLM을 활용한 챗봇(Web)
1. 개요지난 글에서 챗봇을 만드는 글을 올렸습니다. 구현한 챗봇은 CLI환경에서 작동하는 형태였는데, 현 시중에 나와있는 ChatGPT나 Gemini등 다양한 챗봇들은 Web Server를 통해 GUI환경으로 보여집니
area51.tistory.com
2. Web 구현
가. Login.js
모듈 임포트를 먼저 진행합니다.
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
Login에 대한 컴포넌트를 정의합니다.
이때 setToken이라는 prop를 받도록 설정합니다.
const Login = ({ setToken }) => {
ID와 PW를 받아 로그인을 진행하기 때문에 변수를 빈 문자열로 설정하여 선언하고, 페이지 이동을 위한 함수를 설정합니다.
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
이제 로그인 로직을 작성해줍니다.
const handleLogin = async (e) => {
e.preventDefault();
const response = await fetch('http://localhost:8000/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (response.ok) {
const data = await response.json(); // 로그인 응답에서 사용자ID 가져오기
setToken(data.token); // 서버가 사용자 ID를 반환
localStorage.setItem('token', data.token);
navigate(`/chat/${data.token}`);
} else {
alert('로그인에 실패했습니다.');
}
};
- handleLogin 함수는 폼 제출 시 호출되고, e.preventDefault()를 통해 기본 폼 제출 동작을 방지합니다.
- fetch를 사용하여 서버의 /login 엔드포인트에 POST 요청을 보냅니다. username과 password가 JSON 형식으로 포함됩니다.
- 응답이 성공적(response.ok)일 경우 응답 데이터를 JSON으로 파싱하여 data에 저장합니다.
- setToken(data.token)을 호출하여 상위 컴포넌트에 토큰을 전달합니다.
- localStorage에 토큰을 저장하여 브라우저에 유지시킵니다.
- navigate를 사용하여 /chat/${data.token} 경로로 이동합니다.
- 응답이 실패할 경우, 사용자에게 로그인 실패 메시지를 알립니다.
return (
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<div className="bg-white p-8 rounded shadow-md w-full max-w-md">
<h1 className="text-2xl font-bold mb-6 text-center">로그인</h1>
<form onSubmit={handleLogin}>
<div className="mb-4">
<label className="block mb-1">아이디</label>
<input
type="text"
className="w-full p-2 border border-gray-300 rounded"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
</div>
<div className="mb-4">
<label className="block mb-1">비밀번호</label>
<input
type="password"
className="w-full p-2 border border-gray-300 rounded"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<button
type="submit"
className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
>
로그인
</button>
</form>
<div className="flex justify-between mt-4">
<button
onClick={() => navigate('/signup')}
className="text-blue-500 hover:underline"
>
회원가입
</button>
</div>
</div>
</div>
);
화면 단에 나올 부분을 작성을 하였습니다.
CSS는 Tailwind css를 사용하였는데 아직 꾸미지 않아서 자신에 맞게 꾸며 주시면 됩니다.
나. SignupPage.js
회원가입 페이지입니다.
보통 회원가입을 할때 들어가는 요소는 이름, 아이디, 패스워드, 이메일, 핸드폰 번호, 주소, 인증 등 여러가지 요소들이 있는데, 저는 간단하게 이름이랑 아이디 패스워드 정도만 받도록 하겠습니다.
function SignupPage() {
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
POST방식으로 이름과 아이디, 패스워드를 JSON형식으로 받습니다.
response값이 정상이라면 /login으로 이동하도록 합니다.
const handleSignup = async (e) => {
e.preventDefault();
const response = await fetch('http://localhost:8000/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, username, password }),
});
if (response.ok) {
alert('회원가입이 완료되었습니다. 승인을 기다려주세요.');
navigate('/login'); // 회원가입 후 로그인 페이지로 이동
} else {
const errorData = await response.json();
alert(errorData.detail);
}
};
그리고 웹에 나타나는 부분을 작성해주면 됩니다.
return (
<form onSubmit={handleSignup}>
<label>이름</label>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} required />
<label>아이디</label>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} required />
<label>비밀번호</label>
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
<button type="submit">회원가입</button>
</form>
);
}
다. AdminPage.js
관리자 페이지를 만들어 줍니다.
관리자는 사용 신청한 사람들을 승인해주는 기능을 가지고 있습니다.
추후에는 사용자 목록을 나타내는 기능도 넣을 예정입니다.
먼저 승인되지 않은 사람들의 목록을 가져옵니다.
useEffect(() => {
const fetchUsers = async () => {
const response = await fetch('http://localhost:8000/admin/unapproved');
const data = await response.json();
setUsers(data);
};
fetchUsers();
}, []);
승인을 하는 로직을 작성합니다. 승인된 사용자는 목록에서 제외됩니다.
const approveUser = async (username) => {
const response = await fetch(`http://localhost:8000/admin/approve/${username}`, { method: 'POST' });
if (response.ok) {
alert(`${username}님이 승인되었습니다.`);
setUsers(users.filter(user => user.username !== username));
} else {
alert('승인에 실패했습니다.');
}
};
이제 웹 페이지를 작성합니다.
return (
<div>
<h1>관리자 페이지</h1>
<ul>
{users.map(user => (
<li key={user.username}>
{user.username} - {user.name}
<button onClick={() => approveUser(user.username)}>승인</button>
</li>
))}
</ul>
</div>
);
}
'AI > LLM' 카테고리의 다른 글
누구나 쉽게 만드는 LLM을 활용한 챗봇(Web) (1) | 2024.10.06 |
---|---|
누구나 쉽게 만드는 LLM을 활용한 챗봇 (2) | 2024.09.18 |
댓글