프로그래밍/Node.js

Express.js: 웹 애플리케이션 개발을 위한 강력한 도구

shimdh 2025. 2. 20. 09:25
728x90

1. Express.js 소개 및 설치

1.1 Express.js란?

Express.js는 Node.js 환경에서 웹 애플리케이션을 구축하기 위한 빠르고 유연한 프레임워크입니다. 경량화되어 있으며 유연한 구조를 가지고 있어 RESTful API와 웹 애플리케이션을 쉽게 구축할 수 있습니다.

1.1.1 Express.js의 특징

  • 미들웨어: 요청과 응답 사이에서 기능을 추가하거나 수정하는 미들웨어를 통해 코드의 재사용성을 높이고, 유지보수를 용이하게 합니다.
  • 라우팅: URL 경로에 따라 서로 다른 핸들러 함수를 지정하여 사용자 요청에 대한 처리를 간편하게 할 수 있습니다.
  • 템플릿 엔진 지원: 다양한 템플릿 엔진(Pug, EJS 등)을 사용하여 동적인 HTML 페이지 생성을 지원합니다.
  • 정적 파일 제공: 이미지, CSS, JavaScript 파일과 같은 정적 파일을 쉽게 제공할 수 있습니다.
  • 확장성: 다양한 플러그인과 확장 기능을 통해 기능을 쉽게 추가할 수 있습니다.

1.2 Express.js 설치 방법

Express.js를 설치하기 위해서는 먼저 Node.js가 설치되어 있어야 하며, npm(Node Package Manager)을 통해 쉽게 설치할 수 있습니다.

1.2.1 Node.js 설치 확인

node -v

위 명령어로 Node.js가 제대로 설치되었는지 확인합니다.

1.2.2 새로운 프로젝트 생성

새로운 디렉토리를 만들고 해당 디렉토리로 이동 후 초기화를 진행합니다.

mkdir my-express-app
cd my-express-app
npm init -y

1.2.3 Express 패키지 설치

다음 명령어로 Express를 프로젝트에 추가합니다.

npm install express --save

1.2.4 기타 유용한 패키지 설치

개발을 편리하게 해주는 몇 가지 추가 패키지를 설치합니다.

npm install morgan nodemon
  • morgan: HTTP 요청 로거 미들웨어입니다.
  • nodemon: 소스 코드 변경 시 자동으로 서버를 재시작해주는 도구입니다.

1.3 기본 서버 설정 예제

아래는 간단한 Express 서버 설정 예제입니다:

// app.js 파일 생성 후 아래 코드 작성

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// 기본 라우트 설정
app.get('/', (req, res) => {
    res.send('안녕하세요! Express 서버에 오신 것을 환영합니다.');
});

// 서버 시작
app.listen(PORT, () => {
    console.log(`서버가 http://localhost:${PORT} 에서 실행 중입니다.`);
});

위 코드를 app.js라는 파일에 저장하고 터미널에서 다음 명령어로 실행하면 됩니다:

node app.js

브라우저에서 http://localhost:3000으로 접속하면 "안녕하세요! Express 서버에 오신 것을 환영합니다."라는 메시지를 볼 수 있습니다.

1.4 예제: 정적 파일 제공

정적 파일(이미지, CSS, JavaScript 등)을 제공하려면 express.static 미들웨어를 사용합니다.

// public 폴더 생성 후 그 안에 이미지나 CSS 파일 등을 넣습니다.
app.use(express.static('public'));

이제 public 폴더 내의 파일들은 URL을 통해 접근할 수 있습니다. 예를 들어, public/images/logo.png 파일은 http://localhost:3000/images/logo.png로 접근할 수 있습니다.

1.5 예제: nodemon 사용

package.json 파일의 scripts 부분을 수정하여 nodemon을 사용하도록 설정합니다.

"scripts": {
  "start": "nodemon app.js"
}

이제 npm start 명령어를 사용하면 nodemon이 실행되어 코드 변경 시 서버가 자동으로 재시작됩니다.

1.6 예제: 환경 변수 사용

.env 파일을 생성하여 환경 변수를 관리할 수 있습니다. 이를 위해 dotenv 패키지를 설치합니다.

