[프로그래머스] Node기반 REST API 구현(12)

Lina Hongbi Ko·2024년 10월 18일
0

Programmers_BootCamp

목록 보기
37/76
post-thumbnail

2024년 10월 17일

✏️ 회원 인증 모듈화(문제 2 해결)

  • authorization 외부 모듈로 만들기
// auth.js

const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();

const ensureAuthorization = (req, res) => {
  try {
    let receivedJwt = req.headers["authorization"];
    console.log("received jwt : ", receivedJwt);

    let decodedJwt = jwt.verify(receivedJwt, process.env.PRIVATE_KEY);
    console.log(decodedJwt);

    return decodedJwt;
  } catch (err) {
    console.log(err.name);
    console.log(err.message);

    return err;
  }
};

module.exports = ensureAuthorization;
// LikeController.js

const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();
const ensureAuthorization = require("../auth"); // 인증 모듈

... 생략 ...
// CartController.js

const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();
const authorization = require("../auth");

... 생략 ...

✏️ 내 장바구니 조회(문제 3 해결)

: 내 아이디로 들어갔을때 장바구니에 무엇이 담겨있는지 확인하도록 구현 & selected가 있을 땐 selected한 장바구니 목록 조회

// CartController.js

const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();
const ensureAuthorization = require("../auth");

const getCartItems = (req, res) => {
  let { selected } = req.body; // selected = [1, 3]

  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    let sql = `SELECT cartItems.id, book_id, title, summary, quantity, price 
    FROM cartItems LEFT JOIN books 
    ON cartItems.book_id = books.id 
    WHERE user_id = ?`;
    let values = [authorization.id];

    if (selected) {
      // 주문서 작성시 '선택한 장바구니 목록 조회'
      sql += ` AND cartItems.id IN (?)`;
      values.push(selected);
    }
    // 회원 장바구니 보기
    conn.query(sql, values, (err, results) => {
      if (err) {
        console.log(err);
        return res.status(StatusCodes.BAD_REQUEST).end();
      }

      return res.status(StatusCodes.OK).json(results);
    });
  }
};

✏️ 주문하기 API에 JWT 구현

// OrderController.js

const mariadb = require("mysql2/promise");
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const ensureAuthorization = require("../auth"); // 인증 모듈

const order = async (req, res) => {
  const conn = await mariadb.createConnection({
    host: "127.0.0.1",
    user: "root",
    password: "root",
    database: "Bookshop",
    dateStrings: true,
  });

  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    const { items, delivery, totalQuantity, totalPrice, firstBookTitle } =
      req.body;

    //(1) delivery에 Insert
    let sql =
      "INSERT INTO delivery (address, receiver, contact) VALUES (?, ?, ?)";
    let values = [delivery.address, delivery.receiver, delivery.contact];

    let [results] = await conn.execute(sql, values);
    let delivery_id = results.insertId;

    // (2) orders에 Insert
    sql = `INSERT INTO orders (book_title, total_quantity, total_price, user_id, delivery_id) VALUES (?, ?, ?, ?, ?)`;
    values = [
      firstBookTitle,
      totalQuantity,
      totalPrice,
      authorization.id,
      delivery_id,
    ];

    [results] = await conn.execute(sql, values);
    let order_id = results.insertId;

    // (2-1) items를 가지고, 장바구니에서 book_id, quantity 조회
    sql = `SELECT book_id, quantity FROM cartItems WHERE id IN (?)`;
    let [orderItems, fields] = await conn.query(sql, [items]); // [rows, fields]

    // (3) orderedBook에 Insert
    sql = `INSERT INTO orderedBook (order_id, book_id, quantity) VALUES ?`;

    values = [];
    orderItems.forEach((item) => {
      values.push([order_id, item.book_id, item.quantity]);
    });

    [results] = await conn.query(sql, [values]);
    // 이중배열을 넘겨줄땐 execute가 아닌 query를 써야함

    let result = await deleteCartItems(conn, items);

    return res.status(StatusCodes.OK).json(result);
  }
};

const deleteCartItems = async (conn, items) => {
  let sql = `DELETE FROM cartItems WHERE id IN (?)`;

  let result = await conn.query(sql, [items]);
  return result;
};

POSTMAN) token + POST + localhost:9999/orders + 데이터

✏️ 좋아요 확인 in 개별 도서 조회 with JWT

// BookController.js

const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const ensureAuthorization = require("../auth"); // 인증 모듈

