백엔드 기초 마무리

Younha Lee·2026년 1월 29일

TIL

목록 보기
21/67

Router

라우터 이전에 라우팅(Routing)을 먼저 알아보고 넘어가겠습니다.

라우팅은 URI(또는 경로)와 특정 HTTP 요청 메서드(GET, POST 등)인 특정 엔드포인트에 대한 클라이언트 요청에 애플리케이션이 응답하는 방식을 결정하는 것

쉽게 이야기해서 요청에 대해 적절한 경로로 안내하는 것입니다. Express의 route를 사용하면 지금까지 같은 주소에 대해서 다른 HTTP 요청 메서드 함수를 따로 작성했던 것이 깔끔해집니다.

여기서 한 단계 더 나아가서 요청들을 기능에 맞게 여러 파일로 분리한다면 얼마나 좋을까요? 진행하는 프로젝트도 사서와 책에 대한 요청들을 구분해서 파일을 만들었습니다. 이를 하나의 파일에서 express.Router()를 사용해 각 요청 파일을 하나의 모듈(미들웨어)로 만들고 app.js에서 사용해 보겠습니다.

파일 구조 기반으로 라우팅 리팩토링


기존에 app.js 에 모든 파일을 넣던 구현에서 도메인 기준으로 파일을 나눴어요.
export default routerusers.js 를 export 하여 app.js 에서 다음과 같이 라우팅 미들웨어를 사용하게 했어요.

// app.js
import express from 'express';
import userRouter from './routes/users.js'; // router import

const app = express();
const PORT = 3000;
app.listen(PORT, () => console.log(`Server is running on ${PORT}`));

app.use('/', userRouter); // app에 등록
// routes/users.js
import express from 'express';
const router = express.Router();
router.use(express.json());

// ~~ 로직 작성
export default router; // router export

똑같이 '/users' 로 요청을 보내서 라우팅이 잘 되었나 확인해봤어요.

잘 된 것을 확인할 수 있었어요.app.use('/channels', channelRouter);

일일히 app을 router로 변경할 때 refactoring 기능을 사용해봅시다

  • 결론 prefix 대로 라우팅을 분리해서 도메인별로 컨트롤러를 갖게 하자.
  • app.js는 글로벌하게 적용하는 미들웨어만 등록하자.
    정도로 express 파일구조를 정리할 수 있어요!

중복되는 URL 합치기

// routes/channels.js
router
    .route('/')
    .get((req, res) => {
        const channels = Array.from(db.values());
        res.json(channels);
    })
// app.js
app.use('/channels', channelRouter);

channels.js에서는 모든 api의 prefix가 channels다 보니 app.js에서 해당 prefix를 지정했어요.
users.js도 리팩토링한다면, auth 모듈을 따로 만들고 users는 prefix로 지정했을 것 같아요.

제대로 ERD 그리기

지금까지는 유저 테이블과 채널 테이블이 별개였는데, 이제 1:n 관계를 적용해서 연결해보려 해요.
유저 테이블 - id, email, password, nickname
채널 테이블 - id, channel_title, user_id

그리고 api 설계에서 원래는 jwt를 통해 헤더에서 요청을 보낸 유저의 id를 가져와야하는데, 일단 body에 userId를 담기로 했어요.

추가된 API

기존 api에, email을 기반으로 해당 유저의 채널을 조회하는 GET /channels를 추가하려고 해요.
그렇기 때문에, 해당 이메일이 유저 테이블에 없으면 예외 처리하는 코드도 추가했어요.

    .get((req, res) => {
        let { email } = req.body;
        let channels = [];

        // db에서 하나씩 가져온 채널 주인의 email이 req.body.email와 같은지 검증
        db.forEach((value, key) => {
            if (value.email === email) channels.push(value);
        })
        // 예외처리
        if(channels.length === 0) return res.status(404).json(
            { "message": "No Channel Found" }
        )
        res.json(channels);
    })


GET 요청에는 body보다는 query string을 이용하는 것이 관례지만 일단 바디에 담는 것으로 만들었어요.

profile
할 땐 하고 놀 땐 노는 일일놀놀입니다.

0개의 댓글