npm install dotenv

.env 파일에 다음과 같이 작성합니다:

PORT=5000

app.js 파일 상단에 dotenv를 설정합니다:

require('dotenv').config();

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// ... 나머지 코드

이제 PORT 환경 변수가 설정되어 있지 않으면 기본값으로 3000을 사용하고, 설정되어 있으면 해당 값을 사용합니다.


2. 미들웨어 사용

2.1 미들웨어란?

미들웨어는 HTTP 요청이 들어오고 응답이 나가기 전에 처리되는 함수입니다. 이들은 요청 객체(req), 응답 객체(res) 및 다음 미들웨어 함수를 호출하는 next() 함수를 인자로 받습니다.

2.2 기본적인 미들웨어 예제

const express = require('express');
const app = express();

// 기본 미들웨어
app.use((req, res, next) => {
    console.log(`요청 URL: ${req.url}`);
    next(); // 다음 미들웨어로 넘어감
});

// 라우트 정의
app.get('/', (req, res) => {
    res.send('홈페이지에 오신 것을 환영합니다!');
});

app.listen(3000, () => {
    console.log('서버가 3000번 포트에서 실행 중입니다.');
});

위 예제에서 첫 번째 미들웨어는 모든 요청의 URL을 로그로 출력하고 next()를 호출하여 다음 처리를 이어갑니다.

2.3 미들웨어의 종류와 사용 방법

2.3.1 애플리케이션 수준 미들웨어

전체 애플리케이션에 적용되는 미들웨어로, app.use() 메서드를 통해 등록합니다.

2.3.2 라우터 수준 미들웨어

특정 라우터에만 적용되는 미들웨어로, router.use() 메서드를 사용하여 설정할 수 있습니다.

2.3.3 내장된 미들웨어

Express에서 제공하는 기본 내장형 기능 (예: body-parser, express.static).

2.3.4 커스텀 미들웨어

사용자 정의 로직을 담은 함수로 작성 가능합니다.

2.3.5 써드파티 미들웨어

npm을 통해 설치하여 사용하는 외부 라이브러리 (예: morgan, cors).

2.4 라우터 수준의 커스텀 미들웨어 예제

const express = require('express');
const router = express.Router();

// 커스텀 인증 체크 미들웨어
function checkAuth(req, res, next) {
    if (req.isAuthenticated()) { // 가상의 인증 체크 로직
        return next();
    }
    res.status(403).send('접근 거부!');
}

// 보호된 라우트 설정
router.get('/protected', checkAuth, (req, res) => {
    res.send('비밀 정보 접근 성공!');
});

module.exports = router;

위 코드는 /protected 경로에 대한 접근 시 인증 여부를 확인하는 커스텀 모듈을 생성한 것입니다.

2.5 예제: 로깅 미들웨어

morgan을 사용하여 HTTP 요청을 로그로 남기는 미들웨어를 추가합니다.

const express = require('express');
const morgan = require('morgan');
const app = express();

// HTTP 요청 로거 미들웨어
app.use(morgan('dev'));

// ... 나머지 코드

2.6 예제: JSON 파싱 미들웨어

body-parser를 사용하여 JSON 요청 본문을 파싱하는 미들웨어를 추가합니다. (Express 4.16.0 이상 버전에서는 express.json()으로 대체 가능)

const express = require('express');
const app = express();

// JSON 요청 본문 파싱 미들웨어
app.use(express.json());

// POST 요청 예제
app.post('/api/data', (req, res) => {
    console.log(req.body); // 파싱된 JSON 데이터
    res.json({ message: '데이터 수신 완료', data: req.body });
});

// ... 나머지 코드

2.7 예제: 에러 핸들링 미들웨어

에러를 처리하는 미들웨어를 작성하여 중앙에서 에러를 관리할 수 있습니다.

const express = require('express');
const app = express();

// ... 라우트 및 다른 미들웨어

// 에러 핸들링 미들웨어
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('서버 에러 발생!');
});

// ... 나머지 코드

2.8 예제: CORS 처리 미들웨어

cors 미들웨어를 사용하여 Cross-Origin Resource Sharing(CORS)를 허용합니다.

const express = require('express');
const cors = require('cors');
const app = express();

