본문 바로가기

JavaScript/node.js

[express] [책] Node.js로 서버 만들기 (1/2)

 
Node.js로 서버 만들기
빠르게실무형 Node.js 개발자가 될 수 있도록 도와주는 실습형 입문서다.5줄로 만드는Node.js 서버로 핵심 개념을 파악하고,데이터베이스 연동,실시간 통신 실습을 통해 실무형 개발 지식을 습득한 후,페이스북 클론 코딩과 배포로 통합 실습을 해볼 수 있게 단계적으로 구성하였다.페이스북 클론 프로젝트는 처음엔따라해보고, 그다음엔안보고만들어보고, 그다음엔응용해서좀더확장된여러분의버전을만들어보길바란다. _대상 독자 _Node.js를 기술 스택에 담고 싶어한다면 _당장 Node.js로 서버를 개발해야 한다면 _개발부터 배포까지 가능한 Node.js 토이 프로젝트를 찾고 있다면

 

저자
박민경
출판
로드북
출판일
2021.10.21

▒ 'Node.js로 서버 만들기' 내용정리

Chapter01. Node.js 첫걸음

1-1. Node.js 첫걸음

  • 많은 서비스에서 웹과 앱을 사용하기에, 웹 개발 분야는 가장 보편적이면서도 핫한 분야이다
  • [클라이언트의 Request ↔ 서버의 Response]
    - 클라이언트 : 사용자의 컴퓨터
    - 서버 : 웹 서비스를 위한 리소스가 저장되어 있는 컴퓨터

  • [웹 서버란] : 클라이언트에서 보내는 요청을 처리하고 적절한 결과를 보내주는 프로그램
    - 기존 보편적인 웹 서버 프레임워크로는 파이썬의 Django와 자바의 Spring이 있다.
    - Node.js는 자유도가 높다는 특징

  • [Node,js가 서버 그 자체, 혹은 프레임워크를 의미하지 않는다]
     "Node.js는 자바스크립트의 런타임이다" (런타임 : 실행환경 => js를 구동할 수 있는 환경)
    (자바스크립트는 브라우저에서 동작하는 언어로 설계되었는데, Node.js는 이를 브라우저 밖에서도 동작하게 한다. 서버를 만드는데 가장 많이 사용됨.)

  • [Node.js의 장점]
    - js기반이기에 연결성이 좋음
    - 빠른 실행과 성능을 보장(비동기처리에서 강점)
    - 다른 서버 프레임워크에 비해 커스터마이징이 쉬움

  • [Node.js가 동작하는 방식 : 비동기처리]
    - 하나의 작업이 끝날 때 까지 제어권을 넘겨주지 않는 것을 Blocking, 순차적으로 작업이 진행되는 것을 Sync라 함
    - Node.js는 NonBlocking-Async방식으로 동작한다

    - 이는 싱글 스레드 & 이벤트 루프를 기반으로 한다(프로세스 : 브라우저 / 스레드 : 브라우저에서 실행되는 작업)
     /*
    싱글스레드로 동작하는 원리 나중에 따로 정리하기 : 이벤트루프(콜 스택, 콜백 큐)
    0. [이벤트루프의 감시 下]
    1. 작업스레드는 작업이 끝난 뒤, 이어서 실행될 콜백함수를 '콜백 큐'에 등록한다
    2. 이벤트루프는 이를 '콜 스택'에 하나씩 넣어 실행시킨다
    */

Chapter02. 자바스크립트 리마인드

 

Chapter03. 5줄로 만드는 서버

3-3. http 모듈로 서버 만들기

  • localhost는 루프백 도메인 이름(호스트 이름)이다.
    (루프백 : 인터넷 상에서 자신의 컴퓨터를 식별하는 특수한 형태의 IP 주소)

  • 포트번호는 0부터 65535번 까지, 서버용으로는 80 혹은 8080이 주로 쓰인다
    Well-known ports (0~1023) : 이미 사용중이라 사용 불가
    Registered ports(1024~49151) : 필요시 할당 받아 사용
    Dynamic ports(49152~65535) : 주로 시스템에서 사용 

  • [http 상태 코드] : http요청에 대한 성공/실패 여부를 알려줌
    - 100번대 : 요청을 받았고, 작업을 계속 진행해도 된다
    - 200번대 : 요청을 수용했다
    - 300번대 : 요청을 완료하려면 추가적인 작업이 필요하다
    - 400번대 : 클라이언트 서버 오류(권한,부적절한 URL 등)
    - 500번대 : 서버에 문제있음

  • [주요 http 상태 코드]
    - 200 : 요청 성공
    - 204 : 요청은 성공했으나, response 할 내용이 없음
    - 304 : 이전 요청과 중복
    - 400 : 요청에 오류가 있음
    - 401 : 요청에 권한 필요
    - 403 : 요청이 거부됨
    - 404 : 요청한 URL의 부존재
    - 500 : 서버에 오류가 있어 응답이 불가함

