JWT ( Json Web Token )은 웹 표준으로 서버와 클라이언트 사이에서 정보를 안전하게 전송하기 위해 도움을 주는 웹 토큰 ( Web Token )이다.

  • JSON 형태의 데이터를 안전하게 전송하고 검증할 수 있는 기능을 제공한다.
  • 인터넷 표준으로 자리잡은 규칙이다.
  • 다양한 암호화 알고리즘을 사용할 수 있어, 신뢰성을 보장한다.
  • header.payload.signature의 형식으로 3가지의 데이터를 포함한다.

 

JWT 형태

jwt - Header, Payload, Signature

 

JWT는 앞서 언급했듯이, 크게 세 부분, 헤더 ( Header ), 페이로드 ( Payload ), 서명 ( Signature )로 구성되어 있다.

각각의 부분은 점 ( . ) 으로 분리된다.

 

JWT의 구조는 https://jwt.io/ 에서 확인할 수 있다.

  • Header : 헤더는 토큰의 타입과 어떤 암호화를 사용해 생성된 데이터인지 정듸외어 있다.
{
  "alg": "HS256",
  "typ": "JWT"
}
  • Payload : 페이로드는 실제 전달하려는 데이터를 담고 있다. 대표적으로 개발자가 원하는 데이터를 저장한다.
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
  • Signature : 서명은 헤더와 페이로드, 그리고 비밀 키 ( Secret Key )를 이용해 생성된다. 이 서명은 토큰이 변조되지 않은 정상적인 토큰인지 확인할 수 있게 도와준다.
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
	secret
)

 

각 부분은 Base64로 인코딩해, 점 ( . ) 으로 연결하면 최종적으로 JWT를 생성하게 된다. 이렇게 생성된 JWT는 이전에 배운 쿠키 ( Cookie ) 또는 Path Parameter를 통해 전달될 수 있다.

 

JWT 특성

 1. JWT는 비밀 키를 모르더라도 복호화 ( Decode )가 가능하다.

  • JWT를 가진 사람이라면 누구나 해당 토큰에 어떤 데이터가 담겨있는지 확인할 수 있다.
  • 변조만 불가능 할 뿐, 누구나 복호화해 보는 것은 가능하다는 의미가 된다.

 2. 민감한 정보 ( 개인정보, 비밀번호 등 )는 담지 않도록 해야한다.

  • JWT의 페이로드는 누구나 복호화해 볼 수 있기 때문이다

 3. JavaScript와 같이 특정 언어에서만 사용 가능한것은 아니다

  • JWT는 단순히 데이터 형식일 뿐, 단지 개념으로 존재하고, 이 개념을 코드로 구현해 공개된 코드를 우리가 사용하는게 일반적이다.

쿠키, 세션과 다른점 

데이터를 교환하고 관리하는 방식인 쿠키 / 세션과 달리, JWT는 단순히 데이터를 표현하는 형식이다.

  • JWT로 만든 데이터는 변조가 어렵고, 서버에 별도의 상태 정보를 저장하지 않기 때문에, 서버를 Stateless ( 무상태 )로 관리할 수 있다.
  • 쿠키와 세션은 사용자의 로그인 정보나 세션 데이터를 서버에 저장하므로 상태를 유지한다. 따라서 Stateful ( 상태 보존 )하게 데이터가 관리된다.

 

'IT' 카테고리의 다른 글

[IT] Access Token, Refresh Token  (1) 2024.09.09
[IT] 인증, 인가  (0) 2024.09.09
[IT] 쿠키와 세션  (0) 2024.09.08
[AWS] RDS 구매하고 사용하기  (0) 2024.09.05
[IT] Javascript - Package Manager ( npm, yarn )  (0) 2024.08.28

쿠키

브라우저가 서버로부터 응답으로 Set-Cookie 헤더를 받은 경우 해당 데이터를 저장한 뒤 모든 요청에 포함하여 보낸다.

  • 쿠키는 사용자가 naver.com과 같은 웹 사이트를 방문할 때마다 이전에 방문했던 정보를 기억하는 데이터 파일이다.
  • 데이터를 여러 사이트에 공유할 수 있기 때문에 보안에 취약할 수 있다.
  • 쿠키는 userId=user-1321;userName=sparta 와 같이 문자열 형식으로 존재하며 쿠키간에는 세미콜론 (;) 으로 구분한다.

세션

