본문 바로가기
내일배움 강의/강의- Node.js 입문, 숙련

Node.js 입문주차 1주차 - 7_REST API 개발하기

by GREEN나무 2024. 11. 4.
728x90


1. Express의 REST API를 어떻게 개발하는지 알아봅니다.
2. Express 프레임워크에서 REST API를 개발해봅니다.

 

01. REST API 개발

◆ 상품 목록 조회 API
▷ 구현하려면 
상품 목록 조회 API에서는 모든 상품(goods)이 한번에 전달 되어야합니다.
 ex) GET 메소드를 이용해서 /goods 라는 주소로 요청을 보냈을 때, 모든 상품 목록이 응답(response)해서 json 포맷으로 상품 목록이 보여야 합니다.
이번 주차에서는 DB대신 routes 폴더에 goods.js 파일에서 아래의 상품 json 데이터를 저장합니다.

 

  상품 예시 데이터  코드(/routes/goods.js 코드)

더보기
// /routes/goods.js
import express from 'express';

// Express.js의 라우터를 생성합니다.
const router = express.Router();

const goods = [
  {
    goodsId: 1,
    name: '상품 1',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg',
    category: 'drink',
    price: 6.2,
  },
  {
    goodsId: 2,
    name: '상품 2',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2014/08/26/19/19/wine-428316_1280.jpg',
    category: 'drink',
    price: 0.11,
  },
  {
    goodsId: 3,
    name: '상품 3',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/02/12/frogs-1650658_1280.jpg',
    category: 'drink',
    price: 2.2,
  },
  {
    goodsId: 4,
    name: '상품 4',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/02/11/frogs-1650657_1280.jpg',
    category: 'drink',
    price: 0.1,
  },
];

/** 상품 목록 조회 **/
// localhost:3000/api/goods GET
router.get('/goods', (req, res) => {
  return res.json({ goods: goods });
});

export default router;

http://localhost:3000/api/goods

 

◆ 상품 상세 조회 API

▷ 구현하려면

      특정 상품의 상세 조회를 위해서 기존 상품 목록 주소 이후에 경로 매개변수(Path Parameter)로 상품 id(goodsId)로 특정 상품 상세 조회를 구현 해야합니다.

▷  경로 매개변수(Path Parameter) : 
Path Parameter 또는 Path Variable이라고 불립니다.
라우트 주소에서 사용되는 특수한 패턴 중 하나입니다. 이는 URL의 일부분으로, 언제든지 변경될 수 있는 값을 나타내기 위해 사용됩니다.
   상품 목록 조회 API의 주소가 /goods 였다면 그뒤에 /:goodsId 라는 값을 추가해서 요청시 goodsId값을 받아올 수 있습니다. 
이 값은 API 내에서 req.params 객체 안에서 해당하는 경로 매개변수의 이름(goodsId)으로 접근하여 얻을 수 있습니다. 
   req.prams.goodsId를 통해 goodsId파라미터 값을 얻을 수 있습니다.

// goods.js에 추가할 코드 입니다

/* 상품 상세 조회API 
http://localhost:3000/api/goods/:goodsId/ */
router.get('/goods/:goodsId', (req, res) => {
  // 1. 상품의 id 조회
  // 2. 상품 id와 일치하는 데이터 찾기
  // 3. 조회한 상품 정보르 Response로 Return 한다.

  const goodsId = req.params.goodsId;  // 1.
  const findGoods = goods.find((oneGoods) =>oneGoods.goodsId === +goodsId) // 2.
  return res.status(200).json({goods: findGoods}); // 3.
})

http://localhost:3000/api/goods/2


◆  상품 등록 API
구현하려면
상품 등록 API에서는 클라이언트가 요청(Request)시 전달하는 상품의 정보(body data)를 서버로 전달받아야합니다.
상품 등록 API는 ‘데이터를 저장’하는 역할을 담당하므로, Http 메서드 중에서는 데이터를 생성하는 POST 메서드를 이용하여 구현해야합니다.
▷ POST 메서드 : 클라이언트가 서버로 보내는 데이터를 전송하기 위해 사용되는 메서드입니다. 이 데이터는 주로 서버의 리소스를 생성할 때 사용합니다.
▷ 구현하기에 앞서

