Node.js 와 Express, Restful API 에 대한 나의 경험

이 전에 나의 경험은 공식 가이드 북을 참고하여, 공부한 내용을 블로그에 기록하고, Azure에 배포했던 경험까지 있다.

아래는 이전에 수행했던 링크이며, 중복되는 내용 외에 새로 알게된 내용 위주로 정리하려고 한다.

  • Node.js 를 다루었었던 이전의 링크

  • Express 를 다루었었던 이전의 링크


1. Node.js의 구성요소

  • Node.js의 소스 코드는 C++와 자바스크립트, 파이썬 등으로 이루어져 있다.
  • Node.js는 각 계층이 각 하단에 있는 API를 사용하는 계층의 집합으로 설계되어 있다.

image-20230810142625939

<출처 - 78페이지, Node.js 백엔드 개발자 되기(박승규 지음)>

  • Node.js의 구성요소 중 V8과 libuv가 중요하다.
    • V8: 자바스크립트 코드 실행에 필요한 런타임에 사용되는 엔진
    • libuv: 자바스크립트 런타임에 필요한 이벤트 루프 및 운영체제 시스템 API를 사용하는데 필요한 라이브러리

2. Node.js의 장단점

  • 장점
    • 비동기 이벤트 기반 IO를 사용해 동시에 여러 요청을 다루기 용이
    • 자바스크립트를 사용해 프론트엔드 개발자의 백엔드 진입이 용이
    • 클라이언트와 같은 언어를 사용하면 서버의 코드에 사용된 로직을 클라이언트에서도 사용할 수 있음
    • 개발자 생태계가 잘 구성되어 있어서, 패키지 매니저에서 필요한 대부분을 제공함
    • V8 엔진이 JIT 컴파일러이므로 서버 기동이 빠름
  • 단점
    • 기본적으로 CPU를 하나만 사용하므로 멀티코어를 사용하려면 별도의 작업이 필요함
    • 비동기 지원하지 않는 IO, CPU 작업은 주의
    • 콜백을 중첩해서 계속 사용하면 코드 작성 및 디버깅이 힘들어짐
    • 이벤트 기반으로 프로그래밍을 해본 적이 없다면 코드 작성이 타 언어에 비해 어려울 수 있음

3. Node.js 서버 프로그래밍

아래 프로그램은 아래와 같이 동작한다.

  • 동작 1. 브라우저에서 localhost:8000 을 접속하면, hello Node.js가 출력
  • 동작 2. 콘솔에서는 서버를 호출할 때마다, 카운팅 값이 출력
const http = require("http"); // 1. http 객체 생성
let count = 0;

const server = http.createServer((req, res) => { // 2. 서버 객체 생성
    count = log(count); // 3. 카운트 1 증가
    res.statusCode = 200; // 4. 결괏값 200
    res.setHeader("Content-Type", "text/plain"); // 5. 헤더 설정
    res.write("hello\n"); // 6. 응답값 설정
    setTimeout(() => {
        res.end("Node.js") // 7. 2초 후 Node.js 출력
    }, 2000);
});

function log(count) {
    console.log((count += 1));
    return count
}

server.listen(8000); // 8. 8000번 포트로 서버 실행
  • res.statusCode = 200: 요청에 대한 상태 코드를 200으로 설정한다. 주요 상태 코드는 아래 표에서 확인.
코드 메시지 설명
200 OK 요청 처리 성공
301 Moved Permanently 요구한 데이터를 변경된 URL에서 찾음
304 Not modified 클라이언트의 캐시에 저장되어 있음
400 Bad Request 요청 실패. 클라이언트의 요청에 문제가 있음
403 Forbidden 접근 금지
404 Not Found 페이지를 찾을 수 없음
405 Method not allowed 요청한 메서드가 허용되어 있지 않음
408 Request timeout 요청 시간이 지남
500 Internal Server Error 서버 에러
501 Not Implemented 필요한 기능이 서버에 구현되어 있지 않음
502 Bad gateway 게이트웨이 상태가 좋지 않음
503 Service Unavailable 서버가 사용 불가 상태임
  • res.setHeader(“Content-Type”, “text/plain”): HTTP는 요청/응답에 대한 부가 정보를 설정할 수 있다. 부가 정보는 header에 설정하게 되는데, 여기서는 콘텐츠 타입을 ‘text/plain’으로 설정했다.
  • server.listen(8000): 사용할 포트 번호를 8000번으로 지정한다. IP가 생략되었으면, 기본값인 localhost 혹은 127.0.0.1로 서버에 접근할 수 있다.
    • 포트 번호는 16비트로 이루어져 있으며, 0~1023번 포트는 루트 권한이 필요하다. 1024~49151번은 슈퍼 유저 권한이 없어도 임의로 사용할 수 있다. 49152~65535번의 구간은 일반 사용자들이 자유롭게 사용할 수 있다.

4. curl 내려받기 및 테스트해보기

나는 Postman을 사용하기 때문에, curl에 대한 내용은 패스하였다.

5. 정말로 동시에 요청을 처리하는지 성능 테스트하기

개발 서버와 프로덕션 서버의 가장 큰 차이는 트래픽이다. 그래서 실제 유저의 트래픽이 들어오는 것처럼 테스트할 수 있는 도구 k6가 있다. 아래는 k6 설치 순서와 테스트방법, 결과이다.

  • 순서 1. 링크에서 다운로드 및 설치

image-20230810172938906

  • 순서 2. hello.js를 테스트하기 위해, ‘hello_test.js’ 파일을 동일한 경로에 생성
// hello_test.js
import http from "k6/http";

export const options = { // 1) 테스트 옵션
    vus: 100, // 유저 100명
    duration: '10s', // 10초 동안 요청을 보냄
};

export default function () {
    http.get("http://localhost:8000"); // 2) 테스트에 사용할 함수 지정
}
  • 순서 3. hello_test.js 파일 실행
k6 run hello_test.js
  • 순서 4. 실행결과를 아래와 같이 분석해볼 수 있음

image-20230811181224402

  1. 가상 유저 100명, 최대 40초 동안 테스트한 시나리오. 실제 테스트 시간은 10초, graceful Stop 기본값 30초를 더해서 40초가 됨. gracefulStop 옵션은 최소 30초 동안은 기존 유저값이 유지된다는 의미.
  2. avg=2.13s 는 평균 2.13초가 걸렸다는 의미. p(90)=2.2s는 90% 요청이 2.2s 이하라는 의미.
  3. HTTP 요청이 얼마나 실패했는지 보여줌.
  4. HTTP 요청이 500번 발생했다는 뜻.
  5. HTTP 요청이 한번 완료되고 다시 시작될때까지 걸리는 시간을 보여줌. 평균 2.13초가 걸림.
  • 순서 5. 분석 결과는 평균 2초 걸리는 요청 100개를 동시에 처리했다는 것을 알 수 있음. hello.js 디버그를 살펴보면, 1000번의 카운트가 된 것을 볼 수 있으며, 전부다 응답했음을 알 수 있다.

image-20230811182112045

참고

다음에 다루게 될 것

  • Node.js와 http 객체로 서버 만들기

댓글남기기