개발자 도전기/[STUDY] JS || TS

ts-node | NodeBird | express 미들웨어

답수 2022. 4. 19. 22:38
728x90
반응형

 

 

※ 인프런 - Node.js에 TypeScript 적용하기(feat. NodeBire) by 조현영 강의를 기반으로 정리한 내용입니다.

 

모듈 설치

프로젝트에 필요한 모듈들을 한꺼번에 설치해보자.

npm i morgan cors cookie-parser express-session dotenv passport hpp helmet

 

문제는 대부분 모듈들이 타입을 지원하지 않기 때문에 타이핑을 따로 설치해야 함

npm i @types/morgan @types/cors @types/cookie-parser @types/express-session @types/dotenv @types/passport @types/hpp @types/helmet

 

아래 모듈들도 필요할 것 같아서? 추가로 설치

npm i passport-local bcrypt @types/passport-local @types/bcrypt

 

주의할 점은 @types 모듈과 버전이 다른 경우가 있는데, 이는 살짝 위험할 수 있다. 예를 들어 bcrypt가 4.0.1 버전이면 @types/bcrypt도 4버전이어야 하는데 3.0.0 이러면 문제가 될 수 있다. 이럴 때는 두 가지 해결 방법이 있다. 첫 번째는 bcrypt를 3버전으로 다운그레이드하는 방법, 다른 하나는 에러가 발생했을 때 내가 직접 타이핑을 입력하여 커스터마이징하여 사용하는 것

 

설치할 때 버전 체크 꼭 하자!!! 앞 버전(메이저 버전)만 맞아도 된다고 한다.

 

설치를 하는데, npm 경고문 두 개가 떴다.

npm WARN deprecated @types/dotenv@8.2.0: This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed.

npm WARN deprecated @types/helmet@4.0.0: This is a stub types definition. helmet provides its own type definitions, so you do not need this installed.

 

dotenv하고 helmet 모듈은 자체적인 타입 정의를 사용하니까 설치 필요 없다는 뜻. 바로 삭.제.

 

 

그럼 이제 index.ts에 다 불러오고, 미들웨어를 장착해보자.

import * as express from "express";
import * as morgan from "morgan";
import * as cors from "cors";
import * as cookieParser from "cookie-parser";
import * as expressSession from "express-session";
import * as dotenv from "dotenv";
import * as passport from "passport";
import * as hpp from "hpp";
import helmet from "helmet";

dotenv.config();
const app = express();
// 환경변수 설정
const prod: boolean = process.env.NODE_ENV === 'production'; // 배포용

app.set('port', prod ? process.env.PORT : 3065);    // 배포용이면 포트 자유자재로 바꿀 수 있도록, 개발용이면 3065로 고정

// 미들웨어 장착
if (prod) {
    app.use(hpp());
    app.use(helmet());
    app.use(morgan('combined'));
    app.use(cors({
        origin: /nodebird\.com$/,
        credentials: true
    }));
} else {
    app.use(morgan('dev'));
    app.use(cors({
        origin: true,
        credentials: true
    }));
}

app.use('/', express.static('uploads'));
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(expressSession({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET!,    // 타입스크립트에서는 dotenv 인식 못 함. ! 를 통해 에러 없앰
    cookie: {
        httpOnly: true,
        secure: false,  // https -> true
        domain: prod ? '.nodebird.com' : undefined
        // domain: prod && '.nodebird.com'  // domain은 string | undefined 타입 형식으로 에러남(js에서는 문제 없음)
    },
    name: 'rnbck'
}));
app.use(passport.initialize());
app.use(passport.session());

app.get('/', (req, res) => {
    res.send('nodebird 백엔드 정상 동작!');
});

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

 

.... 선생님.. 진도가 너무 빨라요..ㅜㅜㅠ,... 

저 모듈과 미들웨어에 대해서는 내가 하나씩 공부해나가자...!

 

 

미들웨어 보면, 배포용일 때와 개발용일 때 사용하는 미들웨어 설정이 다른 것을 볼 수 있다.

 

hpp

// npm 정의
Express middleware to protect against HTTP Parameter Pollution attacks.

hpp는 HTTP Parameter Pollution의 약자로, 익스프레스에 동일한 이름을 가진 파라미터들이 있으면 이를 배열로 만들어주어 의도치 않은 동작이 발생하는 것을 방지하는 미들웨어다.

 

helmet

// npm 정의
Helmet helps you secure your Express apps by setting various HTTP headers. It's not a silver bullet, but it can help!

