Express.js 공식 문서 번역(Advanced topics)

최기환·2023년 4월 8일
0

Express를 위한 엔진 템플릿 개발

app.engine(ext, callback)을 통해 나만의 템플릿 엔진을 만들 수 있다. ext는 파일 확장자명을 의미하며 callback은 다음과 같은 매개변수를 받는 템플릿 엔진 함수를 의미한다: 파일의 위치, 옵션 객체, 콜백 함수.

다음은 .ntl파일을 랜더링하기위한 아주 간단한 템플릿 엔진 예제이다.

const fs = require('fs'); // 이 엔진은 fs 모듈을 필요로 한다.
app.engine('ntl', (filePath, options, callback) => { // 템플릿 엔진 정의
  fs.readFile(filePath, (err, content) => {
    if (err) return callback(err);
    // 이것은 아주 간단한 템플릿 엔진이다.
    const rendered = content.toString();
    .replace('#title#', `<title>${options.title}</title>`);
    .replace('#message#', `<h1>${options.message}</h1>`);
    return callback(null, rendered);
  });
});
app.set('views', './views'); // views 디렉토리 지정
app.set('view engine', 'ntl'); // 템플릿 엔진 등록

이제 앱은 .ntl 파일들을 보여줄 수 있을 것이다.
다음과 같은 index.ntl파일을 만든다.

#title#
#message#

그리고 앱에 다음과 같은 라우트를 추가한다.

app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello thre!' });
});

page에 요청을 보내면, index.ntl은 HTML로서 보여질 것이다.

Express 앱 프로세스 관리

Express를 배포한 후 실행할 때 process manager는 다음과 같이 사용하면 도움이 될 것이다:

  • 어떤 충돌이 발생했을 때 자동적으로 앱을 재시작한다.
  • 런타임 퍼포먼스에 대한 인사이트를 얻고 리소스 소비에 대한 정보를 얻을 수 있다.
  • 퍼포먼스를 수정하기위해 동적으로 설정을 수정한다.
  • 클러스터링을 제어한다.

    클러스터링이란
    Express 애플리케이션을 여러 개의 프로세스로 분할하여 CPU 및 시스템 리소스를 더 효율적으로 활용하게 해주는 기술.

process manager는 애플리케이션 서버와 비슷한것이다: 배포를 용이하게 하는 애플리케이션을 위한 컨테이너다. 높은 사용성을 제공하고 애플리케이션을 런타임에 관리할 수 있도록 해준다.

가장 유명한 process manager는 다음과 같은 것들이 있다:

  • Forever
  • PM2
  • StrongLoop Process Manager
  • SystemD

Production Best Practices: Security

Overview

production은 달리 실제 사용자들에게 제공되고 서비스되는 단계를 의미한다. 이와 달리 development는 아직 코드를 쓰고 테스트 중인 단계를 의미하며 애플리케이션은 외부로부터의 접근을 막는다.

개발환경과 운영 환경은 다르게 설정된다. 예를들어, 개발환경에서는 다양한 로그를 띄울 수 있지만 운영 환경에서는 중요한 보안 문제가 될 수 있다.

Security best practices 는 다음을 포함한다:

  • deprecated된 버전을 쓰지 말자
  • TLS를 사용해라
  • Helmet을 사용해라
  • 쿠키를 안전하게 사용해라
    = 권환 확인 에대한 브루트 포스 공격을 예방해라
  • 너의 dependencies가 안전한것을 확실히 해라
  • 다른 알려진 취약점들을 피해라
  • 다른 고려해야할 점

사장되거나 취약한 버전의 Express를 쓰지마라.

2.X, 3.X버전은 더이상 유지보수되지 않는다. 보안이나 성능 관련 이슈는 이 버전들에서 고쳐지지 않는다.

TLS를 사용해라

니가 만약 민감한 데이터를 다루고 있다면 Transport Layer Security(TLS)를 사용해라. 이 기술은 데이터가 클라이언트에서 서버로 보내지기 전에 암호화 한다. 그러므로 평범한 해킹을 예방하게 해준다. Ajax 와 POST 요청이 보이지 않게 숨겨져 있을 지라도 네트워크 트래픽은 다양한 공격에 취약하다.