쿠키를 기반으로 구성된 기술이다. 단, 클라이언트가 마음대로 데이터를 확인 할 수 있던 쿠키와는 다르게 세션은 데이터를 서버에만 저장한다.

  • 세션은 일반적으로 세션 Id를 쿠키를 이용해 클라이언트에게 전달해, 서버는 이 세션 Id를 사용해 저장된 세션 데이터를 조회한다.
  • 세션을 통해 사용자의 상태 정보를 서버에 저장하면, 서버는 사용자의 상태를 추적 할 수 있게 된다.
  • 보안성은 좋으나, 반대로 사용자가 많은 경우 서버에 저장해야 할 데이터가 많아져서 서버 컴퓨터가 감당하지 못하는 문제가 생기기 쉽다.
  • 쿠키와 마찬가지로 세션 역시 만료 기간이 있다.

 

쿠키 ( Cookie ) 만들어보기

쿠키의 동작 방식

 

서버가 클라이언트의 HTTP 요청 ( Request )을 수신할 때, 서버는 응답 ( Response )과 함께 Set-Cookie 라는 헤더를 함께 전송할 수 있다. 그 후 쿠키는 해당 서버에 의해 만들어진 응답 ( Response )과 함께 Cookie HTTP 헤더안에 포함되어 전달받는다.

 

쿠키를 할당하는 API를 만들어보자

// app.js

import express from 'express';

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

app.use(express.json());

app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

 

Set-Cookie 를 이용해 쿠키 할당하기

// 'Set-Cookie'를 이용하여 쿠키를 할당하는 API
app.get("/set-cookie", (req, res) => {
  let expire = new Date();
  expire.setMinutes(expire.getMinutes() + 60); // 만료 시간을 60분으로 설정합니다.

  res.writeHead(200, {
    'Set-Cookie': `name=sparta; Expires=${expire.toGMTString()}; HttpOnly; Path=/`,
  });
  return res.end();
});

 

res.cookie() 를 이용해 쿠키 할당하기

// 'res.cookie()'를 이용하여 쿠키를 할당하는 API
app.get("/set-cookie", (req, res) => {
  let expires = new Date();
  expires.setMinutes(expires.getMinutes() + 60); // 만료 시간을 60분으로 설정합니다.

  res.cookie('name', 'sparta', {
    expires: expires
  });
  return res.end();
});

 

name이란 이름으로, sparta 데이터를 가진 쿠키 모습

 

req를 이용해 쿠키 접근하기

클라이언트는 서버에 요청 ( Request )을 보낼 때 자신이 보하고 있는 쿠키를 자동으로 서버에 전달하게 된다.

여기서 클라이언가 전달하는 쿠키 정보는 Request header에 포함되어 서버에 전달되게 된다.

 

서버에서 어떤 방식으로 쿠키를 사용할까?

일반적으로 쿠키는 req.headers.cookie에 들어있다. req.headers는 클라이언트가 요청한 Request의 헤더 ( header )를 의미한다.

Request의 헤더

  • 헤더는 요청을 보낸 클라이언트에 관한 상세한 정보를 담고 있다.
  • 이 정보에는 사용자의 브라우저 유형, 운영 체제, 데스크탑이나 모바일의 사용 유무 등이 포함된다.
  • 깨알 같이, 쿠키 정보 또한 이 헤더 안에 포함되어 있는것을 확인할 수 있다.

 

/get-cookie에 접근했을 때, 클라이언트가 전달한 모든 쿠키를 출력하는 API를 만들어보자

// 'req.headers.cookie'를 이용하여 클라이언트의 모든 쿠키를 조회하는 API
app.get('/get-cookie', (req, res) => {
  const cookie = req.headers.cookie;
  console.log(cookie); // name=sparta
  return res.status(200).json({ cookie });
});

 

쿠키 정보 출력된 모습

 

cookie-parser 미들웨어 적용하기

요청에 추가된 쿠키를 req.cookies 객체로 만들어 더이상 req.headers.cookie와 같이 번거롭게 사용할 필요 없어진다.

이전에는 req.headers.cookie 와 같이 여러 프로퍼티를 넘어서야 쿠키를 사용할 수 있었으나 cookie-parser 미들웨어를 이용하면 더욱 간편하게 쿠키를 관리할 수 있다.

 

cookie-parser 설치

# yarn을 이용해 cookie-parser를 설치합니다.
yarn add cookie-parser

 

