본문 바로가기
Backend/Node.js

Express 팁 ( 쉬운 )

by 잘먹는 개발자 에단 2025. 7. 22.

1. 미들웨어 중심의 아키텍처를 잘 활용하여야 한다.

- 요청과 응답 객체에 접근하고, 다음 미들웨어 호출 중심의 아키텍처를 잘 활용하여야 한다.

 

- 요청과 응답 객체에 접근하고, 다음 미들웨어 함수를 호출하는 ( next() ) 함수들의 연속으로 어플리이션의 로직이 구성된다. 

 

- 기능분리 

  ㄴ 각 미들웨어는 하나의 명확한 기능을 담당하도록 작성해야한다. ( 로깅, 인증, 데이터파싱 ) 예를 들어서, 요청 본문을 파싱하는 express.json(), express.urlencoded()나 CORS를 처리하는 CORS 같은 미들웨어를 사용하는 것이 일반적이다.

 

- 실행 순서의 중요성

  ㄴ 미들웨어는 app.use()나 라우터에 등록된 순서대로 실행된다. 따라서 인증 미들웨어는 항상 실제 로직을 처리하는 라우터보다 먼저 위치해야 한다. 순서가 잘못되면 의도치 않은 결과를 초래할 수 있다. 

 

- 에러처리 미들웨어

  ㄴ 일반 미들웨어와 다르게 에러처리 미들웨어는 (err, req, res, next) 4개의 인자를 가진다. 이 미들웨어는 모든 라우터와 미들웨어 체인의 가장 마지막에 위치시켜서 중앙에서 에러를 효과적으로 관리해야 한다. 

 

// 1. 일반 미들웨어 ( 요청시간 로깅 )
app.use((req, res, next)=>{
	console.log('Time:', Date.now());
    next();
})

// 2. 라우터
app.use('/api/users', userRoutes);

// 3. 에러처리 미들웨어 ( 가장 마지막에 위치 )
app.use((err, req, res, next)=>{
	console.error(err.stack);
    res.status(500).send('Something broke!');
})

 

 

2. 라우터 분리

- 어플리케이션의 규모가 커지면 모든 라우트를 app.js 파일 하나에 관리하기 어렵다. 

 

- express.Router를 사용해 기능별로 라우터 파일을 분리하는 것이 필수적이다.

  ㄴ 관심사 분리 Separation of Concerns : 사용자 관련 api는 route/user.js, 상품 관련 api는 routes/product.js와 같이 도메인 별로 파일을 분리한다.

  ㄴ 모듈화 : 각 라우트 파일은 express.Router 인스턴스를 생성하여 로직을 정의하고, 이를 모듈로 export 한다. 메인파일 app.js에서는 이 모듈들을 import 하여 특정 경로에 연결한다. 

 

 

3. 비동기 처리와 에러 핸들링

- Node.js 환경상 비동기 작업이 많으므로, 이를 효과적으로 처리하는 것이 중요하다.

 

- Promise와 async/await 활용 : 콜백 지옥을 피하기 위해서 Promise나 async/await 문법을 적극적으로 사용해야한다. 이는 코드를 더 읽기 쉽고 동기적인 흐름처럼 보이게 해준다.

 

- 비동기에러처리 : async/await을 사용할 때 try...catch 블록으로 비동기 작업 중 발생할 수 있는 에러를 잡아 next(err)를 통해 에러처리 미들웨어로 전달해야 한다. 혹은 express-async-handler와 같은 라이브러리를 사용하면 이 과정을 자동화할 수 있다. 

router.get('/:id', async (req, res, next) => {
  try {
    const user = await User.findById(req.params.id);
    if (!user) {
      return res.status(404).send('User not found');
    }
    res.send(user);
  } catch (err) {
    next(err); // 에러를 중앙 에러 핸들러로 전달
  }
});

 

 

4. 환경변수 관리

- 데이터베이스 접속정보, api 키 등 민감하거나 환경에 따라서 달라지는 설정 값들은 코드에 직접 하드코딩해서는 안된다.

- .env 파일 사용 : dotenv 라이브러리를 사용하여, .env 파일에 환경변수를 정의하고, process.env 객체를 통해 접근하는 것이 일반적이다. .env 파일은 .gitignore에 추가하여 Git 저장소에 올라가지 않도록 주의해야한다.

require('dotenv').config();

const port = process.env.PORT || 5000;
const mongoUri = process.env.MONGO_URI;

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

 

 

5. MVC 패턴 활용 

- Express 자체는 특정 아키텍처를 강요하지 않지만, MVC 패턴 또는 이와 유사한 구조를 적용하면 코드베이스를 체계적으로 구성할 수 있다. 

  ㄴ Controller : 라우트 핸들러의 로직이 길어지면 별도의 컨트롤러 함수로 분리한다. 컨트롤러는 요청을 받아서 비즈니스 로직 Service을 호출하고, 그 결과를 응답으로 보낸다.

  ㄴ Service ( or Business Logic ) : 실제 어플리케이션의 핵심 비즈니스 로직을 담당한다. 데이터베이스 모델과 상호작용하고, 복잡한 계산 등을 처리한다.

  ㄴ Model : 데이터베이스 스키마를 정의하고 데이터에 접근하는 계층이다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Backend > Node.js' 카테고리의 다른 글

Passport 인증 미들웨어  (0) 2025.04.22
[Express] 정리 (1)  (0) 2025.04.10