본문 바로가기
프로젝트

24/09/05 - [실습] 할 일 메모 사이트(1): 설계 & 서버 구현 & 프론트엔드 서빙

by Jini_Lamp 2024. 9. 5.

이번에는 지난 시간에 배웠던 것들을 바탕으로 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 파일을 보여준다.