Sign In

ALL THE 개발.

개발
: 프론트 엔드 : 프레이머
: 백엔드 :
: AI : 검색엔진 도입
1.
결론
로그인, 닉네임 설정, 마이페이지 등의 기능은 모두 데이터베이스와 밀접하게 연결되어 있습니다. 데이터베이스는 모든 사용자 데이터를 안전하고 구조적으로 관리하며, 이러한 데이터를 기반으로 다양한 기능을 제공합니다.
유사한 시스템을 구현하고 싶다면:
HTML/CSS/JavaScript로 UI를 만들고.
Node.js 같은 백엔드 기술로 데이터베이스와 연결.
MySQL 같은 데이터베이스로 사용자 정보를 저장.
추가로 더 알고 싶거나 구현 관련 질문이 있으면 말씀해주세요! 😊
올디의 모티브 사이트 : 오픈 (셀바이 뮤직)
>>> 피그마 플러그인에 셀바이 뮤직을 가져와서
프레이머로 연동시켜서 ALLTHE를 만들고
그냥 거의 셀바이뮤직하고 똑같이 만들고 관련 유튜브 컨텐츠만 추천해줘
댓글하고 로그인 기능만 연동시키면 돼.
12월 7일 한 일
1.
네이버 로그인 연동하기
>>> 네이버 개발자 센터에 접속해서 로그인 후 api 발급받기.
클라이언트 ID :DeOYaYTehrjPqXJDFGaj
클라이언트 시크릿 : p5z4GImj9T
이용약관 페이지 작성을 완료하였다 html 코드는 termofservice.html이다.
현재 데이터 베이스를 연동하기 전, 즉 chatgtp 응답 반환까지 성공한 index.js의 백엔드 코드는

