모든 개발자가 따라야 할 백엔드 설정

발행: (2026년 3월 3일 오후 09:27 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

모든 개발자가 따라야 할 백엔드 설정 커버 이미지

소개

백엔드 코드를 작성하기 전에, 확장성, 디버깅, 협업을 더 원활하게 도와주는 깔끔하고 체계적인 설정을 갖추는 것이 매우 중요합니다.

다음은 주요 6가지 레이어입니다:

  • 라우트
  • 컨트롤러
  • 미들웨어
  • 서비스
  • 레포지토리
  • 데이터베이스

라우트 – 진입점

라우트는 특정 요청이 서버에 도달했을 때 어떤 함수가 실행되어야 하는지를 정의합니다. HTTP 메서드와 URL을 컨트롤러에 매핑합니다.

router.post("/signup", userController.signup);
router.get("/profile", authMiddleware, userController.getProfile);

라우트는 얇고 깔끔해야 합니다. 로직을 포함하지 않으며, 요청이 어디로 가야 하는지만 결정합니다. 라우트를 백엔드의 로드맵이라고 생각하세요.

컨트롤러 – 요청 핸들러

컨트롤러가 수행하는 일:

  • 요청 데이터 읽기 (req.body, req.params, req.query)
  • 응답 전송 (res.json, res.status)
  • 서비스 레이어 호출

컨트롤러가 하지 말아야 할 일:

  • 비즈니스 로직 포함
  • 데이터베이스에 직접 접근
  • 비밀번호 해시 처리
  • 비즈니스 규칙 계산

컨트롤러를 리셉션 직원에 비유하면, 요청을 받고 응답을 전달하는 역할을 합니다.

Middleware – The Gatekeepers

미들웨어는 컨트롤러보다 먼저 실행됩니다. 다음과 같은 용도로 사용됩니다:

  • Authentication (JWT verification)
  • Logging
  • Input validation
  • Rate limiting
  • Error handling
router.get("/profile", authMiddleware, userController.getProfile);

요청은 컨트롤러에 도달하기 전에 미들웨어를 통과해야 합니다. 미들웨어를 공항의 보안 검사에 비유해 보세요.

Services – The Brain of the Application

This is where your real logic lives. Services handle:

  • 비즈니스 규칙
  • 데이터 변환
  • 워크플로우 결정
  • 여러 저장소의 오케스트레이션
exports.signup = async ({ email, password }) => {
  const existingUser = await userRepository.findByEmail(email);

  if (existingUser) {
    throw new Error("User already exists");
  }

  const hashedPassword = await bcrypt.hash(password, 10);

  return await userRepository.createUser(email, hashedPassword);
};

Think of services as the decision‑maker.

Repository – 데이터 액세스 레이어

Repository는 다음을 담당합니다:

  • 데이터베이스와 통신
  • 쿼리 실행
  • 원시 데이터 반환

It does NOT:

  • 비즈니스 규칙 결정
  • 로직 검증
exports.findByEmail = async (email) => {
  return db("users").where({ email }).first();
};

Repository는 데이터베이스에 대한 추상화입니다. PostgreSQL에서 MongoDB로 전환하더라도 변경되어야 하는 것은 레포지토리 레이어뿐입니다. 레포지토리를 애플리케이션과 데이터베이스 사이의 번역가로 생각하세요.

데이터베이스 – 스토리지 엔진

This is your:

  • PostgreSQL
  • MySQL
  • MongoDB
  • Supabase

Its job is simple:

  • 데이터 저장
  • 데이터 검색
  • 무결성 유지

It does not care about HTTP, business logic, or application rules; it only stores information.

전체 요청 흐름

  1. 사용자가 가입합니다.
  2. 요청이 Route에 도달합니다.
  3. Middleware가 토큰/입력을 검증합니다.
  4. Controller가 요청을 받습니다.
  5. ControllerService를 호출합니다.
  6. Service가 비즈니스 로직을 적용합니다.
  7. ServiceRepository를 호출합니다.
  8. RepositoryDatabase와 통신합니다.
  9. 응답이 체인을 거슬러 올라갑니다.
Database → Repository → Service → Controller → Client

깨끗함. 예측 가능함. 확장 가능.

🧠 간단한 사고 모델

어디에 속하는지 헷갈릴 때는 다음과 같이 물어보세요:

  • HTTP를 처리하나요? → Controller
  • 검증/인증/로그를 수행하나요? → Middleware
  • 비즈니스 로직인가요? → Service
  • 데이터베이스 쿼리인가요? → Repository
  • 스토리지인가요? → Database
  • 엔드포인트를 컨트롤러에 매핑하나요? → Route

이 구조는 로버트 C. 마틴의 Clean Architecture에서 대중화된 아키텍처 원칙에서 영감을 받았으며, 실용적인 백엔드 애플리케이션을 위해 단순화되었습니다.

0 조회
Back to Blog

관련 글

더 보기 »

TDD의 중요성

문제는 제가 12개의 매개변수를 가진 “awesome” API를 만들었다는 것입니다. 그 API는 형편없었습니다. 제 머릿속을 박사 수준으로 이해하지 않으면 아무도 사용할 수 없었습니다. 수년간 백엔드 개발을 하면서, 저는…

스프린트

!Sprint: Express 코드 중복 없이 https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9mcbu1c3wuvlq0tiuup0.png 소개 Sprint: 코드 중복을 없애세요