POST 메서드에서 클라이언트가 전달한 데이터는 Express.js에서 `req.body`를 통해 접근할 수 있습니다. 

`req.body`에 접근하려면 Body Parser 미들웨어를 사용해야 합니다.

Body Parser는 클라이언트가 전송한 데이터를 해석하여 `req.body` 객체로 변환해주어, 클라이언트 데이터를 쉽게 추출할 수 있도록 도와줍니다.


▷ Body Parser는 app.js파일에 추가하여, body에 접근이 가능하도록 설정합니다.

// app.js

// Express에서 req.body에 접근하여, body 데이터를 사용할 수 있도록 설정하는 미들웨어
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

전체 코드

더보기
// app.js

import express from 'express';
import goodsRouter from './routes/goods.js';
import newsRouter from './routes/news.js';

const app = express();
const PORT = 3000;

// Express에서 req.body에 접근하여, body 데이터를 사용할 수 있도록 설정하는 미들웨어

// json 형태로 서버에 body 데이터를 전달하면, req.body에 데이터를 변환하여 넣어줍니다.
// API 클라이언트를 사용 할 때 사용
app.use(express.json());

// form content type에서 body 데이터를 전달하면, req.body에 데이터를 변환하여 넣어줍니다.
// 프론트엔드 동료와 협업시 사용
app.use(express.urlencoded({ extended: true }));


// localhost:3000/api -> goodsRouter, newsRouter
app.use('/api', [goodsRouter, newsRouter]);

app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

 

// /routes/goods.js
import express from 'express';

// Express.js의 라우터를 생성합니다.
const router = express.Router();

const goods = [
  {
    goodsId: 1,
    name: '상품 1',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg',
    category: 'drink',
    price: 6.2,
  },
  {
    goodsId: 2,
    name: '상품 2',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2014/08/26/19/19/wine-428316_1280.jpg',
    category: 'drink',
    price: 0.11,
  },
  {
    goodsId: 3,
    name: '상품 3',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/02/12/frogs-1650658_1280.jpg',
    category: 'drink',
    price: 2.2,
  },
  {
    goodsId: 4,
    name: '상품 4',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/02/11/frogs-1650657_1280.jpg',
    category: 'drink',
    price: 0.1,
  },
];

/** 상품 목록 조회 **/
// localhost:3000/api/goods GET
router.get('/goods', (req, res) => {
  return res.json({ goods: goods });
});


/* 상품 상세 조회API 
http://localhost:3000/api/goods/:goodsId/ */
router.get('/goods/:goodsId', (req, res) => {
  // 1. 상품의 id 조회
  // 2. 상품 id와 일치하는 데이터 찾기
  // 3. 조회한 상품 정보르 Response로 Return 한다.

  const goodsId = req.params.goodsId;  // 1.
  const findGoods = goods.find((oneGoods) =>oneGoods.goodsId === +goodsId) // 2.
  return res.status(200).json({goods: findGoods}); // 3.
})

/**상품 등록 API **/
// http://localhost:3000/api/goods/
router.post('/goods', (req, res) => {
  // 1. name, thumbnailUrl, category, price를 req.body로 전달받는다.
  // 2. 해당하는 데이터를바탕으로 상품을 등록한다.
  // 3. 등록된 상품 데이터를 클라이언트에게 반환한다.

  const name = req.body.name;
  const thumbnailUrl = req.body.thumbnailUrl;
  const category = req.body.category;
  const price = req.body.price;

  const goodsId = goods[goods.length - 1].goodsId + 1; // 현재 goodsId의 가장 큰 값 + 1

  const goodsItem = {
    goodsId: goodsId,
    name: name,
    thumbnailUrl: thumbnailUrl,
    category: category,
    price: price,
  };
  goods.push(goodsItem);

  return res.status(201).json({ goods: goodsItem });
});

export default router;

 

 

 

  Insomnia로 상품등록 API 테스트

body데이터의 형식을 선택해 보낼 수 있습니다.