3-4. express 모듈을 사용해 서버 만들기

  • [프레임워크]
    설계 & 구현의 측면에서 재사용이 가능한 도구들을 제공하는 것.
    = 전형적으로 필요한 작업들을 미리 해놓은 것

  • [버전 표기법 : SemVer 표기법]
    세 자릿수로 표기함
    첫 번째 : 중요한 업데이트 (^0.0.0 : 첫 째 자리까지 고정) (권장)
    두 번째 : 버그 수정등 일반적인 수정 (~0.0.0 둘 째 자리까지 고정)
    세 번째 : 사소한 수정 (0.0.0 해당 버전만을 사용)

  • [express가 대신 해주는 것들]
    /*이 부분은 학원 수업내용 보고 정리하기*/
    post요청시 받아온 정보를 자동으로 req.body에 파싱해주는 미들웨어를 가짐
    express 사용시 node_modules 라이브러리가 다운로드 됨
    express-generator를 사용하면 서버구동을 위한 설정(bin, app.js) 및 전형적인 웹 서버 설계구조까지 만들어줌 

  • [http 요청 메서드] : 클라이언트가 웹 서버에게 자신의 목적을 알리는 수단!
    GET : 리소스를 얻을 때(ex. 페이지 로딩)
    HEAD : 문서의 정보를 얻을 때
    POST : 리소스를 전송할 때(ex. 입력 폼 제출)
    PUT : 내용 전체를 갱신할 때
    PATCH : 내용을 부분적으로 갱신할 때
    DELETE : 파일을 삭제할 때

3-5. express와 미들웨어

  • 미들웨어는 요청과 응답 사이에서 구체적인 작업을 수행하는 역할을 함
    app.use() 메서드를 통해 사용한다. 
    app.set()은 전역으로 사용된다는 차이점


  • 미들웨어는 순서대로 실행되기 때문에 순서 배치가 중요하다
    - next() : 다음 미들웨어로
    - next(error) : 오류 처리 미들웨어로
    - next('route') : 한 라우터 내에서 분기를 만들 때

  • [자주 사용하는 미들웨어]

    1. exrpess.static(__dirname + '/public') :
    정적파일을 담은 경로만 지정해주면 자동으로 매칭하여 처리함

    2. router : app.use('/경로', 미들웨어)
    특정경로 요청시 연결될 미들웨어를 지정함 (use, get, post, put, delete)   

    3. morgan : app.use(logger('양식')) 
    요청과 응답을 양식에 따라 콘솔에 출력하는 기능 (combined, common, dev, short, tiny)
    콘솔이 아니라 dump파일로 기록하는 winston이라는 모듈도 있다

    4-1. express.json : app.use(express.json()) 
    4-2. express.urlencoded : app.use(express.urlencoded({extended : true}));
    post, put 요청시에는 요청정보가 url이 아니라 request body에 들어있는데, 이 정보를 읽을 수 있는 구문으로 파싱 하고 req.body 필드로 넘겨주는 역할을 한다

    5. cookie-parser :
    클라이언트가 보낸 쿠키는 req.headers.cookie를 통해 문자열로 전달되는데 이를 req.cookies.쿠키명에 파싱해주는 역할

    6. exrpess-session :
    쿠키와 유사한 개념이나, 세션은 정보를 서버에 두고 브라우저에는 암호회된 키 값만 보낸다는 점에 차이

  • [응답을 위한 함수]
    - res.send() : 문자열로 응답
    - res.json() : json 객체로 응답
    - res.render() : pug와 같은 템플릿을 렌더링하여 응답
    - res.sendFile() : 파일로 응답

3-5. 미들웨어 적용 예제

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

/* 포트 설정 */
app.set('port', process.env.PORT || 8080);

/* 공통 미들웨어 */
app.use(express.static(__dirname + '/public'));
app.use(morgan('dev'));
app.use(cookieParser('secret@1234')); // 암호화된 쿠키를 사용하기 위한 임의의 문자 전송
app.use(session({
    secret: 'secret@1234', // 암호화
    resave: false, // 새로운 요청시 세션에 변동 사항이 없어도 다시 저장할지 설정
    saveUninitialized: true, // 세션에 저장할 내용이 없어도 저장할지 설정
    cookie: { // 세션 쿠키 옵션 들 설정 httpOnly, expires, domain, path, secure, sameSite
        httpOnly: true, // 로그인 구현시 필수 적용, javascript로 접근 할 수 없게 하는 기능
    },
    // name: 'connect.sid' // 세션 쿠키의 Name지정 default가 connect.sid
}));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