const bookDetail = (req, res) => {

  // 로그인 상태가 아니면 => liked 빼고 보내주면 되고
  
  // 로그인 상태이면 => liked 추가해서
  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    let book_id = req.params.id;

    let sql = `SELECT *,
                (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
                (SELECT EXISTS (SELECT * FROM likes WHERE user_id = ? AND liked_book_id = ?)) AS liked 
              FROM books
              LEFT JOIN category 
              ON books.category_id = category.category_id 
              WHERE books.id = ?;`;
    let values = [authorization.id, book_id, book_id];
    conn.query(sql, values, (err, results) => {
      if (err) {
        console.log(err);
        return res.status(StatusCodes.BAD_REQUEST).end();
      }

      if (results[0]) {
        return res.status(StatusCodes.OK).json(results[0]); // 책 한 권만 보여주기
      } else {
        return res.status(StatusCodes.NOT_FOUND).end();
      }
    });
  }
};

POSTMAN) token + GET + localhost:9999/books/1

liked:0 인 것을 확인할 수 있다.

POSTMAN) token 입력하지 않음 + GET + localhost:9999/books/1

잘못된 토큰이라는 메시지를 볼 수 있다.

로그인 상태가 아닐때 도서 개별 조회를 하면 liked는 보이지 않도록 처리해주자

// auth.js

const jwt = require("jsonwebtoken");
const dotenv = require("dotenv");
dotenv.config();

const ensureAuthorization = (req, res) => {
  try {
    let receivedJwt = req.headers["authorization"];
    console.log("received jwt : ", receivedJwt);

    if(receivedJwt) {
      let decodedJwt = jwt.verify(receivedJwt, process.env.PRIVATE_KEY);
      console.log(decodedJwt);

      return decodedJwt;
    } else {
      throw new ReferenceError("jwt must be provided");
      // or return receivedJwt
    }
  } catch (err) {
    console.log(err.name);
    console.log(err.message);

    return err;
  }
};

module.exports = ensureAuthorization;
const bookDetail = (req, res) => {
  // 로그인 상태가 아니면 => liked 빼고 보내주면 되고
  // 로그읜 상태이면 => liked 추가해서

  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    let book_id = req.params.id;

    authorization instanceof ReferenceError
      ? (sql = `SELECT *,
                (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes 
              FROM books
              LEFT JOIN category 
              ON books.category_id = category.category_id 
              WHERE books.id = ?;`)
      : (sql = `SELECT *,
                (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
                (SELECT EXISTS (SELECT * FROM likes WHERE user_id = ? AND liked_book_id = ?)) AS liked 
              FROM books
              LEFT JOIN category 
              ON books.category_id = category.category_id 
              WHERE books.id = ?;`);

    authorization instanceof ReferenceError
      ? (values = [book_id])
      : (values = [authorization.id, book_id, book_id]);

    conn.query(sql, values, (err, results) => {
      if (err) {
        console.log(err);
        return res.status(StatusCodes.BAD_REQUEST).end();
      }

      if (results[0]) {
        return res.status(StatusCodes.OK).json(results[0]); // 책 한 권만 보여주기
      } else {
        return res.status(StatusCodes.NOT_FOUND).end();
      }
    });
  }
};

POSTMAN) GET+localhost:9999/books/1

로그인 하지 않아서(토큰X) liked가 없는 것을 알 수 있음

POSTMAN) GET+localhost:9999/books/1+token

로그인하니깐(토큰O) liked 있는 것 확인할 수 있음

❗️ 좋아요 추가, 삭제 로직 response 좋아요 수

  • 좋아요 API는 메서드와 쿼리 명령문 빼고는 추가/삭제가 같음 → 내가 해결한 방법은 삼항 조건 연산자 써서 sql과 values를 나눠주고 쿼리문은 공통으로 쓰게 만들었음,, (위 코드 참조)
  • 개별 도서 조회에서 좋아요를 누르면 좋아요 숫자가 늘어나고 취소를 누르면 숫자가 줄어든다 ⇒ 페이지에 진입하면 좋아요 db를 통해 숫자를 뿌려주지만, 좋아요/취소를 해당 페이지에서 누르는 것은 임시로 페이지 안에서는 프론트엔드가 해결하도록 할 것임 → 나중에 요구사항 변경되면 바꿔보자

✏️ 장바구니 도서 삭제, 주문(상세)내역 조회 with JWT

💡 장바구니 아이템 삭제에 토큰 인증 넣기

// CartController.js

const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const ensureAuthorization = require("../auth");

const removeCartItem = (req, res) => {
  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    let cartItemId = req.params.id;

    let sql = "DELETE FROM cartItems WHERE id = ?";
    conn.query(sql, cartItemId, (err, results) => {
      if (err) {
        console.log(err);
        return res.status(StatusCodes.BAD_REQUEST).end();
      }

      return res.status(StatusCodes.OK).json(results);
    });
  }
};