// CORS 허용
app.use(cors());

// ... 나머지 코드

2.9 예제: 세션 관리 미들웨어

express-session 미들웨어를 사용하여 세션을 관리합니다.

const express = require('express');
const session = require('express-session');
const app = express();

// 세션 설정
app.use(session({
  secret: 'your-secret-key', // 세션을 암호화하기 위한 키
  resave: false,
  saveUninitialized: true,
  cookie: { secure: false } // HTTPS가 아닌 경우 false로 설정
}));

// 세션 사용 예제
app.get('/', (req, res) => {
  if (req.session.views) {
    req.session.views++;
    res.send(`방문 횟수: ${req.session.views}`);
  } else {
    req.session.views = 1;
    res.send('처음 방문하셨습니다.');
  }
});

2.10 미들웨어의 활용 사례

  • 로그 기록: 모든 요청 정보를 기록하거나 특정 이벤트 발생 시 로그를 남기는 데 사용할 수 있습니다.
  • 요청 데이터 파싱: 클라이언트가 전송한 JSON 또는 폼 데이터를 쉽게 처리하기 위해 body-parser 같은 내장 모듈을 사용할 수 있습니다.
  • CORS 설정: 다른 도메인에서 오는 요청을 허용하기 위해 CORS 정책을 설정할 때 유용합니다.
  • 세션 관리: 사용자 세션 정보를 저장하고 관리하기 위해 session middleware를 사용할 수 있습니다.
  • 인증 및 권한 부여: 사용자의 로그인 상태를 확인하고, 특정 리소스에 대한 접근 권한을 제어합니다.
  • 정적 파일 제공: 이미지, CSS, JavaScript 파일과 같은 정적 파일을 제공합니다.

3. 라우팅 및 컨트롤러

3.1 라우팅이란?

라우팅은 클라이언트가 서버에 요청할 때, 해당 요청을 어떤 코드로 처리할지를 결정하는 과정입니다. Express.js에서는 다양한 HTTP 메서드(GET, POST, PUT, DELETE 등)에 따라 특정 URL 경로와 연결된 핸들러 함수를 설정할 수 있습니다.

3.2 기본 라우팅 예제

const express = require('express');
const app = express();

// GET 요청 처리
app.get('/hello', (req, res) => {
    res.send('안녕하세요!');
});

// POST 요청 처리
app.post('/submit', (req, res) => {
    // 클라이언트로부터 받은 데이터 처리
    res.send('데이터가 제출되었습니다.');
});

app.listen(3000, () => {
    console.log('서버가 http://localhost:3000 에서 실행되고 있습니다.');
});

위의 예제에서 /hello 경로에 대한 GET 요청이 들어오면 "안녕하세요!"라는 메시지를 반환합니다. 또한 /submit 경로에 대한 POST 요청도 처리가 가능합니다.

3.3 컨트롤러란?

컨트롤러는 비즈니스 로직을 담당하며, 주어진 요청에 대해 적절한 응답을 생성하는 역할을 합니다. 이를 통해 코드의 재사용성을 높이고 유지보수를 쉽게 할 수 있습니다.

3.4 컨트롤러 사용 예제

먼저 controllers 폴더를 만들고 userController.js 파일을 생성하여 다음과 같이 작성합니다:

// controllers/userController.js

exports.getUser = (req, res) => {
    const userId = req.params.id;
    // 사용자 정보를 데이터베이스에서 조회하는 로직 추가
    res.send(`사용자 ID: ${userId}`);
};

exports.createUser = (req, res) => {
    // 사용자 생성 로직
    res.send('사용자 생성 완료');
};

그 후 메인 파일에서 이 컨트롤러를 사용할 수 있습니다:

const express = require('express');
const userController = require('./controllers/userController');

const app = express();

// 사용자 정보 조회 라우터 설정
app.get('/users/:id', userController.getUser);

// 사용자 생성 라우터 설정
app.post('/users', userController.createUser);

app.listen(3000, () => {
    console.log('서버가 http://localhost:3000 에서 실행되고 있습니다.');
});

