2023.12.21(목)

🏗️미니 프로젝트 (유튜브)에 DB 연결

📢 기존의 user_id → email로 변경

  • 회원
    • SELECT 로그인 (POST /login : email, password)
      • ${name}님 환영합니다. → 메인 페이지로 redirect
    • INSERT 회원 가입 (POST /join : email, name, password, contact)
      • ${name}님 환영합니다. → 로그인 페이지로 redirect
    • SELECT 마이페이지 = 회원 개별 조회 (GET /users : email) (※ 원래 email*는 body가 아니라 header에 숨겨서 Token(JWT)으로 받아야함*)
    • DELETE 마이페이지 > 회원 개별 탈퇴 (DELETE /users : email) (※ 원래 email*는 body가 아니라 header에 숨겨서 Token(JWT)으로 받아야함*)
      • ${name}님 다음에 또 뵙겠습니다. → 메인 페이지로 redirect
  • 마이페이지 > 채널 관리 (계정 하나로 최대 100개의 채널 관리 가능)
    • SELECT 회원의 채널 전체 조회 (GET /channels : user_id)
    • INSERT 채널 개별 생성 (POST /channels : name, user_id) (※ 원래 userId는 body가 아니라 header에 숨겨서 Token(JWT)으로 받아야함)
      • ${name} 채널을 응원합니다. → 채널 관리 페이지로 redirect
    • UPDATE 채널 개별 수정 (PUT /channels/:id : name)
      • 채널명이 ${oldName}에서 ${newName}()로 성공적으로 수정되었습니다.
    • DELETE 채널 개별 삭제 (DELETE /channels/:id)
      • ${name} 채널이 삭제되었습니다 → 메인 페이지로 redirect
    • SELECT 채널 개별 조회 (GET /channels/:id)

💻CODE

21일차에 작성한 코드에서 수정 (Map 대신 진짜 DB 연결!)
수정한 코드들👇

  • mariadb.js

    // get the client
    const mysql = require('mysql2')
    
    // create the connection to database
    const connection = mysql.createConnection({
        // host: 'localhost',
        // port: 3306,
        user: 'root',
        password: 'root',
        // timezone: 'Asia/Seoul',
        database: 'Youtube',
        dateStrings: true
    })
    
    module.exports = connection;
  • routes/users.js

    const express = require('express')
    const router = express.Router()
    const conn = require('../mariadb')
    
    router.post('/login', (req, res) => {
        const { email, password } = req.body
        if (email && password) {
            let sql = 'SELECT * FROM `users` WHERE email = ?'
            conn.query(
                sql, email,
                function (err, results) {
                    const loginUser = results[0]
                    if (loginUser && loginUser.password == password) res.status(200).json({ message: `${loginUser.name}님 환영합니다.` })
                    else res.status(403).json({ message: "이메일 또는 비밀번호가 틀렸습니다." })
                }
            )
        } else {
            res.status(400).json({ message: "잘못된 형식입니다." })
        }
    })
    
    router.post('/join', (req, res) => {
        const { email, name, password, contact } = req.body
        if (email && name && password) {
            let sql = 'INSERT INTO `users` (email, name, password, contact) VALUES (?, ?, ?, ?)'
            let values = [email, name, password, contact]
            conn.query(
                sql, values,
                function (err, results) {
                    res.status(201).json({ message: `${name}님 환영합니다.`, results })
                }
            )
        } else {
            res.status(400).json({ message: "잘못된 형식입니다." })
        }
    })
    
    router.route('/users')
        .get((req, res) => {
            let { email } = req.body
            let sql = 'SELECT * FROM `users` WHERE email = ?'
            conn.query(
                sql, email,
                function (err, results) {
                    if (results.length) res.status(200).json(results)
                    else res.status(404).json({ message: "존재하지 않는 회원입니다." })
                }
            )
        })
        .delete((req, res) => {
            let { email } = req.body
            let sql = 'DELETE FROM `users` WHERE email = ?'
            conn.query(
                sql, email,
                function (err, results) {
                    console.log(results)
                    // if (!err) res.status(200).json({ message: `${name}님 다음에 또 뵙겠습니다.` })
                    // else res.status(404).json({ message: "존재하지 않는 회원입니다." })
                }
            )
        })
    
    module.exports = router
  • routes/channels.js

    • 채널 개별 수정과 개별 삭제는 아직 수정 X
    • 채널 개별 생성의 경우 기존에 존재하는 user_id만 들어오는 것으로 가정했기 때문에 이 부분에 대해 유효성 검사 필요!
    const express = require('express')
    const router = express.Router()
    const conn = require('../mariadb')
    
    const db = new Map()
    var id = 0
    
    const channelNotFound = (res) => res.status(404).json({ message: "채널이 존재하지 않습니다." })
    
    router.route('/')
        .get((req, res) => {    // 채널 전체 조회
            const { userId } = req.body
            if (userId) {
                let sql = 'SELECT * FROM `channels` WHERE user_id = ?'
                conn.query(
                    sql, userId,
                    function (err, results) {
                        if (results.length) res.status(200).json(results)
                        else channelNotFound(res)
                    }
                )
            } else {
                res.status(400).json({ message: "잘못된 형식입니다." })
            }
        })
        .post((req, res) => {    // 채널 개별 생성
            const { name, user_id } = req.body
            // 유효성 검사 필요!
            if (name && user_id) {
                let sql = 'INSERT INTO `users` (name, user_id) VALUES (?, ?)'
                let values = [name, user_id]
                conn.query(
                    sql, values,
                    function (err, results) {
                        res.status(201).json({ message: `${name} 채널을 응원합니다.` })
                    }
                )
            } else {
                res.status(400).json({ message: "잘못된 형식입니다." })
            }
        })
    
    router.route('/:id')
        .get((req, res) => { // 채널 개별 조회
            let { id } = req.params
            id = parseInt(id)
            let sql = 'SELECT * FROM `channels` WHERE id = ?'
            conn.query(
                sql, id,
                function (err, results) {
                    if (results.length) res.status(200).json(results)
                    else channelNotFound(res)
                }
            )
        })
        .put((req, res) => { // 채널 개별 수정
            let { id } = req.params
            id = parseInt(id)
            if (db.has(id)) {
                const channel = db.get(id)
                const oldChannelTitle = channel.channelTitle
                const newChannelTitle = req.body.channelTitle
                channel.channelTitle = newChannelTitle
                // db.set(id, channel)
                res.status(200).json({ message: `채널명이 ${oldChannelTitle}에서 ${newChannelTitle}(으)로 성공적으로 수정되었습니다.` })
            } else {
                channelNotFound(res)
            }
        })
        .delete((req, res) => {  // 채널 개별 삭제
            let { id } = req.params
            id = parseInt(id)
            if (db.has(id)) {
                const { channelTitle } = db.get(id)
                db.delete(id)
                res.status(200).json({ message: `${channelTitle} 채널이 삭제되었습니다` })
            } else {
                channelNotFound(res)
            }
        })
    
    module.exports = router