💡 주문 내역, 상세 내역 조회에 토큰 인증 넣기

// OrderController.js

... 생략 ...

const getOrders = async (req, res) => {
  const conn = await mariadb.createConnection({
    host: "127.0.0.1",
    user: "root",
    password: "root",
    database: "Bookshop",
    dateStrings: true,
  });

  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    let sql = `SELECT orders.id, created_at, address, receiver, contact, book_title, total_quantity, total_price FROM orders LEFT JOIN delivery ON orders.delivery_id = delivery.id;`;

    let [rows, fields] = await conn.query(sql);
    return res.status(StatusCodes.OK).json(rows);
  }
};

const getOrderDetail = async (req, res) => {
  const orderId = req.params.id;
  const conn = await mariadb.createConnection({
    host: "127.0.0.1",
    user: "root",
    password: "root",
    database: "Bookshop",
    dateStrings: true,
  });

  let authorization = ensureAuthorization(req, res);

  if (authorization instanceof jwt.TokenExpiredError) {
    return res.status(StatusCodes.UNAUTHORIZED).json({
      message: "로그인 세션이 만료되었습니다. 다시 로그인 하세요.",
    });
  } else if (authorization instanceof jwt.JsonWebTokenError) {
    return res.status(StatusCodes.BAD_REQUEST).json({
      message: "잘못된 토큰입니다.",
    });
  } else {
    let sql = `SELECT book_id, title, author, price, quantity FROM orderedBook LEFT JOIN books ON orderedBook.book_id = books.id WHERE order_id=?`;

    let [rows, field] = await conn.query(sql, orderId);
    return res.status(StatusCodes.OK).json(rows);
  }
};

✏️ pagination

💡 전체 도서 조회 with pagination

  • 전체 도서 조회 했을 때 paging 시키기
    • 백엔드와 프론트엔드는 서로의 state를 저장하고 있지 않다. 자기가 현재 어떤 상태인지 기억을 하고 있지 않는다. 화면(프론트)에서 1페이지를 요청해서 서버(백)에서 응답해줘도 화면은 다시 자기가 몇페이지 였는지 기억 하고 있지 않아서 자기가 요청한걸 모른다. 그리고 총 몇 페이지 필요한지도 모른다. 총 페이지수를 하단에서 출력하려면 총 몇페이지인지 알아야 출력해줄 수 있음
    • 따라서 총 몇페이지인지, 현재 몇번째 페이지인지 보내줘야함
    • 만약 무한 스크롤이라면 전체 아이템 수가 필요할 수 있음 → 총 개수도 알려줘야함
    • 페이지네이션 정보 → total page, current page, totalBooks 필요
      • total page수를 보내지 않아도, totalBooks만 프론트에게 보내줘도 나눠서 몫으로 total page 수 계산 가능하니깐 current page, totalBooks만 response로 받을예정

💡 전체 도서 조회 구현

  • pagination에 currentPage와 totalBooks를 reponse로 받기 위해서,
    • 먼저 currentPage는 url로 들어오지만
    • totalBooks는 우리가 쿼리로 가져와야 한다. (2가지 방법이 있음)
  1. SELECT FROM Bookshop.books LIMIT 4 OFFSET 0;
    SELECT count(
    ) FROM Bookshop.books;

  1. SELECT SQL_CALC_FOUND_ROWS * FROM Bookshop.books LIMIT 4 OFFSET 0;
    SELECT found_rows();

  • 2번째 쿼리를 들고 구현해보자
// BookController.js

const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const ensureAuthorization = require("../auth"); // 인증 모듈

// (카테고리별, 신간 여부) 전체 도서 목록 조회
const allBooks = (req, res) => {
  let { category_id, news, limit, currentPage } = req.query;

  let offset = limit * (currentPage - 1);

  let sql =
    `SELECT SQL_CALC_FOUND_ROWS *, (SELECT count(*) FROM likes 
    WHERE liked_book_id=books.id) AS likes FROM books`;
  let values = [];
  if (category_id && news) {
    sql +=
      " WHERE category_id = ? AND pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
    values = [category_id];
  } else if (category_id) {
    sql += " WHERE category_id = ?";
    values = [category_id];
  } else if (news) {
    sql +=
      " WHERE pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
  }

  sql += " LIMIT ? OFFSET ?";
  values = [...values, parseInt(limit), offset];

  conn.query(sql, values, (err, results) => {
    if (err) {
      console.log(err);
      // return res.status(StatusCodes.BAD_REQUEST).end();
    }
    console.log(results);
    // if (results.length) {
    //   return res.status(StatusCodes.OK).json(results);
    // } else {
    //   return res.status(StatusCodes.NOT_FOUND).end();
    // }
  });

  sql = "SELECT found_rows()";
  conn.query(sql, (err, results) => {
    if (err) {
      console.log(err);
      return res.status(StatusCodes.BAD_REQUEST).end();
    }

    return res.status(StatusCodes.OK).json(results);
  });
};

