Express 개발 강좌, 보안 고려사항 및 CORS 정책

작성자: 조광형

작성일: 2024년 11월 26일

1. 서론

Express는 Node.js를 기반으로 한 경량 웹 프레임워크로, 백엔드 서버 개발에 널리 사용됩니다. 그러나, 웹 애플리케이션을 개발할 때 보안은 가장 중요한 고려사항 중 하나입니다. 이 강좌에서는 Express 애플리케이션에 대한 보안 고려사항과 CORS(교차 출처 리소스 공유) 정책에 대해 자세히 알아보겠습니다.

2. Express의 보안 고려사항

애플리케이션의 보안을 강화하기 위해 다음과 같은 방법들을 적용할 수 있습니다.

2.1. HTTPS 사용

HTTP 대신 HTTPS를 사용함으로써, 데이터 전송 시 암호화를 통해 정보의 유출과 중간자 공격을 방지할 수 있습니다. Express 애플리케이션에서 HTTPS를 설정하는 방법은 다음과 같습니다.


const express = require('express');
const https = require('https');
const fs = require('fs');

const app = express();
const PORT = 3000;

// SSL 인증서 경로 설정
const options = {
    key: fs.readFileSync('/path/to/private-key.pem'),
    cert: fs.readFileSync('/path/to/certificate.pem')
};

// HTTPS 서버 생성
https.createServer(options, app).listen(PORT, () => {
    console.log(`HTTPS 서버가 포트 ${PORT}에서 실행 중입니다.`);
});
            

2.2. Helmet 미들웨어 사용

Helmet은 Express 애플리케이션의 보안을 높이기 위해 HTTP 헤더를 설정하는 미들웨어입니다. 다음과 같이 쉽게 적용할 수 있습니다.


const helmet = require('helmet');

app.use(helmet());
            

2.3. 데이터 검증 및 인가

서버에서 사용하는 입력 데이터에 대해 철저한 검증 및 인가 절차를 구현해야 합니다. 예를 들어, 사용자가 입력한 데이터에 대해 xss 필터링, SQL 인젝션 방지를 위한 Prepared Statement 등을 사용할 수 있습니다.


const { body, validationResult } = require('express-validator');

app.post('/user', [
    body('email').isEmail(),
    body('password').isLength({ min: 5 })
], (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(400).json({ errors: errors.array() });
    }

    // 유저 생성 로직
});
            

2.4. 비밀번호 해시화

사용자 비밀번호는 평문으로 저장하지 않고 해시 처리하여 저장해야 합니다. bcrypt와 같은 라이브러리를 사용할 수 있습니다.


const bcrypt = require('bcrypt');

const saltRounds = 10;
const myPlaintextPassword = 's0/\/\P4$$w0rD';

bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
    // 해시된 비밀번호 데이터베이스에 저장
});
            

2.5. 에러 핸들링

에러 핸들링을 통해 사용자에게 불필요한 정보가 노출되는 것을 방지할 수 있습니다. 적절한 에러 메시지를 정의하고 로그를 관리하여 보안성을 높이는 것이 좋습니다.


app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('무언가 잘못되었습니다!');
});
            

3. CORS 정책

CORS는 “Cross-Origin Resource Sharing”의 약자로, 웹 페이지가 다른 출처의 리소스에 접근할 수 있도록 해주는 메커니즘입니다. CORS 정책을 이해하고 설정하는 것은 보안과 애플리케이션의 정상 작동에 필수적입니다.

3.1. CORS의 필요성

모던 웹 애플리케이션은 종종 다양한 출처의 API와 상호작용합니다. 이때, 브라우저는 보안 상의 이유로 교차 출처 요청을 제한합니다. CORS는 이 제한을 설정하고 관리할 수 있는 방법을 제공합니다.

3.2. CORS를 설정하는 방법

Express에서 CORS를 설정할 때는 ‘cors’ 미들웨어를 사용할 수 있습니다. 설치 후 아래와 같이 설정할 수 있습니다.


const cors = require('cors');

// CORS 미들웨어 사용
app.use(cors({
    origin: 'https://example.com', // 허용할 출처
    methods: ['GET', 'POST'], // 허용할 HTTP 메서드
    allowedHeaders: ['Content-Type', 'Authorization'] // 허용할 헤더
}));
            

3.3. 특정 경로에 대한 CORS 설정

특정 경로에만 CORS를 적용하고 싶은 경우, 옵션을 지정하여 개별적으로 설정할 수 있습니다.


app.get('/api/data', cors(), (req, res) => {
    res.json({ data: '데이터입니다.' });
});
            

4. CORS 관련 보안 고려사항

CORS를 설정할 때 주의해야 할 점은 허용할 출처를 정확히 지정하는 것입니다. ‘*’와 같은 와일드카드를 사용하면 모든 도메인에서 요청할 수 있게 되므로, 필요한 경우에만 사용해야 합니다.

4.1. 요청 헤더와 메서드 제한

CORS 설정 시, 허용할 요청 헤더와 HTTP 메서드를 철저히 관리하여 보안을 강화할 수 있습니다.

4.2. Credential 지원

인증 정보를 포함한 요청을 처리해야 할 경우, ‘Access-Control-Allow-Credentials’ 헤더를 true로 설정할 수 있습니다. 다만, 요청의 출처를 제한해야 합니다.


app.use(cors({
    origin: 'https://example.com',
    credentials: true
}));
            

5. 결론

Express에서의 보안 고려사항 및 CORS 정책은 웹 애플리케이션의 안전성과 성능에 큰 영향을 미칩니다. HTTPS, Helmet, 데이터 검증, 비밀번호 해시화 등의 방법을 통해 보안을 강화하고, CORS를 적절히 설정하여 다양한 출처와 안전하게 상호작용할 수 있습니다.

앞으로의 웹 애플리케이션 개발에서도 보안을 항상 염두에 두고, 정기적으로 보안 상태를 점검하는 것이 중요합니다.

이 게시물이 유용하셨다면, 공유해 주시기 바랍니다!