이전 포스팅에서는
아주 기본적인 형태의 라우팅을 적용해보았다.
(+ 라우팅이 무엇인지)
🔗 이전 포스팅 링크 : https://woojin.tistory.com/25
이번 포스팅에서는
유지보수가 용이하도록
라우터 관련 코드를 적절히 분리시켜보자.
디렉토리 구조 만들기
위와 같이 디렉토리 구조를 설계한다.
빈껍데기인 파일만 만들어 놓아도 된다.
src/api : 블로그 관련 api를 묶어놓은 폴더
src/router : api 폴더에 있는 api들의 라우팅을 담당하는 폴더
blog.ts, signup.ts, user.ts는 간단한 api를 구현한 것으로, 아래에서 상세 내용을 다루겠다.
디렉토리 구조 설명
대략적인 디렉토리 구조를 설명하고 넘어가보려 한다.
localhost:8080/api/user/1 에 GET 메서드를 요청한다면,,
1. index.ts로 이동한다.
2 .api를 보고 router/index.ts로 이동한다.
3. user를 보고 router/userRouter.ts로 이동한다.
4. get 메서드를 보고 파라미터(userId : 1)를 가지고 api/user.ts 에서 정의한 selectUser로 이동한다.
5. api/user.ts에서 정의한 selectUser를 실행한다.
쉽게 말하면,
api에서는 api 기능에 대한 내용을 다루고,
router에서는 메서드 종류와 요청에 대한 분기를 다룬다.
내용에 따라 폴더가 분리되어 있어, 쉽게 위치를 파악하고 유지보수할 수 있다.
api 폴더 작성
// blog.ts
import { Request, Response } from "express";
const selectPost = async (req: Request, res: Response) => {
const param = req.params;
return res.status(200).json({
status: 200,
message: "포스팅 조회 성공",
posting_number: param.blogId
});
};
const likePost = async (req: Request, res: Response) => {
const param = req.params;
return res.status(200).json({
status:200,
message: "좋아요 성공",
posting_number: param.blogId
});
};
export { selectPost, likePost };
blog.ts에서는 selectPost와 likePost 두 개의 함수를 정의한다.
req.params는 뒤에서 정의할 request url 상 파라미터를 가져오는 것이다.
// signup.ts
import { Request, Response } from 'express';
const signup = async (req: Request, res: Response) => {
return res.status(201).json({
status: 201,
message: "회원가입 성공",
});
}
export default signup;
// user.ts
import { Request, Response } from "express";
const selectUser = async (req: Request, res: Response) => {
const param = req.params
return res.status(200).json({
status: 200,
message: "유저 조회 성공",
data: param
});
};
export default selectUser;
json 형식의 메세지와 상태코드를 응답(response)한다.
router 폴더 작성
// blogRouter.ts
import express, { Router } from "express";
import { likePost, selectPost } from "../api/blog";
const router: Router = express.Router();
router.get('/:blogId', selectPost);
router.get('/like/:blogId', likePost);
export default router;
Router를 따로 import해놓고, express.Router()를 사용하는 것은
에어비엔비 표준 규격을 맞추기 위함이라고 한다.
코드에서 보이다시피, 특정 엔드포인트에 특정 메서드가 요청되면, api 폴더에 작성한 파일의 함수가 불러와진다.
엔드포인트 뒤에 ':blogId'와 같은 것은 url로 전달받은 파라미터를 저장할 변수명이다.
예를 들어 블로그 id가 3인 포스팅을 'likePost'하려고 한다면,
localhost:8080/api/blog/like/3 과 같이 요청을 받아
3을 'blogId'에 저장해서 likePost 함수가 있는 api/blog.ts로 전달하는 것이다.
// signupRouter.ts
import express, { Router } from 'express';
import signup from '../api/signup';
const router: Router = express.Router();
router.post('/', signup);
export default router;
// userRouter.ts
import express, { Router } from "express";
import selectUser from "../api/user";
const router: Router = express.Router();
router.get('/:userId', selectUser);
export default router;
마지막으로 index.ts를 만들어준다 (router 폴더 내부에 있는 index.ts)
// router/index.ts
import express, { Router } from "express";
import userRouter from "./userRouter";
import blogRouter from "./blogRouter";
import signupRouter from "./signupRouter";
const router: Router = express.Router();
router.use('/user', userRouter);
router.use('/blog', blogRouter);
router.use('/auth', signupRouter);
export default router;
위에서 작성한 파라미터 앞단에 붙는 url을 정의한다.
/user는 userRouter로 이동하고 (..)
이렇게 정의한 router는,
아래에서 루트 디렉토리에 있는 index.ts로 전달한다.
index.ts(루트 디렉토리) 작성
// index.ts
import express, { Request, Response, NextFunction } from 'express';
import apiRoute from './router/index'; // export한 이름과 다르게 import할 수 있다!
const app = express();
app.use(express.json());
app.use('/api', apiRoute);
app.get('/', (req: Request, res: Response, next: NextFunction) => {
res.send('Hi! This is server tutorial.');
});
app.listen('8080', () => {
console.log(`
#############################################
🛡️ Server listening on port: 8000 🛡️
#############################################
`);
});
이제 라우팅 구조가 명확하게 보일 것이다.
아래 예시들에 설명을 달아보자.
1. localhost:8080/ (get)
index.ts의 app.get에 따라 'Hi! This is server tutorial.'이 response로 보내진다.
실행 결과는 위와 같다.
2. localhost:8080/api/user/1 (get)
index.ts에서,
app.use('/api', apiRoute) 를 보고 apiRoute를 import한 ./router/index.ts로 이동한다.
./router/index.ts에서,
router.use('/user', userRouter)에 의해 userRouter를 import한 ./router/userRouter.ts로 이동한다.
./router/userRouter.ts에서,
router.get('/:userId', selectUser)로 이동해 userId:1 을 selectUser로 전달한다.
./api/user.ts에서,
selectUser가 실행되고, userId:1 은 req.params를 통해 전달된다.
실행 결과는 위와 같다.
간단한 라우팅 구조에서
유지보수가 용이한 라우터 분리 구조로 수정해보았다.
'Javascript, Typescript > Node, Express, Nest.js' 카테고리의 다른 글
[express] express-validator로 request body 유효성 검사하기 #node.js #express #validation #express-validator (0) | 2022.05.12 |
---|---|
[express] 프로젝트 시작하고 CRUD 구현하기 (+프로젝트 구조 알아보기) #express #node.js #typescript #MongoDB (2) | 2022.05.11 |
[Express] 간단한 라우팅 적용하기 (Typescript 사용) #Node.js #Express (0) | 2022.04.24 |
[Express] 간단한 서버 만들기 (Typescript 사용) #Node.js #Express (0) | 2022.04.24 |
Express 초기 세팅, yarn 사용법 (0) | 2022.04.22 |