POSTMAN) GET + localhost:9999/books?limit=4 & currentPage=1

  • 전체 도서 조회 response body 구성 맞추기
const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const jwt = require("jsonwebtoken");
const ensureAuthorization = require("../auth"); // 인증 모듈

// (카테고리별, 신간 여부) 전체 도서 목록 조회
const allBooks = (req, res) => {
  let allBooksRes = {}; // json 형태로 마련해둠 
  // API 설계에서 봤듯, json형태로 books(도서데이터), 
  // pagination(전체도서수, 현재 페이지) 받아올 것임

  let { category_id, news, limit, currentPage } = req.query;

  let offset = limit * (currentPage - 1);

  let sql =
    "SELECT SQL_CALC_FOUND_ROWS *, (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes FROM books";
  let values = [];
  if (category_id && news) {
    sql +=
      " WHERE category_id = ? AND pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
    values = [category_id];
  } else if (category_id) {
    sql += " WHERE category_id = ?";
    values = [category_id];
  } else if (news) {
    sql +=
      " WHERE pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
  }

  sql += " LIMIT ? OFFSET ?";
  values = [...values, parseInt(limit), offset];

  conn.query(sql, values, (err, results) => {
    if (err) {
      console.log(err);
      // return res.status(StatusCodes.BAD_REQUEST).end();
    }
    if (results.length) {
	    console.log(results);
      allBooksRes.books = results; // books(도서 데이터) 받음
    } else {
      return res.status(StatusCodes.NOT_FOUND).end();
    }
  });

  sql = "SELECT found_rows()";
  conn.query(sql, (err, results) => {
    if (err) {
      console.log(err);
      return res.status(StatusCodes.BAD_REQUEST).end();
    }
		// results -> [{"found_rows()":11}]의 형태임
    let pagination = {}; // pagination(총 도서 수, 현재 페이지) 받음
    pagination.currentPage = parseInt(currentPage); // params로 받음
    pagination.totalCount = results[0]["found_rows()"];
    // 배열 안의 json 형태이므로
    // 배열의 첫번째 요소를 꺼내서
		// found_rows() 키 값을 사용

    allBooksRes.pagination = pagination;

    return res.status(StatusCodes.OK).json(allBooksRes);
  });
};

POSTMAN) GET+ localhost:9999/books?limit=4¤tPage=1

✏️ response format : snake -> camel

  • 데이터베이스에서는 snake 방식으로 컬럼들을 추가했는데, 프론트엔드에게 넘겨줄땐 camel로 넘겨줘야함
    • 따라서 카멜로 바꿔줘야하는데, 컬럼을 선택해서 AS를 사용해 넣어주거나(SELECT … AS pubDate), 를 풀고 필요한 컬럼만 선택하거나, map을 사용하는 등의 방법을 통해 바꿔준다
    • map을 사용해보자
// BookController.js

... 생략 ...
  sql += " LIMIT ? OFFSET ?";
  values = [...values, parseInt(limit), offset];

  conn.query(sql, values, (err, results) => {
    if (err) {
      console.log(err);
      // return res.status(StatusCodes.BAD_REQUEST).end();
    }
    if (results.length) {
      results.map((result) => {
        result.pubDate = result.pub_date;
        delete result.pub_date;
      });
      allBooksRes.books = results;
    } else {
      return res.status(StatusCodes.NOT_FOUND).end();
    }
  });
 ... 생략 ...

✏️ error status code

: 실패시 필요한 error status code도 고려 해야 한다

if(results.affectedRows) {
      return res.status(StatusCodes.CREATED).json(results);
    } else {
      return res.status(StatusCodes.BAD_REQUEST).end();
    }

