TIL
2023. 4. 1.
TIL #013
오늘 개발한 것
BookStack FE
- axios 설치
- axios를 통한 /signup post 구현
BookStack BE
- cors 미들웨어를 통한 CORS 정책 회피
- body-parser를 통한 req.body 파싱 구현
- /signup post 데이터 받아오기 구현
오늘 배운 것
생활코딩 - Node.js
- 더보기http://opentutorials.org:3000/main?id=HTML&page=12opentutorials.org : host(domain)main : pathModule : url사용방법은 아래와 같다.관련 문서 : Node.js > URLNode.js의 파일 읽기 기능
관련 문서 : Node > fs.readFile콘솔을 통해 입력된 값을 Node.js에서 읽는 방법const fs = require('fs'); const data = fs.readFile(path [,options], callback);
Module: fs.readDir아래와 같은 방법으로 사용 가능관련 문서 : Node > fs.readDirNode.js에서의 모듈의 동기와 비동기를 구분하는 기준Node.js는 기본적으로 모든 모듈이 비동기적으로 처리되도록 되어 있으나, 뒤에 Sync를 붙이게 되면 동기적으로 처리되도록 예외를 두고 있다.import { argv } from 'node:process'; // print process.argv argv.forEach((val, index) => { console.log(`${index}: ${val}`); });
Sync (X) ⇒ 비동기적 처리NPM : Nodejs Package manager다양한 package들(프로그램들)을 설치 할 수 있도록 해 준다.const fs = require('fs'); console.log('A'); const file = fs.readFileSync('B.txt'); console.log(file); console.log('C'); // A B C 순서로 출력
- Node.js를 설치할 때 기본적으로 함께 설치되는 package manager
- const fs = require('fs'); console.log('A'); const file = fs.readFile('B.txt', () => { console.log(file); }); console.log('C'); // A C B 순서로 출력
- Sync (0) ⇒ 동기적 처리
- 어떤 모듈이던 뒤에 Sync가 붙어 있으면 동기적으로 처리하는 모듈이다.
- Sync
- import { readFile } from 'node:fs'; readFile('/etc/passwd', (err, data) => { if (err) throw err; console.log(data); });
- 디렉토리의 파일 목록을 읽을 수 있는 모듈
- 아래와 같은 방법으로 사용 가능
- Module : process.argv
- 아래와 같은 방법으로 사용 가능함
- Module : fs.readFile
- const url = require('url') const app = ....(req, res){ const currentUrl = req.url; const queryData = url.parse(currentUrl, true).query; };
- Node.js에서 url을 사용할 수 있도록 하는 모듈.
- id=HTML&page=12 : query string query string의 시작은 ?, 구분은 &
- 3000 : port (http의 기본 포트 = 80)
- http : protocol
- URL
생활코딩 - Express
- 더보기Web Application을 보다 세련되게 만들기 위해 만들어진 Node.js Framework.Node.js에서 가장 보편적으로 사용되는 프레임워크 이기도 함.세상의 반복적인 일들을 자동화하여 처리할 수 있도록 해 주는 코드 모음.Route Parameter : req.params아래와 같이 사용할 수 있음관련 문서 : Express Routingbody로 전달되는 내용들의 parsing을 위해 사용되는 미들웨어.cf. express v.4 이상부터는 내장되어 있기 때문에 별도로 설치할 필요는 없음미들웨어 : compression대체로 압축, 압축 해제하는 비용이 큰 데이터를 네트워크로 보내는 것 보다 저렴하기 때문에,
미들웨어의 실행 순서const compression = require('compression'); const app = require('express')(); app.use(compression()); // 이 후 모든 express를 통한 데이터는 압축되어 유통된다.
관련 문서 : Express > using-middleware404 처리어느 라우팅도 찾지 못하고 해당 미들웨어까지 도달하게 되면 404 에러가 아래와 같이 실행됨.라우팅 콜백함수에서의 err아래와 같이 사용 가능next(err)err가 발생하는 어디서든 next()의 인자로 해당 err를 주게 되면, 코드 최하단에 있는 err 처리 담당 미들웨어가 실행된다.Router 분리메인 파일topicRouterconst app = express(); app.use(function (req, res, next){ // 실행할 코드 next(); };
Express 보안 유지 방법// topicRouter.js const express = require('express'); const router = express.Router(); router.get(...); router.post(...); module.exports = router;
- Express를 항상 최신 버전으로 유지할 것
- TLS를 사용할 것 (https)
- Helmet 미들웨어를 이용할 것
- 분리된 router가 위치될 파일
- // main.js const topicRouter = require('./topicRouter.js'); app.use('/topic', topicRouter);
- main.js
- app.get('/', (req,res) => { fs.readFile('file.txt', (err, res) => { if(err) next(err) // 에러 담당 미들웨어로 err를 보내버림 // err가 발생하지 않았다면 하위 코드 실행. }; ) ... // next(err)는 최하단의 err 담당 미들웨어를 실행시킴. app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('에러 발생'); } app.listen(...)
- 미들웨어 상의 모든 err를 핸들링 할 수 있는 미들웨어
- app.get('/', (req,res) => { fs.readFile('file.txt', (err, res) => { if(err) res.send('fs.readFile 실행 도중 에러 발생'); // err 발생 // err가 발생하지 않았다면 하위 코드 실행. }; )
- 모듈 실행 중 에러가 발생했는지 여부를 알 수 있는 매개변수
- app.use((req, res, next) => { res.status(404).send('can\\'t find page'); };
- 미들웨어의 가장 마지막에 위치하도록 설정.
- Express 에러 처리 방법
- Application-level middleware
- 용량이 큰 경우에는 반드시 compression하는 과정이 필요하다.
- 데이터를 압축하여 응답할 수 있는 미들웨어.
- const bodyParser = require('body-parser'); const express = require('express'); const app = express(); app.use(bodyParser.urlencoded({ extended: false })) app.post('/create', (req,res) => console.log(req.body)); // body에 post의 데이터가 들어 있음
- body-parser 미들웨어를 사용함으로서 req에서 body라는 프로퍼티를 사용할 수 있게 된다.
- 미들웨어 : body-parser
- // url : localhost:3000/page/HTML app.get('/page/:pageId', (req,res) => { const params = **req.params**; console.log(params); // {pageId : HTML} }
- URL 파라미터를 값으로 받을 수 있도록 해주는 프로퍼티
- 즉 더 적은 지식, 코드로 더 많은 일들을 안전하게 처리할 수 있도록 해주는 도구.
- Framework란?
- 기본적으로 Node.js 위에서 동작
- Express?
VLPT - Baekend/JWT
- 더보기
- 유저가 현재 로그인 중이라는 정보를 서버에 저장하는 방식
- 메모리 또는 데이터베이스에 저장
- 로그인한 유저가 많아지면 메모리 혹은 데이터베이스에 무리가 됨
- 서버 확장이 어려워짐
- 유저가 회원 인증할 때 토큰을 발급 해 주는 방식
- 토큰에는 유저 정보, 토큰 만료일 등의 정보가 저장되어 있으며, 이러한 정보는 해싱되어 암호화된 상태로 저장된다.
- 장점
- 서버 확장 용이
- 플랫폼간 권한 공유 가능
- 쿠키 사용이 어려운 모바일에서도 사용 가능
- 토큰 저장 방식
- localstorage || sessionstorage에 저장
- XSS 해킹 공격에 취약함
- 토큰을 쿠키에 넣는 방식
- 쿠키가 한정된 도메인에서만 사용 가능
- CSRF 해킹 공격에 취약하나, 해당 공격은 해결 가능
- localstorage || sessionstorage에 저장
- 세션 방식 회원 인증
JWT Auth
- 더보기JSON형식의 데이터를 저장하는 토큰.헤더페이로드헤더와 마찬가지로 Base64URL을 사용하여 인코딩/디코딩되기 때문에 보안 관련된 내용이 있어서는 안됨.인코딩 된 Header, 인코딩 된 Payload, 비밀키, 헤더에 지정된 알고리즘으로 구성.참고 문헌 : JWT 관련 블로그express에서 jwt를 다루기 위해 설치하는 패키지.
- 참고 문헌 : jsonwebtoken 관련 블로그
- jsonwebtoken
- Base64URL을 거치지 않고 헤더 알고리즘을 통해 바로 암호화되기 때문에 보안에 강함. 또한 원본 데이터가 변경되면 바로 알 수 있기 때문에 데이터의 무결성을 보장함.
- Signature
- claim 데이터(유저 정보, 메타 데이터 등)로 구성. 용량 문제로 인해 최대한 줄인 단어를 사용 (issuer ⇒ iss, expiration time ⇒ exp 등)
- 일반적으로 해시 알고리즘, 토큰 타입으로 구성. Base64URL로 인코딩 되며, 똑같이 Base64URL로 디코딩 될 수 있기 때문에 보안 관련된 내용이 위치해서는 안되는 부분이다.
- 헤더, 페이로드, 시그니처 세 부분이 각기 .로 구분되어 구성되어있음.
- JWT (JSON Web Token)
오늘의 에러
CORS CORS Fuxking CORS
에러 상황
로컬 간 통신에서 CORS에러 발생
원인
구글의 CORS policy
해결방법
express에 cors 미들웨어 적용
관련 문헌 : Express > CORS, 관련 블로그