내일 배울 유효성 검사가 기대된다.

🤯timezone issue

mysql2 module 사용 시 mysql.createConnection()의 connection option 중에서 timezone의 동작이 잘 이해가 가지 않아 테스트 중이다. 현재 다음과 같은 동작을 보이는 것을 확인했는데 예상했던 결과와 달라서 너무 헷갈린다..ㅠ
(dateStrings: false를 사용하면 [Function: Date]를 반환하고 dateStrings: true를 사용하면 [Function: String]이 반환된다.)

MariaDB : time_zoneconnection option : timezoneconnection option : dateStringsTIMESTAMP output
SYSTEM (UTC)'local'false2023-12-20T01:16:32.000ZUTC - 9
SYSTEM (UTC)'local'true'2023-12-20 10:16:32’UTC
SYSTEM (UTC)'Asia/Seoul'false2023-12-20T10:16:32.000ZUTC
SYSTEM (UTC)'Asia/Seoul'true'2023-12-20 10:16:32’UTC
SYSTEM (UTC)'+09:00'false2023-12-20T01:16:32.000ZUTC - 9
SYSTEM (UTC)'+09:00'true2023-12-20 10:16:32UTC
SYSTEM (UTC)'-09:00'false2023-12-20T19:16:32.000ZUTC + 9
SYSTEM (UTC)'-09:00'true2023-12-20 10:16:32UTC
Asia/Seoul'local'false2023-12-20T10:16:32.000ZUTC
Asia/Seoul'local'true2023-12-20 19:16:32KST
Asia/Seoul'Asia/Seoul'false2023-12-20T19:16:32.000ZKST
Asia/Seoul'Asia/Seoul'true2023-12-20 19:16:32KST
Asia/Seoul'+09:00'false2023-12-20T10:16:32.000ZUTC
Asia/Seoul'+09:00'true2023-12-20 19:16:32KST
Asia/Seoul'-09:00'false2023-12-21T04:16:32.000ZKST + 9
Asia/Seoul`'-09:00'true2023-12-20 19:16:32KST

깃허브 이슈에 timezone과 관련된 내용이 많은데 아직 해결이 안된건지 싶다.🤔

profile
이것저것 관심 많은 개발자👩‍💻

0개의 댓글