import OpenAI from 'openai';
import dotenv from 'dotenv';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors'; // CORS 모듈 가져오기
import path from 'path';
import { fileURLToPath } from 'url';
import session from 'express-session';
import passport from 'passport';
import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
import { Strategy as KakaoStrategy } from 'passport-kakao';
import { Strategy as NaverStrategy } from 'passport-naver';
import mysql from 'mysql2/promise'; // MySQL2의 Promise 기반 연결
// __dirname 설정 (ES 모듈 환경용)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 환경 변수 로드
dotenv.config();
// Express 앱 생성
const app = express();
// 세션 설정
app.use(
session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
// OpenAI 클라이언트 설정
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// MySQL 데이터베이스 연결 설정
let db; // 전역 변수로 설정하여 어디에서든 사용 가능하도록
(async () => {
try {
db = await mysql.createConnection({
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'myapp',
});
console.log('MySQL Connected');
} catch (err) {
console.error('MySQL Connection Error:', err);
}
})();
// OpenAI API 요청 함수
async function getChatCompletion(userMessage) {
try {
const completion = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [
{ role: "system", content: "당신은 ALLTHE라는 정보 검색 서비스의 조력자입니다. ALLTHE는 각종 플랫폼, 노마드, 사이트 정보를 담고 있습니다." },
{ role: "user", content: userMessage } // 사용자의 메시지를 추가
]
});
    const hallo = completion.choices[0].message.content; // 응답을 hallo 변수에 저장
    console.log(hallo); // 응답을 콘솔에 출력
    return hallo; // hallo 값을 반환
} catch (error) {
    console.error("Error with OpenAI API:", error.response ? error.response.data : error.message);
    throw new Error('Failed to get response from OpenAI API');
}
}
// Passport 직렬화/역직렬화 설정
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
// Google OAuth 설정
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
},
async (accessToken, refreshToken, profile, done) => {
try {
const [rows] = await db.execute(
'SELECT * FROM users WHERE provider = ? AND provider_id = ?',
['google', profile.id]
);
            if (rows.length === 0) {
                await db.execute(
                    'INSERT INTO users (username, email, provider, provider_id, profile_picture) VALUES (?, ?, ?, ?, ?)',
                    [profile.displayName, profile.emails[0].value, 'google', profile.id, profile.photos[0]?.value]
                );
            }
            return done(null, profile);
        } catch (err) {
            console.error('Google Auth Error:', err);
            return done(err, null);
        }
    }
)
);
// Kakao OAuth 설정
passport.use(
new KakaoStrategy(
{
clientID: process.env.KAKAO_CLIENT_ID,
callbackURL: '/auth/kakao/callback',
},
async (accessToken, refreshToken, profile, done) => {
try {
const [rows] = await db.execute(
'SELECT * FROM users WHERE provider = ? AND provider_id = ?',
['kakao', profile.id]
);
            if (rows.length === 0) {
                await db.execute(
                    'INSERT INTO users (username, provider, provider_id, profile_picture) VALUES (?, ?, ?, ?)',
                    [profile.displayName || profile.username, 'kakao', profile.id, profile._json.properties.profile_image]
                );
            }
            return done(null, profile);
        } catch (err) {
            console.error('Kakao Auth Error:', err);
            return done(err, null);
        }
    }
)
);
// Naver OAuth 설정
passport.use(
new NaverStrategy(
{
clientID: process.env.NAVER_CLIENT_ID,
clientSecret: process.env.NAVER_CLIENT_SECRET,
callbackURL: '/auth/naver/callback',
},
async (accessToken, refreshToken, profile, done) => {
try {
const [rows] = await db.execute(
'SELECT * FROM users WHERE provider = ? AND provider_id = ?',
['naver', profile.id]
);
            if (rows.length === 0) {
                await db.execute(
                    'INSERT INTO users (username, email, provider, provider_id, profile_picture) VALUES (?, ?, ?, ?, ?)',
                    [profile.displayName, profile.emails[0]?.value, 'naver', profile.id, profile._json.profile_image]
                );
            }
            return done(null, profile);
        } catch (err) {
            console.error('Naver Auth Error:', err);
            return done(err, null);
        }
    }
)
);
// Express 서버 설정 및 실행 함수
function startServer() {
app.use(cors()); // CORS 설정 추가
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// 정적 파일 경로 설정
const frontendPath = path.join(__dirname, '../frontend');
app.use(express.static(frontendPath));

// 기본 경로에서 index.html 제공
app.get('/', (req, res) => {
    res.sendFile(path.join(frontendPath, 'index.html'));
});

// OpenAI POST 요청 처리
app.post('/hallo', async (req, res) => {
    const userMessage = req.body.message;
    try {
        const hallo = await getChatCompletion(userMessage);
        res.json({ response: hallo });
    } catch (error) {
        res.status(500).json({ error: 'Error occurred while fetching the response.' });
    }
});

// 로그인 라우트 (Google, Kakao, Naver 등 추가)

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
}
// 서버 시작
startServer();
admin 페이지 (데이터베이스 패치하기전)
header {
background-color: #333;
color: #fff;
padding: 20px;
text-align: center;
}
main {
padding: 20px;
}
nav {
margin-bottom: 20px;
display: flex;
gap: 10px;
}
.tab-button {
padding: 10px 20px;
border: none;
background-color: #ddd;
cursor: pointer;
transition: background-color 0.3s;
}
.tab-button.active {
background-color: #333;
color: #fff;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
table th, table td {
border: 1px solid #ddd;
padding: 10px;
text-align: center;
}
button {
padding: 10px 20px;
background-color: #333;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #555;
}
</style>
<main>
    <!-- 탭 메뉴 -->
    <nav>
        <button class="tab-button active" data-tab="uploads">업로드 정보 관리</button>
        <button class="tab-button" data-tab="chat-rooms">아바타 채팅방 관리</button>
        <button class="tab-button" data-tab="personalization">개인화 페이지 관리</button>
    </nav>

    <!-- 업로드된 정보 관리 -->
    <section id="uploads" class="tab-content active">
        <h2>업로드된 정보 관리</h2>
        <table id="uploadTable">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>제목</th>
                    <th>카테고리</th>
                    <th>내용</th>
                    <th>액션</th>
                </tr>
            </thead>
            <tbody>
                <!-- 데이터가 동적으로 추가됩니다 -->
            </tbody>
        </table>
        <button onclick="openUploadModal()">정보 추가</button>
    </section>

    <!-- 아바타 채팅방 관리 -->
    <section id="chat-rooms" class="tab-content">
        <h2>아바타 채팅방 관리</h2>
        <table id="chatRoomTable">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>채팅방 이름</th>
                    <th>참여자 수</th>
                    <th>상태</th>
                    <th>액션</th>
                </tr>
            </thead>
            <tbody>
                <!-- 데이터가 동적으로 추가됩니다 -->
            </tbody>
        </table>
    </section>

    <!-- 개인화 페이지 관리 -->
    <section id="personalization" class="tab-content">
        <h2>개인화 페이지 관리</h2>
        <table id="userTable">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>이름</th>
                    <th>이메일</th>
                    <th>상태</th>
                    <th>액션</th>
                </tr>
            </thead>
            <tbody>
                <!-- 데이터가 동적으로 추가됩니다 -->
            </tbody>
        </table>
    </section>
</main>

<script>
    document.addEventListener('DOMContentLoaded', () => {
const tabs = document.querySelectorAll('.tab-button');
const contents = document.querySelectorAll('.tab-content');

// 탭 전환
tabs.forEach(tab => {
    tab.addEventListener('click', () => {
        tabs.forEach(t => t.classList.remove('active'));
        contents.forEach(c => c.classList.remove('active'));

        tab.classList.add('active');
        document.getElementById(tab.dataset.tab).classList.add('active');
    });
});

// 데이터 가져오기 (업로드된 정보)
fetchUploads();

// 데이터 가져오기 (아바타 채팅방)
fetchChatRooms();

// 데이터 가져오기 (개인화 페이지)
fetchUsers();
});
// 업로드된 정보 가져오기
function fetchUploads() {
const uploadTable = document.getElementById('uploadTable').querySelector('tbody');
uploadTable.innerHTML = ''; // 기존 데이터 초기화
// 여기에 서버로부터 데이터를 가져오는 코드 추가 (더미 데이터 예제)
const uploads = [
    { id: 1, title: 'AI 혁신', category: 'AI', content: 'AI 기술 소개' },
    { id: 2, title: '취업 꿀팁', category: '취업', content: '취업 준비 가이드' }
];

uploads.forEach(upload => {
    const row = document.createElement('tr');
    row.innerHTML = 
        <td>${upload.id}</td>
        <td>${upload.title}</td>
        <td>${upload.category}</td>
        <td>${upload.content}</td>
        <td>
            <button onclick="editUpload(${upload.id})">수정</button>
            <button onclick="deleteUpload(${upload.id})">삭제</button>
        </td>
    ;
    uploadTable.appendChild(row);
});
}
// 아바타 채팅방 가져오기
function fetchChatRooms() {
const chatRoomTable = document.getElementById('chatRoomTable').querySelector('tbody');
chatRoomTable.innerHTML = '';
const chatRooms = [
    { id: 1, name: 'AI 방', participants: 10, status: '활성' },
    { id: 2, name: '취업 방', participants: 5, status: '비활성' }
];

chatRooms.forEach(room => {
    const row = document.createElement('tr');
    row.innerHTML = 
        <td>${room.id}</td>
        <td>${room.name}</td>
        <td>${room.participants}</td>
        <td>${room.status}</td>
        <td>
            <button onclick="deleteChatRoom(${room.id})">삭제</button>
        </td>
    ;
    chatRoomTable.appendChild(row);
});
}
// 사용자 정보 가져오기
function fetchUsers() {
const userTable = document.getElementById('userTable').querySelector('tbody');
userTable.innerHTML = '';
const users = [
    { id: 1, name: '김철수', email: 'kim@example.com', status: '활성' },
    { id: 2, name: '이영희', email: 'lee@example.com', status: '비활성' }
];

users.forEach(user => {
    const row = document.createElement('tr');
    row.innerHTML = 
        <td>${user.id}</td>
        <td>${user.name}</td>
        <td>${user.email}</td>
        <td>${user.status}</td>
        <td>
            <button onclick="editUser(${user.id})">수정</button>
            <button onclick="deleteUser(${user.id})">삭제</button>
        </td>
    ;
    userTable.appendChild(row);
});
}
</script>
위와 같다.