cookie-parser 미들웨어를 전역으로 사용하려면 다음과 같이 사용한다.

app.use(cookieParser());

 

cookie-parser 등록하기

import cookieParser from 'cookie-parser';

app.use(cookieParser());

// 'req.cookies'를 이용하여 클라이언트의 모든 쿠키를 조회하는 API
app.get('/get-cookie', (req, res) => {
  const cookies = req.cookies;
  console.log(cookies);
  return res.status(200).json({ cookie: cookies });
});

 

쿠키 조회 부분을 req.cookies로 변경했고, 쿠키의 형태가 name=sparta에서 { name: 'sparta' } 형태의 객체로 변환된 것을 확인 할 수 있다. 

 

cookie-parser를 통해 클라가 가지고 있는 쿠키 정보를 객체 형식으로 조회결과

 

cookie-parser 쿠키 정보 : https://www.npmjs.com/package/cookie-parser

 

cookie-parser

Parse HTTP request cookies. Latest version: 1.4.6, last published: 3 years ago. Start using cookie-parser in your project by running `npm i cookie-parser`. There are 9001 other projects in the npm registry using cookie-parser.

www.npmjs.com

 

세션 ( Session ) 만들어보기

Cookie-Session 흐름

 

쿠키의 경우 서버를 재시작하거나 새로고침을 하더라도 로그인이 유지된다. 이는 사용자에게는 편리하나, 서버의 입장에서는 보안 문제가 발생할 수 있다. 쿠키가 조작되거나 노출된다면 해당 권한을 탈튀당해, 악의적인 공격을 받을 수 있게 되는 것이다.

그렇다면, 쿠키에는 어떤 정보를 담아야 할까?

사용자가 누구인지 확실하게 구분할 수 있는 정보를 넣어줘야 한다.

 

먼저 /set-session API를 호출했을 때 name=sparta 의 정보를 서버에 저장하고, 저장한 시간 정보를 쿠키로 반환 받는 API와 /get-session API를 호출했을 때 쿠키의 시간 정보를 이용해 서버에 저장된 name 정보를 출력하는 API를 만들어보자.

 

/set-session API 만들기

let session = {};
app.get('/set-session', function (req, res, next) {
  // 현재는 sparta라는 이름으로 저장하지만, 나중에는 복잡한 사용자의 정보로 변경될 수 있습니다.
  const name = 'sparta';
  const uniqueInt = Date.now();
  // 세션에 사용자의 시간 정보 저장
  session[uniqueInt] = { name };

  res.cookie('sessionKey', uniqueInt);
  return res.status(200).end();
});
  • 서버에서 해당 사용자의 정보를 저장하기 위해 session 객체를 생성한다.
  • /set-session API가 호출되면 name=sparta의 정보를 세션에 삽입하고, 해당하는 데이터를 검색하기 위한 시간 정보를 쿠키로 반환한다.

 

/get-session API 만들기

app.get('/get-session', function (req, res, next) {
  const { sessionKey } = req.cookies;
  // 클라이언트의 쿠키에 저장된 세션키로 서버의 세션 정보를 조회합니다.
  const name = session[sessionKey];
  return res.status(200).json({ name });
});
  • 쿠키에 저장된 sessionKey를 이용해 session에 저장된 데이터를 불러온다.

세션 API 전체 코드, app.js

import express from 'express';
import cookieParser from 'cookie-parser';

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

app.use(express.json());
app.use(cookieParser());

// 'req.cookies'를 이용하여 클라이언트의 모든 쿠키를 조회하는 API
app.get('/get-cookie', (req, res) => {
  const cookies = req.cookies;
  console.log(cookies);
  return res.status(200).json({ cookie: cookies });
});

let session = {};
app.get('/set-session', function (req, res, next) {
  // 현재는 sparta라는 이름으로 저장하지만, 나중에는 복잡한 사용자의 정보로 변경될 수 있습니다.
  const name = 'sparta';
  const uniqueInt = Date.now();
  // 세션에 사용자의 시간 정보 저장
  session[uniqueInt] = { name };

  res.cookie('sessionKey', uniqueInt);
  return res.status(200).end();
});

app.get('/get-session', function (req, res, next) {
  const { sessionKey } = req.cookies;
  // 클라이언트의 쿠키에 저장된 세션키로 서버의 세션 정보를 조회합니다.
  const name = session[sessionKey];
  return res.status(200).json({ name });
});

