이번에는 지난 시간에 배웠던 것들을 바탕으로 MongoDB와 REST API를 이용해 실습 프로젝트를 진행할 것이다.
구현할 것은 [할 밀 메모 사이트]로, 기능은 아래와 같다.
1. 할 일 추가하기
2. 할 일 목록 보기
3. 할 일 내용 변경하기
4. 할 일 순서 변경하기
5. 할 일 완료하기
6. 할 일 완료 해제하기
API를 구현하기 위해 Express.js를 이용해 서버를 구현할 것이며, MongoDB에는 데이터를 저장하고, 이를 위해 mongoose를 이용하여 DB와 통신이 가능하도록 할 것이다.
API 서버 준비
- 프로젝트 폴더 생성 -> 터미널을 통해 초기화
# 프로젝트를 초기화합니다.
yarn init -y
# express와 mongoose를 yarn을 이용해 설치합니다.
yarn add express mongoose
- ES6 모듈을 사용할 것이기 때문에 package.json 파일에 "type": "module" 추가
{
"name": "todo-list",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"type": "module", // 추가
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.4.0"
}
}
서버 구현
이번에는 Node.js 서버 하나로 API와 프론트엔드 파일을 제공 받을 것이다. 하지만 이렇게 되면 /memo 주소가 프론트 파일을 가리키게 되고, GET /memo는 API를 가리키게 되며 서버가 혼란스러울 수 있다.
따라서 API 경로는 항상 경로 앞에 /api를 붙이는 방식으로 구현할 것이다. 반대로 /api가 붙지 않는 경우는 프론트엔드 파일을 가리키게 될 것이다.
- /api/memo: API의 메모 정보
- /memo: 프론트엔트 파일
- app.js 전체 코드
import express from 'express';
const app = express();
const PORT = 3000;
// Express에서 req.body에 접근하여 body 데이터를 사용할 수 있도록 설정합니다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 라우터 생성 -> 해당 라우터에다 API 구현
const router = express.Router();
// 이 라우터를 전역 middleware로 등록
// '/' 경로에다 GET 요청을 처리한다.
// 즉, 이 라우터가 사용되는 위치에서 '/'로 요청이 들어올 때 응답을 보낸다.
router.get('/', (req, res) => {
return res.json({ message: 'Hi!' });
});
// 앞에 /api가 붙은 경우에만 해당하는 API로 접근 가능
// 즉, 라우터를 /api 경로에 연결한 것.
// 따라서 라우터에 정의된 모든 경로는 /api 가 앞에 붙어서 동작하게 된다.
app.use('/api', router);
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
코드를 정리해보자면, 다음과 같다.
- 라우터 생성 및 API 구현
여기서 router는 express.Router()를 사용해 만들어진 새로운 라우터 객체이다.
이 라우터 객체는 '/' 경로에 대한 GET 요청을 처리한다. 즉, 이 라우터가 사용되는 위치에서 '/'로 요청이 들어올 때, 응답을 보낸다.
const router = express.Router();
router.get('/', (req, res) => {
return res.json({ message: 'Hi!' });
});
- 라우터를 특정 경로에 붙이기
아래 코드는 router를 /api 경로에 연결하는 것이다. 즉, 라우터에 정의된 모든 경로는 /api 경로가 앞에 붙어 있어야 한다.
app.use('/api', router);
요약하자면, 라우터는 '/' 경로를 정의하고 있지만, app.use()에 의해 /api 경로에 연결되었다.
그 결과 /api 경로가 앞에 붙어야만 라우터에서 정의한 경로들이 동작한다.
- 알아두면 좋은 것
app.use(express.json());
express.json 미들웨어는 클라이언트의 요청을 받을 때 body에 있는 데이터를 정상적으로 사용할 수 있게 분석해주는 역할을 한다. 그로인해 우리는 JSON 형태의 body를 입력받을 수 있다.
프론트엔드 파일 추가 & 백엔드에서 서빙하기
부트캠프에서 나눠주는 파일을 다운받고, 프로젝트에 추가한다. 파일 경로들은 다음과 같다.
내 프로젝트 폴더 이름
├── app.js
├── assets
│ ├── asset-manifest.json
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ ├── robots.txt
│ └── static
│ ├── css
│ │ ├── main.6842b365.chunk.css
│ │ └── main.6842b365.chunk.css.map
│ └── js
│ ├── 2.96129310.chunk.js
│ ├── 2.96129310.chunk.js.LICENSE.txt
│ ├── 2.96129310.chunk.js.map
│ ├── 3.0962e34f.chunk.js
│ ├── 3.0962e34f.chunk.js.map
│ ├── main.c5ceafa0.chunk.js
│ ├── main.c5ceafa0.chunk.js.map
│ ├── runtime-main.2ec3457b.js
│ └── runtime-main.2ec3457b.js.map
├── package-lock.json
└── package.json
파일을 추가했다면, assets 파일을 서빙할 수 있도록 static 미들웨어를 추가한다.
// app.js
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// assets 폴더에 있는 모든 파일들을 서빙할 것이다.
// 즉, 정적인 파일을 assets 폴더에 있는 파일들을 바탕으로 서빙을 할 거다.
app.use(express.static('./assets')); // <- 추가된 코드!
이는 프론트엔드를 담고 있는 assets 폴더를 Express 서버에서 접근할 수 있도록 정적 파일 미들웨어를 사용한 것이다.
!! 잠깐 !!
서빙(Serving)이란, 웹 개발에서 서버가 클라이언트로 파일을 제공하는 것이다. 즉, 클라이언트가 파일을 요청하면 서버가 그 파일을 찾아서 클라이언트에게 전송해주는 과정을 의미한다.
app.use(express.static('./assets'));
따라서 위 코드는 Express.js에서 제공하는 정적 파일을 서빙하는 미들웨어를 설정하는 부분이다. 여기서 express.static() 함수는 정적 파일을 제공하는 역할을 한다.
하여, 클라이언트는 ./assets 폴더에 있는 모든 파일을 직접 요청할 수 있다.
예를 들어 ./assets 폴더 안에 logo192.png 라는 이미지 파일이 있다면, 클라이언트는 http://localhost:3000/logo192.png 와 같은 URL로 해당 파일을 요청할 수 있다. 그러면 서버는 그 파일을 찾아 클라이언트로 전송(서빙)한다.
해서, http://localhost:3000/로 접속을 하면 다음과 같은 창으로 변한다.
index.js 파일이 보이는 이유는 index.js 파일이 기본 루트로 설정되었기 때문이다. 따라서 아무런 경로를 입력하지 않으면 index.js 파일을 보여준다.
'프로젝트' 카테고리의 다른 글
24/09/06 - [실습] 할 일 메모 사이트(3): Create, Read 구현 (0) | 2024.09.06 |
---|---|
24/09/05 - [실습] 할 일 메모 사이트(2): 스키마(Schema) 설계 (0) | 2024.09.05 |
24/08/29 - [개인] 로그 라이크 게임(3): 최종 결과물 및 피드백 (0) | 2024.08.29 |
24/08/23 - [개인] 로그 라이크 게임(2): JS 클래스의 _와 private (0) | 2024.08.23 |
24/08/22 - [개인] 로그 라이크 게임(1) (0) | 2024.08.22 |