위의 예시에서는 /users/:id 경로를 통해 특정 사용자의 ID를 받아오는 기능이 구현되었습니다. 이렇게 분리된 컨트롤러 덕분에 비즈니스 로직과 라우팅이 명확하게 구분되어 유지보수성이 향상됩니다.

3.5 미들웨어와 함께 사용하는 방법

Express.js에서는 미들웨어를 사용하여 각 요청 단계마다 특정 작업을 수행할 수 있습니다. 이러한 미들웨어는 인증 확인이나 데이터 파싱 같은 공통 작업들을 관리하는 데 유용합니다.

3.6 미들웨어 예제

// 인증 미들웨어 함수 정의
function authenticate(req, res, next) {
    const token = req.headers['authorization'];

    if (token === 'valid-token') {
        next(); // 다음 미들웨어 또는 핸들러 호출
    } else {
        res.status(403).send('접근 거부');
    }
}

// 보호된 리소스 접근 시 인증 미들웨어 적용
app.get('/protected', authenticate, (req, res) => {
   res.send('보호된 리소스에 접근했습니다.');
});

위의 코드에서는 /protected 경로에 접근하기 전에 authenticate 미들웨어가 호출되어 토큰 검증 과정을 수행합니다.

3.7 예제: 라우터 분리

routes 폴더를 만들고 userRoutes.js 파일을 생성하여 사용자 관련 라우트를 분리합니다.

// routes/userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');

router.get('/:id', userController.getUser);
router.post('/', userController.createUser);

module.exports = router;

app.js에서 사용자 라우트를 사용합니다.

const express = require('express');
const app = express();
const userRoutes = require('./routes/userRoutes');

// 사용자 라우트 사용
app.use('/users', userRoutes);

// ... 나머지 코드

3.8 예제: 쿼리 파라미터 처리

쿼리 파라미터를 처리하는 라우트를 추가합니다.

// controllers/userController.js 에 다음 함수를 추가합니다.
exports.searchUsers = (req, res) => {
  const query = req.query.q; // 예: /users/search?q=john
  // 쿼리 파라미터 q를 사용해 사용자 검색 로직을 구현
  res.send(`검색어: ${query}`);
};

// routes/userRoutes.js 에 다음 라우트를 추가합니다.
router.get('/search', userController.searchUsers);

3.9 예제: 동적 라우트 파라미터와 함께 미들웨어 사용

특정 사용자를 조회하기 전에 해당 사용자가 존재하는지 확인하는 미들웨어를 추가합니다.

// controllers/userController.js
exports.checkUserExists = (req, res, next) => {
  const userId = req.params.id;
  // 데이터베이스에서 사용자 존재 여부 확인 로직
  const userExists = true; // 예시로 true로 설정

  if (userExists) {
    next();
  } else {
    res.status(404).send('사용자를 찾을 수 없습니다.');
  }
};

// routes/userRoutes.js
router.get('/:id', userController.checkUserExists, userController.getUser);

3.10 예제: 여러 개의 라우트 파라미터 처리

여러 개의 라우트 파라미터를 처리하는 예제입니다.

// controllers/productController.js (새 파일 생성)
exports.getProduct = (req, res) => {
  const categoryId = req.params.categoryId;
  const productId = req.params.productId;
  // 카테고리와 제품 ID를 사용한 로직 구현
  res.send(`카테고리 ID: ${categoryId}, 제품 ID: ${productId}`);
};

// routes/productRoutes.js (새 파일 생성)
const express = require('express');
const router = express.Router();
const productController = require('../controllers/productController');

router.get('/:categoryId/:productId', productController.getProduct);

module.exports = router;

// app.js 에 제품 라우트 추가
const productRoutes = require('./routes/productRoutes');
app.use('/products', productRoutes);

결론

Express.js는 Node.js 환경에서 빠르고 효율적인 웹 애플리케이션 개발을 가능하게 해주는 강력한 도구입니다. 미들웨어, 라우팅, 컨트롤러 등의 개념을 이해하고 활용하면 더욱 견고하고 유지보수가 쉬운 애플리케이션을 개발할 수 있습니다. 이 글을 통해 Express.js의 기본 개념과 사용 방법을 익히고, 실제 프로젝트에 적용해 보시기 바랍니다.

728x90