app.listen(PORT, () => {
  console.log(PORT, '포트로 서버가 열렸어요!');
});

 

'IT' 카테고리의 다른 글

[IT] Access Token, Refresh Token  (1) 2024.09.09
[IT] 인증, 인가  (0) 2024.09.09
[IT] JWT  (0) 2024.09.08
[AWS] RDS 구매하고 사용하기  (0) 2024.09.05
[IT] Javascript - Package Manager ( npm, yarn )  (0) 2024.08.28

RDS는 AWS에서 제공하는 관계형 데이터베이스 서비스다.

RDS는 서버 운영, 유지 보수, 백업과 같이 데이터베이스 관련 작업을 AWS에게 위임해서, 백엔드 개발자가 데이터베이스를 사용하는 것에 집중할 수 있게 해준다.

 

RDS 구매

https://ap-northeast-2.console.aws.amazon.com/console/home?region=ap-northeast-2#

 

  • 위 링크로 접속해 로그인한다.

 

  • RDS를 검색한 후 클릭한다.

 

  • 데이터베이스 생성을 누른다

 

  • 표준 생성과 MySQL을 클릭한다.

 

  • 템플릿을 프리티어를 선택한다. ( AWS 가입 후 1년 동안 특정 서비스( = 프리 티어 )를 무료로 사용할 수 있다.

 

  • 설정 창에 데이터를 입력한다.
  • DB 인스턴스 식별자, 마스터 사용자 이름, 암호, 암호 확인

 

  • 인스턴스 구성과 스토리지 설정은 그대로 두고 넘어간다.

 

연결 설정은 다음과 같이 설정한다.

  • 컴퓨팅 리소스 : "EC2 컴퓨팅 리소스에 연결 안함" 선택
  • 퍼블릭 액세스 기능 : "예" 선택 ( 이 설정이 되어있어야 우리 컴퓨터에서 AWS RDS의 MySQL과 연결이 가능하다. )
  • VPC 보안 그룹 : "새로 생성" 선택 ( 새 VPC 보안 그룹 이름 : express-database-sg )
  • 가용 영역 : 옵션 중 아무거나 선택해도 됨

 

  • '추가 구성' > '초기 데이터베이스 이름'에 "express_db"를 입력한다.

 

  • 데이터베이스 생성 버튼 클릭해서 생성한다.


 

RDS 포트 열기

  • express-database를 클릭한다.

 

  • 연결 & 보안 > 보안 > VPC 보안 그룹 에서 express-database-sg를 찾아 클릭한다.

 

  • 보안그룹 ID를 클릭한다.

 

  • 인바운크 규칙 편집을 클릭한다.

 

인바운드 규칙을 다음과 같이 설정한다.

 1) "규칙 추가"를 클릭하고, 유형에서 사용자 지정 TCP를 선택한다.   

  • RDS의 특정 TCP 포트를 열도록 설정한다.

 2) 포트 범위에 3306을 입력한다.

  • MySQL을 3306 Port를 기본으로 사용하므로, 해당 Port를 열어준다.

  3) 소스에서 Anywhere-IPv4를 선택한다.

  • 모든 IP 주소에서 전달되는 트래픽을 허용한다는 의미
  • 실제 서비스 환경에서는 이 설정이 보안 위험을 초래할 수 있음

위와 같이 설정하고 "규칙 저장" 버튼을 클릭한다.

'IT' 카테고리의 다른 글

[IT] Access Token, Refresh Token  (1) 2024.09.09
[IT] 인증, 인가  (0) 2024.09.09
[IT] JWT  (0) 2024.09.08
[IT] 쿠키와 세션  (0) 2024.09.08
[IT] Javascript - Package Manager ( npm, yarn )  (0) 2024.08.28

패키지 ( Package )

Node.js에서 코드의 재사용성을 높이기 위해 작성된 독립적인 코드 조각을 '모듈'이라고 부르고,

이러한 모듈을 npm이나 yarn과 같은 패키지 매니저를 통해 업도르하여 다른 개발자들과 공유할 때,

이를 패키지라고 한다.

 

 - 모듈은 일반적으로 프로젝트 내에서 사용되는 코드 조각을 의미하며, 패키지는 이러한 모듈을 포함하고 있거나

   다른 패키지에 의존하고 있는 코드의 집합을 의미한다.

 - 패키지는 다른 패키지를 사용할 수 있다. 이런 관계를 의존 관계라고 부른다.

 