Secure Socket Layer(SSL)과는 친숙할수도 있다. TLS는 간단하게 SSL의 보완이다. 즉, SSL을 사용하고 있따면 TLS로 업그레이드 하는것을 고려해라.

Helmet을 사용해라

Helmet은 HTTP 헤더를 적절하게 설정함으로써 잘 알려진 웹 취얌점으로부터 보호해준다. Helmet은 보안과 관련된 HTTP 응답 헤더를 설정하는 미들웨어 함수들의 모음이다. 다음은 몇가지 예제이다.

  • helmet.contentSecurityPolicy 는 헤더를 Content-Security-Policy헤더로 설정한다. 이것은 크로스 사이트 스크립팅 공격으로부터 보호해준다.

  • helmet.hstsStrict-Transport-Security헤더로 설정해준다. 이것은 서버로의 연결이 HTTPS 연결이 되도록 한다.

  • helmet.frameguardX-Frame-Options로 헤더를 설정해준다.

Helmet는 다른 모듈처럼 설치할 수 있다:

npm install --save helmet

그리고 코드에서 사용하면 된다

//...
const helmet = require('helmet');
app.use(helmet());
//...

Use cookies securely

쿠키가 앱을 부당한 용도로 사용할 수 없도록 해야한다. 디폴트 세션 쿠키 이름을 사용하지 말고 쿠키 보안 설정을 적절하게 설정해라.

두가이 쿠키 세션 모듈이 있다:

  • express-session
  • cookie-session

두 모듈의 차이점은 쿠키 세션 데이터를 저장하는 방법이다. express-session미들웨어는 서버에 데이터를 저장한다; 세션 ID만 저장하고 쿠키 그자체는 저장하지 않는다. 기본 설정으로 메모리 저장소를 사용하고 운영 환경을 위해 만들어지진 않았다. 운영환경에서는 규모있는 세선 저장소를 설정해야한다.

반대로 cookie-session미들웨어는 쿠키 기반 저장을 구현한다: 세션 키 뿐만 아니라 전체 세션을 쿠키에 직렬화한다. 쿠키 데이터가 상대적으로 작고 복호화 하기 쉬운 값을 가진 경우에만 사용해라.

기본으로 설정된 세션 쿠키 이름을 사용하지 마라.

generic cookie name을 사용해라. 예제:

const session = require('express-session');
app.set('trust proxy', 1) // trust first proxy
app.use(session({
  secret: 's3Cur3',
  name: 'sessionId'
}));

쿠키 보안 설정을 해라

  • secure: 브라우저가 HTTPS로 쿠키를 보내도록 한다.
  • httpOnly: HTTP(S)를 통해서만 쿠키를 보내도록 한다.
  • domain: 쿠키의 도메인을 나타낸다. 어떤 URL에서 요청이 왔는지 서버의 도메인과 비교하기위해 사용된다.
  • path: 쿠키의 경로를 나타낸다; 요청 경로와 비교하기 위해 사용된다.
  • expires: 언제 만료될지를 정하는데 사용된다.

예제

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

const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1hour
app.use(session({
  name: 'session',
  keys: ['key1', 'key2'],
  cookie: {
    secure: true,
    httpOnly: true,
    domain: 'example.com',
    path: 'foo/bar',
    expires: expiryDate
  }
}));

브루트 포스 권한 요청 공격을 예방해라

login endpoints가 더 안전하도록 해라.
다음과 같은 간단하고 효과적인 방법이 있다:
1. 로그인 실패 횟수를 통해 확인한다.
2. 긴 기간동안 실패된 로그인 횟수를 통해 확인한다.

추가적인 고려할점

https://blog.risingstack.com/node-js-security-checklist/
이 블로그에서 확인해라

profile
프론트엔드 개발자를 꿈꾸는 취준생(백수) 입니다!

0개의 댓글