2023.12.14(목)

🏗️미니 프로젝트 (유튜브) > 🖋️API 설계

👤회원

  • 로그인 (POST /login : id, pwd)

    • ${name}님 환영합니다. → 메인 페이지로 redirect
  • 회원 가입 (POST /join : id, pwd, name)

    • ${name}님 환영합니다. → 로그인 페이지로 redirect
  • 마이페이지 = 회원 개별 조회 (GET /users/:id : id, name)

  • 마이페이지 > 회원 개별 탈퇴 (DELETE /users/:id)

    • ${name}님 다음에 또 뵙겠습니다. → 메인 페이지로 redirect
  • user-demo.js (기본 동작 및 예외까지 구현)

    // Express module setting
    const express = require('express')  // npm install express
    const app = express()
    const port = 8888
    app.listen(port, () => console.log(`> Server is running on http://localhost:${port}/`))
    app.use(express.json())
    
    const db = new Map()
    var id = 0
    
    // 로그인
    app.post('/login', (req, res) => {
        const { userId, pwd } = req.body
        if (userId && pwd) {
            for (const [_, user] of db) {
                if (userId === user.userId) {
                    if (pwd === user.pwd) return res.status(200).json({ message: `${user.name}님 환영합니다.` })
                    else return res.status(401).json({ message: "잘못된 비밀번호입니다." })
                }
            }
            res.status(401).json({ message: "존재하지 않는 아이디입니다." })
        } else {
            res.status(400).json({ message: "잘못된 형식입니다." })
        }
    })
    // 회원 가입
    app.post('/join', (req, res) => {
        const { userId, pwd, name } = req.body
        if (userId && pwd && name) {
            db.set(++id, req.body)
            res.status(201).json({ message: `${name}님 환영합니다.` })
        } else {
            res.status(400).json({ message: "잘못된 형식입니다." })
        }
    })
    // 회원 개별 조회
    app.get('/users/:id', (req, res) => {
        let { id } = req.params
        id = parseInt(id)
        if (db.has(id)) {
            const { userId, name } = db.get(id)
            res.status(200).json({ userId, name })
        } else {
            res.status(404).json({ message: "존재하지 않는 회원입니다." })
        }
    })
    // 회원 개별 탈퇴
    app.delete('/users/:id', (req, res) => {
        let { id } = req.params
        id = parseInt(id)
        if (db.has(id)) {
            const { name } = db.get(id)
            db.delete(id)
            res.status(200).json({ message: `${name}님 다음에 또 뵙겠습니다.` })
        } else {
            res.status(404).json({ message: "존재하지 않는 회원입니다." })
        }
    })

📺채널 관리

(마이페이지에서 관리 & 계정 하나로 최대 100개의 채널 관리 가능)

  • 채널 생성 (POST /channels : channelTitle)

    • ${channelTitle} 채널을 응원합니다. → 채널 관리 페이지로 redirect
  • 채널 개별 수정 (PUT /channels/:id : channelTitle)

    • 채널명이 ${oldChannelTitle}에서 ${newChannelTitle}()로 성공적으로 수정되었습니다.
  • 채널 개별 삭제 (DELETE /channels/:id)

    • ${channelTitle} 채널이 삭제되었습니다 → 메인 페이지로 redirect
  • 채널 전체 조회 (GET /channels)

  • 채널 개별 조회 (GET /channels/:id)

  • channel-demo.js (기본 동작 및 예외까지 구현, 회원 고려 X)

    // Express module setting
    const express = require('express')  // npm install express
    const app = express()
    const port = 8888
    app.listen(port, () => console.log(`> Server is running on http://localhost:${port}/`))
    app.use(express.json())
    
    const db = new Map()
    var id = 0
    
    app.route('/channels')
        .get((req, res) => {    // 채널 전체 조회
            if (db.size) {
                let channels = []
                db.forEach((value) => channels.push(value))
                res.status(200).json(channels)
            } else {
                res.status(404).json({ message : "조회할 채널이 없습니다."})
            }
        })
        .post((req, res) => {    // 채널 생성
            if (req.body.channelTitle) {
                db.set(++id, req.body)
                res.status(201).json({ message: `${db.get(id).channelTitle} 채널을 응원합니다.` })
            } else {
                res.status(400).json({ message: "잘못된 형식입니다." })
            }
        })
    
    app.route('/channels/:id')
        .get((req, res) => { // 채널 개별 조회
            let { id } = req.params
            id = parseInt(id)
            if (db.has(id)) res.status(200).json(db.get(id))
            else res.status(404).json({ message: "존재하지 않는 채널입니다." })
        })
        .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 {
                res.status(404).json({ message: "존재하지 않는 채널입니다." })
            }
        })
        .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 {
                res.status(404).json({ message: "존재하지 않는 채널입니다." })
            }
        })

💡Object가 비어 있는지 확인하기

지금 코드에서는 내가 다른 방법으로 구현해서 사용하지는 않았지만 송아 강사님께서 언급하신 것처럼 나중에 쓰일 것 같다.

  • 기본적으로 length property는 Array에서만 지원하기 때문에 Object가 비어있는지 확인하려면 다음과 같이 코드를 작성해야 함

  • constructor property로 Object인지 확인 & key들을 배열로 반환한 길이가 0인지 확인

    function isEmptyObj(obj) {
        if (obj.constructor === Object && Object.keys(obj).length === 0) return true;
        return false;
    }
  • Object.prototype.constructor : 인스턴스의 프로토타입을 만든 Object 함수의 참조를 반환 (JavaScript의 데이터 유형 중 하나를 반환한다고 생각하면 됨)

    var o = {};
    o.constructor === Object; // true
    
    var o = new Object();
    o.constructor === Object; // true
    
    var a = [];
    a.constructor === Array; // true
    
    var a = new Array();
    a.constructor === Array; // true
    
    var n = new Number(3);
    n.constructor === Number; // true

오늘까지 강의에서 작성한 코드들은 정말 틀만 잡아 놓은 거라 고칠 부분이 많아 보인다. 일단 채널의 경우 회원에 속하는 하위 데이터이기 때문에 path도 /channels/:id의 형태가 아니라 예를 들어 /users/:uid/channels/:cid처럼 channel이 속하는 회원 id도 받아야 할 것이다. id가 민감한 데이터라면 url이 아니라 request에 숨겨서 보내거나.. 그리고 오늘은 app.route()로 겹치는 path에 대해 HTTP method들을 chaining해서 작성했는데 기능이 많아질 수록 express.Router()로 모듈화시키는 게 더 깔끔할 것 같다.

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

0개의 댓글

Powered by GraphCDN, the GraphQL CDN