패키지 매니저 ( Package Manager )

패키지 매니저 ( 출처 : https://devopedia.org/package-manager )

  • 패키지 매니저는 패키지를 손쉽게 다루는 작업을 안전하고 편리하게 사용하기 위한 툴이다.
  • Node.js 패키지의 설치, 업데이트, 삭제 등을 할 수 있고, 패키지간의 의존성을 관리해준다.
  • Node.js에서 대표적으로 사용하는 패키지 매니저는 npm과 yarn이 존재한다.

 

NPM ( Node Package Manager )

  • npm은 자바스크립트에서 사용할 수 있는 패키지(모듈) 관리자다.
  • Node.js와 관계없이 프론트엔드에서만 사용 가능한 Javascript Package들도 등록되어 있다

 

yarn

  • npm의 대체제로 Facebook이 2016년에 출시한 패키지 매니저로, npm의 대체제로서 등장했다.
  • npm의 부족한 부분을 보완하고 보안 성능이 향상된 패키지 매니저다.
  • yarn은 패키지를 다운로드 하는 과정에서 해당하는 패키지의 보안 검사를 수행한다. 패키지 내부에 위험한 스크립트가 다운로드 되거나, 종속성 문제가 발생하는 것을 방지할 수 있다.
  • yarn은 병렬 처리를 도입해서, 패키지 설치 속도가 npm보다 빠르다는 장점이 있다.

 

package.json

package.json

  • package.json은 Node.js 프로젝트의 가장 핵심적인 파일로 프로젝트에 대한 정보와 설치한 패키지들의 버전을 관리할 때 사용하는 파일이다.
  • package.json 파일에는 프로젝트명, 작성자, 라이센스 정보 등 일반적인 프로젝트의 메타 데이터 뿐만 아니라, 스크립트를 실행할 수 있는 필드도 포함되어 있다.
  • npm과 yarn 모두 동일한 package.json 파일을 참조한다.

 

package-lock.json과 yarn.lock

  • package-lock.json 또는 yarn.lock 파일은 package.json에서 정의한 패키지 외에도 node_modules에 들어있는 패키지들의 버전과 의존 관계가 상사하게 정의되어 있다.
  • 만약, node_modules 폴더가 없더라도, 해당하는 lock 파일이 존재한다면 동일한 패키지 구조를 재설치 할 수 있다.
  • npm으로 패키지를 설치, 수정, 삭제할 때마다 패키지들의 정확한 의존 관계를 package-lock.json 파일에 저장한다.
  • yarn의 경우 패키지들의 상세한 의존 관계를 yarn.lock 파일에 저장한다.
  • 이러한 lock 파일들은 개발 환경 간에 일관된 패키지 버전을 보장해줘서 버전 관리에 매우 중요한 역할을 한다.

 

yarn 설치

글로벌 환경에서 yarn을 설치하기 위해서는 아래 명령어를 터미널에 입력한다.

# npm을 이용하여 전역 환경에 Yarn을 설치합니다!
npm install -g yarn
  • npm install -g yarn은 npm으로 전역 패키지를 설치할 때 사용하는 명령어다
  • yarn 패키지 매니저를 어디서든 사용할 수 있도록 설치한다.
  • 설치가 완료되었는지 확인 하기 위해서는 yarn -v를 입력해 확인한다.

만약, yarn: 이 시스템에서 스크립트를 실행할 수 없으므로... 라는 에러가 난다면,

권한문제로 powershell에서 명령어를 통해 해결할 수 있다.

 

1. powershell 프로그램을 실행한다.

2. get-executionpolicy를 입력해 권한 상태를 확인한다.

3. remotesigned 권한 상태가 아니라면 set-executionpolicy remotesigned를 입력후 y를 눌러 수락한다.

4. get-executionpolicy로 권한 상태가 remotesigned로 변경되었는지 확인한다.

5. npm install -g yarn으로 재설치한다.

 

 

'IT' 카테고리의 다른 글

[IT] Access Token, Refresh Token  (1) 2024.09.09
[IT] 인증, 인가  (0) 2024.09.09
[IT] JWT  (0) 2024.09.08
[IT] 쿠키와 세션  (0) 2024.09.08
[AWS] RDS 구매하고 사용하기  (0) 2024.09.05

+ Recent posts