/* 라우팅 설정 */
app.get('/', (req, res) => {
    if (req.session.name) {
        const output = `  
                <h2>로그인한 사용자님</h2><br>  
                <p>${req.session.name}님 안녕하세요.</p><br>  
            `
        res.send(output);
    } else {
        const output = `  
                <h2>로그인하지 않은 사용자입니다.</h2><br>  
                <p>로그인 해주세요.</p><br>  
            `
        res.send(output);
    }
});

app.get('/login', (req, res) => { // 실제 구현시 post
    console.log(req.session);
    // 쿠키를 사용할 경우 쿠키에 값 세팅 
    // res.cookie(name, value, options)
    // 세션 쿠키를 사용할 경우
    req.session.name = '로드북';
    res.end('Login Ok')
});

app.get('/logout', (req, res) => {
    res.clearCookie('connect.sid'); // 세션 쿠키 삭제
    res.end('Logout Ok');
});

/* 서버와 포트 연결.. */
app.listen(app.get('port'), () => {
    console.log(app.get('port'), '번 포트에서 서버 실행 중 ..')
});

Chapter04. 통신을 구현해보자!

4-1.API

  • Aplication Programming InterFace : 응용프로그램 사이의 소통 방법

  • [JSON 접근 방법]
    - JSON.parse() : string 객체를 json 객체로 변환한다
    - JSON.stringify : json객체를 string객체로 변환한다

  • [request] :
    http 라이브러리 중 가장 오래된 모듈. deprecated된 상태.
    (deprecated : 새로운 기능이나 유지보수 업데이트를 멈추었으며, 이제 쓰이지 않게됨을 의미)

  • [axios] :
    request모듈로 http통신을 하려면 비동기처리가 별도로 필요.
    axios는 Promise를 반환하고 async/await까지 사용할 수 있으며, 구형브러우저 지원 및 요청 중단, 응답시간 초과 설정까지 가능. CSRF보호 기능과 JSON 자동변환 지원
    axios로 받아온 정보는 .data를 붙여주어야 사용 가능하다!

  • [dotenv] :
    노출되면 안되는 정보를 precess.env 객체로 생성해주는 역할을 함.
    키 = 값의 형태로 작성한 .env파일의 위치를 지정해주면 process.env.key 를 통해서 접근 가능

4-2. 캐싱 구현하기

  • API호출은 횟수에 제약이 있고, 받아온 데이터를 파싱하는 부분에서도 리소스가 많이 필요하기에 캐싱시스템 구현이 필수적이다.
  • [Redis : Remote Dictionary Server] :
    NoSQL의 일종으로, 데이터를 키 = 값 형태로 저장하는 데이터 관리 시스템.
    모든 데이터를 메모리에 저장하고 조회하기 때문에 관계형데이터베이스보다 빠르다.
    리스트, 배열 같은 형식의 데이터 처리에 강점이 있으며 쿠키 & 세션을 저장하는데 주로 사용

4-3. REST API

  • [REST : REpresntatianl State Transfer]
    요청받은 주소만 보고도 어떤 내용에 관한 요청인지를 예상할 수 있게 하는 형식

  • API서버를 만들면 다른 사람이 내 서버의 정보를 사용할 수 있게 하는 것 뿐 아니라, 내 웹을 모바일 등으로 구현할 때 서버로 사용할 수 있음. 또한 내 서버의 코드를 공개하지 않으며 데이터베이스에 접근할 권한도 주지 않으면서 데이터만 전달할 수 있기에 보안에도 유리하다

  • 구축한 API는 curl명령어 혹은 Postman 같은 API 테스트 도구를 이용해 시험할 수 있다. 

  • [CORS : Cross - Origin - Resource - Sharing]
    브라우저에서 서버로 요청을 보낼 때, 도메인 이름이 서로 다른 경우 발생하는 오류. 서버에 아무나 접근하는 것을 막기위한 조치
    API를 제공하는 서버 쪽에서, 요청측에 대한 Acess-Control-Allow-Origin을설정해주어야 한다.
    (= 특정한 출처의 접근에 대한 허용 설정)
    +) npm의 cors모듈을 이용하면 확장성이 더 좋음

4-4. 웹 파싱

  • API가 없거나 있어도 사용할 수 없는 경우 : 크롤링, 스크래핑, 파싱
    - 크롤링 : 자동회된 방법으로 웹을 탐색하는 작업
    - 파싱 : 내가 원하는 데이터를 특정한 패턴이나 순서에 따라 추출하여 가공하는 작업
    - 스크래핑 : 크롤링, 파싱의 상위개념

  • [chreeio 모듈] : axios로 받은 데이터에서 DOM Selector로 데이터를 추출하는 모듈