이번 포스트에서는 Node.js 와 Express.js 를 이용하여 샘플 코드를 직접 작성해 보고, 포스트맨을 이용하여 테스트 해보도록 하겠습니다.
준비물
포스트맨 (Postman) 은 API 플랫폼으로, 아직 front-end integration 이 끝나기 전, API 엔드포인트 테스팅을 할 때 제가 주로 사용하는 툴입니다. 크롬 익스텐셩도 있지만 저는 테스크탑 애플리케이션을 다운 받아서 사용합니다. 필요하신 분들이 계시다면 아래 링크를 통해서 다운받으시기 바랍니다. (참고로 저는 맥북 사용자이므로 윈도우 사용자 분들은 아래 링크에서 윈도우즈용을 선택 하시고 다운 받으시면 됩니다.)
https://www.postman.com/downloads/
먼저 프로젝트를 생성할 폴더를 만듭니다. 이 튜토리얼을 위해서 저는 nodejs-tutorial 이라는 폴더를 데스크탑에 생성하였습니다. 방법은 여러가지가 있으니 편하신 대로 생성하시면 됩니다.
그 후 IDE 를 통해서 생성한 폴더를 열어줍니다. 저는 이 튜토리얼에서 맥북 환경의 Visual Studio Code 를 사용하였습니다. VS Code 는 가볍고, 많은 패키지들을 지원하는데도 무료이므로 개발 하시는 분들에게 강려ㅋ 추천하는 IDE 입니다.
프로젝트 초반 작업
프로젝트가 열리면 위의 Terminal 메뉴에서 New Terminal 을 선택하시거나, Ctrl + Shift + ` 를 눌러 새 터미널 프롬프트를 열어줍니다. 그 후, 프로젝트 루트 폴더에서 npm init 커맨드를 실행하게 되면 package.json 파일을 만들어 주게 됩니다.
편의상 저는 entry point 를 app.js 로 바꾸었고, 나머지는 기본값 혹은 공란으로 비워두었습니다. 생성 된 package.json 파일을 보면 위의 내용이 JSON 형태로 변환 되어 저장 되어있는 것을 보실 수 있습니다. 여기서 한가지 해야 할 일은 scripts 오브젝트에 파일을 실행 할 커맨드를 넣어야 합니다. 메인 파일은 app.js 로 설정해 두었지만 어떠한 커맨드로 메인 파일을 실행시킬 지 정의 되어있지 않기 때문이지요. 그리하여 커맨드를 추가하면 이렇게 됩니다.
{
"name": "nodejs-tutorial",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start": "node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
따라서, npm start 치면 node app.js 커맨드가 실행이 되는데 그 말인즉슨, 만약 scripts 안에 start 커맨드를 정의하지 않고 node app.js 를 바로 타이핑 하셔도 똑같이 실행이 됩니다. 이것 또한 편의를 위한 것이므로, 굳이 번거로우시다면 하지 않으셔도 관계는 없습니다.
이제 package.json 파일이 생성 되었으므로, 메인 파일인 app.js 파일을 생성하고 Express.js 패키지를 설치해 보도록 하겠습니다. 열려 있는 터미널에서 아래의 커맨드를 차례로 실행하여 주세요.
// 참고로 $ (달러 사인) 은 터미널 환경이라는 걸 나타내기 위한 것이므로 실제 커맨드를 실행시키실 땐, 복사하지 마시기 바랍니다.
$ touch app.js // app.js 파일 생성 커맨드
$ npm install express --save // express.js 패키지 설치 후 package.json 파일의 dependencies 에 추가
$ npm install body-parser --save // bodyParse 패키지 설치
맨 마지막 body-parser 패키지는 Node.js 미들웨어로서 JSON, Raw, Text, 그리고 URL encoded 폼 데이터를 핸들링 하기 위해 설치하여 주었습니다. Node.js 에서 미들웨어 (Middleware) 는 중요한 개념이라고 생각하므로, 따로 정리하여 올리도록 하겠습니다.
본격 코딩 시작
위의 단계를 성공적으로 마치셨다면, 이제 본격적으로 코드 작성을 시작해 보도록 하겠습니다.
app.js - 메인 파일로서 미들웨어 사용 선언, 서버 가동 등의 코드를 작성합니다.
'use strict'; // strict 모드 사용
const app = require('express')();
const bodyParser = require('body-parser');
const userRoute = require('./api/routes/user');
const serverPort = Number(process.env.SERVER_PORT) || 8080; // SERVER_PORT 환경변수 값이 존재할 시 사용, 그 외에 8080 사용
app.use(bodyParser.json({ strict: false })); // bodyParse 미들웨어 사용
app.use('/users', userRoute); // userRoute 를 미들웨어로서 사용
// 서버 가동
app.listen(serverPort, () => {
console.log(`App listening on port ${serverPort}.`);
});
user.js (route) - API endpoints 를 선언합니다.
'use strict';
const express = require('express');
const router = express.Router();
const users = require('../../mockData/users');
// Get users
router.get('/', (req, res, next) => {
res.status(200).json(users);
});
// Get user by ID
router.get('/:id', (req, res, next) => {
const userId = Number(req.params.id);
const user = users.find(user => user.id === userId);
if (!user) {
res.status(404).json({ errorMessage: `User with ID ${req.params.id} does not exist.` });
return;
}
res.status(200).json(user);
});
// Create a new user
router.post('/', (req, res, next) => {
if (!req.body.name || !req.body.gender || !req.body.country || !req.body.job) {
res.status(400).json({
errorMessage: 'Invalid request body. Must include name, gender, country, and job.'
});
return;
}
req.body.id = users.length + 1;
users.push(req.body);
res.status(201).json(req.body);
});
// Update a user by ID
router.put('/:id', (req, res, next) => {
const targetUser = users.find(user => user.id === Number(req.params.id));
if (!targetUser) {
res.status(404).json({ errorMessage: `User with ID ${req.params.id} does not exist.` });
return;
}
for (const [key, value] of Object.entries(req.body)) {
targetUser[key] = value;
}
res.status(200).json(targetUser);
});
// Delete a user by ID
router.delete('/:id', (req, res, next) => {
const userIdx = users.findIndex(user => user.id === Number(req.params.id));
if (!userIdx) {
res.status(404).json({ errorMessage: `User with ID ${req.params.id} does not exist.` });
return;
}
users.splice(userIdx, 1);
res.status(200).json({ deleteUser: "Successfully delete." });
});
module.exports = router;
유저 데이터를 핸들링 하는 CRUD (Create, Read, Update, Delete) endpoints 를 만들어 보았습니다. 아직 데이터베이스를 연결하지 않았기에, mock 유저들을 만들어 js 파일 안에 저장하였고, 그 데이터를 바탕으로 엔드포인트들을 구성해 보았습니다.
테스트
Get users - 저장되어 있는 모든 유저 리스트를 리턴합니다. HTTP Method 는 GET 을 사용합니다.
Get user by ID - 주어진 ID 값이 존재할 시 그 아이디를 가진 유저 데이터를 리턴합니다. 만약 아이디가 존재하지 않을 시 404 Not Found 에러를 리턴합니다. Get user by ID 는 URL 파라미터에 아이디 값을 넣어야 합니다. 하지만 Node.js 쪽에서 URL 파라미터는 스트링의 형태로 전달되기 때문에 Number 를 사용하여 숫자의 형태로 변환하여 주어야 합니다.
Create a new user - 새로운 유저를 추가합니다. 포스트맨에서는 HTTP Method 를 POST 로 바꾸고, Body 탭을 선택 후 raw, JSON 을 화면과 같이 선택하신 후 JSON 타입의 리퀘스트 바디를 작성해 주시면 됩니다.
Update a user by ID - 주어진 ID 값을 가진 유저의 디테일을 업데이트 합니다. 유저가 존재하지 않을 시 404 Not Found 를 리턴하고, 주어진 프로퍼티와 값을 바탕으로 업데이트 합니다. 업데이트 HTTP Method 는 PUT 과 PATCH 가 있지만 이 튜토리얼에서는 PUT 을 사용하였습니다.
Delete a user by ID - 주어진 ID 값을 가진 유저를 삭제합니다. HTTP Method 는 DELETE 이며, 바디 리퀘스트는 따로 요구되지 않습니다.
마지막으로, 이 프로젝트의 스트럭쳐입니다. 개인 차가 있을 수 있으나 저는 이 형태의 스트럭쳐를 선호합니다.
다음은?
이번 포스트에서는 routes 만을 사용해서 매우 기본적인 API endpoints 테스트를 해보았습니다. 다음 포스트에서는 Controller, Model Service 를 추가하여 Models-Routes-Controllers-Services 스트럭쳐를 구성해 보도록 하겠습니다.
저도 아직 배우는 중인 초보 개발자이기에, 피드백은 언제나 환영이며 잘못 설명되어 있거나 이해하기 어려운 부분이 있을 시, 댓글로 남겨주시기 바랍니다.
그럼...
'Studying > JavaScript & Frameworks' 카테고리의 다른 글
[Node.js 떠먹여 주는 남자] Node.js 와 MongoDB 설치하기 (macOS) (0) | 2022.03.09 |
---|---|
[Node.js 떠먹여 주는 남자] 샘플 코드에 모델 추가와 MongoDB 연결하기 (0) | 2022.03.09 |
[Node.js 떠먹여 주는 남자] 컨트롤러, 서비스 를 이용한 샘플 코드 확장 (0) | 2022.03.08 |
[Node.js 떠먹여 주는 남자] Express.js (2) | 2022.03.05 |
[Node.js 떠먹여 주는 남자] Node.js 는 무엇인가? (0) | 2022.03.04 |