helmet은 다양한 HTTP헤더를 설정하여 익스프레스를 보호하는 모듈이다. helmet에는 다양한 미들웨어들이 있는데, app.use(helmet()); 만 설정할 경우 기본적인 보안(X-Powered-By 등)만 설정된다고 한다. 

  • csp: Content-Security-Policy 헤더 설정. XSS(Cross-site scripting) 공격 및 기타 교차 사이트 인젝션 예방
  • hidePoweredBy: X-Powered-By 헤더 제거
  • hpkp: Public Key Pinning 헤더 추가. 위조된 인증서를 이용한 중간자 공격 방지
  • hsts: SSL/TLS를 통한 HTTP 연결을 적용하는 Strict-Transport-Security 헤더 설정
  • noCache : Cache-Control 및 Pragma 헤더를 설정하여 클라이언트 측에서 캐싱을 사용하지 않도록 함
  • frameguard : X-Frame-Options 헤더 설정하여 clickjacking에 대한 보호 제공
  • ieNoOpen : (IE8 이상) X-Download-Options 설정
  • xssFilter :  X-XSS-Protection 설정. 대부분의 최신 웹 브라우저에서 XSS(Cross-site scripting) 필터를 사용
  • noSniff : X-Content-Type-Options 설정하여, 선언된 콘텐츠 유형으로부터 벗어난 응답에 대한 브라우저의 MIME 가로채기를 방지

* ref: https://7stocks.tistory.com/94

 

※ x-powered-by ?

더보기

x-powered-by는 서버가 어떠한 기술로 개발되었는지를 보여주는 속성으로 response 헤더에 담겨 있다. 특정 기술과 버전을 조작할 수 있는 위험성을 없애기 위해 보안 처리가 필요하다.

ref: https://stackoverflow.com/questions/33580671/what-does-x-powered-by-mean

 

morgan

// npm 정의
HTTP request logger middleware for node.js

morgan은 노드 서버 환경에서 log를 관리하기 위해 사용되는 모듈이다. morgan은 로그 관리를 쉽게 할 수 있도록 하며, 커스텀하기 위한 목적으로도 사용된다. 미리 정의된 형식으로는 combined, common, dev, short, tiny 등이 있고, 각 인자별로 출력되는 로그가 다르다고 한다. 보통 개발시에는 dev나 short을 이용하고 배포용으로는 combined나 common을 추천한다고 하는데, 이는 프로젝트를 진행하면서 각 인자마다 결과물이 어떻게 다른지 직접 테스트해보면서 차이점을 알아볼 것이다.

 

cors

// npm 정의
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.

CORS는 Cross Origin Resource Sharing의 약자로 클라이언트가 도메인 및 포트가 다른 서버로 요청했을 때 브라우저가 보안 목적으로 API를 제한하는 미들웨어다. 다만 cors()는 모든 요청 오리진을 허용하는 것이기 때문에 위의 배포용 코드에서 처럼 origin: /nodebird\.com$/, 속성을 넣어서 일부 허용할 주소를 넣는게 더 안전하다.

credentials 옵션은 true일 떄 다른 도메인간 쿠키 공유를 허락하도록 하며, 기본 값은 false다. 그렇기 때문에 true로 설정하지 않으면 로그인 같은 사용자 인증이 필요한 리소스에 접근할 수 없게 제한된다.

 

express.urlencoded()

이 메소드는 익스프레스에 내장된 미들웨어로, express.json은 json데이터를 파싱하는 것과 다르게 urlencoded데이터의 요청을 파싱한다. json과 마찬가지로 body-parser 기반이다. (참고로 이 미들웨어는 익스트레스 4.16 버전 이상부터 사용 가능하다고 한다)

 

본 코드에서 쓰인 extended: true 옵션은 url로 인코딩된 데잍너를 qs라이브러리로 파싱한다는 뜻이라고 한다. 설정이 false일 때는 querystring 라이브러리가 사용된다고 한다. 

 

cookie-parser

// npm 정의
Parse Cookie header and populate req.cookies with an object keyed by the cookie names. Optionally you may enable signed cookie support by passing a secret string, which assigns req.secret so it may be used by other middleware.

헤더에 담겨 있는 쿠키 데이터를 파싱하고 쿠키 이름으로 지정된 개체로 req.cookies를 채우는 기능을 하는 미들웨어다(키-밸류의 데이터). 나중에 테스트해볼 때 개발자도구에 들어가서 쿠키가 어떻게 되어 있는지 확인해보자.

 

express-session

이 모듈은 단어 그대로 익스프레스에서 세션을 사용할 수 있도록 하는 모듈이다. 

  • resave: 요청이 있을 때마다 변경 사항이 없을 시에도 세션을 다시 저장하는 옵션이다. 즉 매 request마다 세션을 계속 다시 저장한다. 디폴트는 true이고, 우리는 false로 설정했다.
  • saveUninitalized: uninitialized 상태의 세션을 강제로 저장하는 옵션이다. 즉 request에서 새로 생성된 세션에 초기화되지 않은 아무 작업이 이루어지지 않은 세션도 저장한다는 의미로, 역시 false로 설정했다.
  • secret: 세션은 session ID를 쿠키에 담아 보내줘야 클라이언트를 식별할 수 있다. 그래서 세션아이디는 쿠키에 넣고 해시값으로 암호화를 해서 보내게 되는데, 이때 암호화하는데 쓰이는 키가 이 옵션이다.
  • cookie: 클라이언트에 쿠키를 보낼 때 들어있는 데이터들이다. 역시 키-밸류로 이루어진 객체 되어 있다.

 

 

한 번 서버를 실행시켜보면 다음과 같은 로그가 뜬다.

현재 개발자모드여서 dev 로그가 뜨는 듯

 

 

 

 

728x90
반응형
LIST