✏️ 코드 퀄리티를 위한 생각

  • 기능이 다 돌아간다고 다 완성한게 아님!
    • 코드 퀄리티를 높여야함
  • 데이터베이스 중복 코드 → 모듈화 ex) UserController: user에 대한 데이터와 작업 → User (데이터 모듈=Model) - CRUD cf. DB 모듈 : mysql ⇒ 몽구스, 시퀄라이즈
  • 패키지 구조
    1. Router : 경로(URI, URL)와 HTTP method로 요청에 따른 경로를 찾아주는 역할

    2. Controller : 길 매니저 - 요청을 환영! 직접 일을 하진 않음

    3. Service : 직접 일을 하고 ex) 어떤 쿼리를 부를지

      “비즈니스 로직”

    4. Model : 데이터베이스와 소통 → query 집합

  • 예외처리 (try/catch) 더 해줄 곳 없는지
    • 유효성 검사 추가
    • jwt (심화) : access token이 만료되면, ‘로그인 연장?’
      • 로그인시 access token(30m), refresh token(24h) 받음
      1. access token : 로그인한 사람이야 인증(인증/인가)
      2. refresh token : 로그인 연장하는 용도
  • 랜덤 데이터 (외부) API를 활용해 isbn 샘플 데이터들을 채울 수 있음
  • (nodemon 모듈)
  • 프론트엔드와 코드 결합시 에러 발생하면 어떻게 처리해야할지 고민
  • response 포맷 통일 (snake → camel), status code 통일 …

✏️ 랜덤 데이터 API

💡 랜덤데이터 프로젝트 시작

  • 개요
    • 랜덤 데이터를 생성해주는 API (외부 API)를 기반으로 “가짜 사용자 정보 생성” API를 만들것임 ⇒ 랜덤 데이터 API를 사용해서 가짜 사용자 정보 생성 API
  • 내용
    1. 랜덤 데이터 생성 API (가짜 사용자, 가짜 상품, 가짜 전화번호, 등등..)
    2. 가짜 사용자 정보를 생성하는 Express 웹/앱 API
  • 랜덤 데이터 API
    • faker
    • mockaroo

💡 faker

  1. npm install —save-dev @faker-js/faker
  2. 시작해보자
// radom-user.js

const { faker } = require('@faker-js/faker');

// localhost:2222/fake/users
// 한명의 사용자 정보 생성
// fullName, email, password, contact

console.log(faker.internet.userName());
console.log(faker.internet.email());
console.log(faker.internet.password());

💡 가짜 사용자 1명 만들어주는 API

// radom-user.js

const { faker } = require('@faker-js/faker');

// localhost:2222/fake/users
// 한명의 사용자 정보 생성
// fullName, email, password, contact

console.log(faker.internet.email());
console.log(faker.internet.password());
console.log(faker.person.fullName());
console.log(faker.phone.number());

  • npm install express
// radom-user.js

const express = require("express");
const app = express();
const { faker } = require('@faker-js/faker');

// localhost:2222/fake/users
// req 숫자를 받아서, 그 수 만큼 사용자 정보를 생성해주는 api

app.get('/fake/users', function(req, res) {
	res.status(200).json({
		email : faker.internet.email(),
		password : faker.internet.password(),
		fullName : faker.person.fullName(),
		contact : faker.phone.number()
	})
});

console.log(faker.internet.email());
console.log(faker.internet.password());
console.log(faker.person.fullName());
console.log(faker.phone.number());

app.listen(2222);

localhost:2222/fake/users

💡 원하는 사용자 수 만큼 가짜 데이터 만들어주는 API로 수정해보기

// radom-user.js

const express = require("express");
const app = express();
const { faker } = require('@faker-js/faker');

// localhost:2222/fake/users
// req 숫자를 받아서, 그 수 만큼 사용자 정보를 생성해주는 api

app.get('/fake/users/', function(req, res) {
		const {num} = req.query;
	
		let index = 1;
		let users = [];
		while(index <= num) {
			users.push({
				email : faker.internet.email(),
				password : faker.internet.password(),
				fullName : faker.person.fullName(),
				contact : faker.phone.number()
			});
			index++;
		}
		res.status(200).json(users);
});

app.listen(2222);

localhost:2222/faker/users?num=10

🍏🍎 오늘의 느낀점 : 드디어 오늘 백엔드코스가 끝났다.. 마지막인만큼 배운 내용도 많고 어려운 내용도 많았다. pagination을 백엔드에서 처리해줘서 프론트랑 연결해서 보여주는 것도 그동안 궁금했었는데 어떻게 처리하는지 알게 되었다. 초미니 프로젝트를 하면서 직접 API를 만드는 것도 해보면서 많은 것들을 만들어봐야 확실히 감이 올 것 같다.
그리고 코드 퀄리티를 높이기 위해 모듈화하는 것과 패키지 구조를 다시 한번 찾아보면서 코드를 처음부터 한번 다시 짜봐야겠다.

profile
프론트엔드개발자가 되고 싶어서 열심히 땅굴 파는 자

0개의 댓글