반응형

이전 포스팅에서는

아주 기본적인 형태의 라우팅을 적용해보았다.

(+ 라우팅이 무엇인지)

🔗 이전 포스팅 링크 : https://woojin.tistory.com/25

 

[Express] 간단한 라우팅 적용하기 (Typescript 사용) #Node.js #Express

이전 포스팅에 이어서, 간단한 라우팅을 적용해보자. (이전 포스팅) Express 간단한 서버 세팅 👇 https://woojin.tistory.com/24 라우팅(Routing)이란? 애플리케이션 엔드포인트(URI)의 정의, 그리고 URI가 클

woojin.tistory.com

 

이번 포스팅에서는

유지보수가 용이하도록

라우터 관련 코드를 적절히 분리시켜보자.

 


 

디렉토리 구조 만들기

위와 같이 디렉토리 구조를 설계한다.

빈껍데기인 파일만 만들어 놓아도 된다.

 

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를 통해 전달된다.

실행 결과는 위와 같다.

 

 

 

간단한 라우팅 구조에서

유지보수가 용이한 라우터 분리 구조로 수정해보았다.

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

+ Recent posts