get을 post로 수정 > URL ' localhost:3000/api/goods' 기입 > 'Body'> 텍스트에 'Json' 선택> 적고  > Send 클릭

{ // text Json 칸에 붙이세요
	"name": "상품 5",
	"thumbnailUrl": "https://cdn.pixabay.com/photo/2016/07/26/16/16/wine-1543170_960_720.jpg",
	"category": "drink",
	"price": 100.3
}

상품이 추가되었습니다,


◆  상품 등록 API 리팩토링

리팩토링 : 코드를 간략하게 만들어 가독성을 높입니다.
전달받게되는 데이터(import api)가 많아질수록 코드가 복잡해지고 가독성이 떨어지게 될 것입니다.
▷ ‘객체 구조 분해 할당’  : JavaScript에서 제공하는 객체와 배열 같은 복잡한 데이터 타입을 다루기 위한 문법.

      객체 내부의 Key와 일치하는 변수에 값을 할당할 수 있게됩니다.

/** 상품 등록 리팩토링 **/
// localhost:3000/api/goods POST
router.post('/goods', (req, res) => {
  // 객체 구조 분해 할당 적용하기.
  const { name, thumbnailUrl, category, price } = req.body;

  const goodsId = goods[goods.length - 1].goodsId + 1; // 현재 goodsId의 가장 큰 값 + 1

  // 객체 구조 분해 할당 적용하기.
  const goodsItem = {
    goodsId,
    name,
    thumbnailUrl,
    category,
    price,
  };
  goods.push(goodsItem);

  return res.status(201).json({ goods: goodsItem });
});

리팩토링한 goods.js 코드

더보기

 

// /routes/goods.js
import express from 'express';

// Express.js의 라우터를 생성합니다.
const router = express.Router();

const goods = [
  {
    goodsId: 1,
    name: '상품 1',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/19/54/wines-1652455_1280.jpg',
    category: 'drink',
    price: 6.2,
  },
  {
    goodsId: 2,
    name: '상품 2',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2014/08/26/19/19/wine-428316_1280.jpg',
    category: 'drink',
    price: 0.11,
  },
  {
    goodsId: 3,
    name: '상품 3',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/02/12/frogs-1650658_1280.jpg',
    category: 'drink',
    price: 2.2,
  },
  {
    goodsId: 4,
    name: '상품 4',
    thumbnailUrl:
      'https://cdn.pixabay.com/photo/2016/09/07/02/11/frogs-1650657_1280.jpg',
    category: 'drink',
    price: 0.1,
  },
];

/** 상품 목록 조회 **/
// localhost:3000/api/goods GET
router.get('/goods', (req, res) => {
  return res.json({ goods: goods });
});


/* 상품 상세 조회API 
http://localhost:3000/api/goods/:goodsId/ */
router.get('/goods/:goodsId', (req, res) => {
  // 1. 상품의 id 조회
  // 2. 상품 id와 일치하는 데이터 찾기
  // 3. 조회한 상품 정보르 Response로 Return 한다.

  const goodsId = req.params.goodsId;  // 1.
  const findGoods = goods.find((oneGoods) =>oneGoods.goodsId === +goodsId) // 2.
  return res.status(200).json({goods: findGoods}); // 3.
})

/** 상품 등록 리팩토링 **/
// localhost:3000/api/goods POST
router.post('/goods', (req, res) => {
  // 객체 구조 분해 할당 적용하기.
  const { name, thumbnailUrl, category, price } = req.body;

  const goodsId = goods[goods.length - 1].goodsId + 1; // 현재 goodsId의 가장 큰 값 + 1

  // 객체 구조 분해 할당 적용하기.
  const goodsItem = {
    goodsId,
    name,
    thumbnailUrl,
    category,
    price,
  };
  goods.push(goodsItem);

  return res.status(201).json({ goods: goodsItem });
});

export default router;

클라이언트가 전달한 파라미터를 한 줄로 간단하게 줄였습니다.

새로운 상품을 생성할 때 Key-Value를 각각 선언하는 것 대신 한 줄로 처리할 수 있게 되었습니다.