#1. HTTP Server

1. Server (통신)

  • 통신이란 서로 다른 프로그램간의 데이터 교환을 말한다.
  • A라는 프로그램이 B라는 프로그램에게 어떤 데이터를 요청하면 B가 그에 대한 결과를 응답한다.
  • 이 때 A를 클라이언트, B를 서버라고 한다.

1) 웹 환경에서의 통신

  • 웹 브라우저가(클라이언트) 웹 사이트에 구동되고 있는 웹 서버(서버)에게 URL 형식으로 특정 파일의 내용을 요청한다.
  • 웹 서버는 자신이 요청받은 페이지의 HTML 코드를 응답 데이터로 전송한다.

 

2) 프론트엔드

  • 클라이언트 안에서 구동되는 프로그램
  • 엔드유저(최종사용자)에게 직접적으로 눈으로 보고, 조작할 수 있는 환경을 제공한다.
    • 웹 페이지 형식: HTML + CSS + JS
    • 안드로이드(JAVA, 코틀린), IOS(Swift)

 

3) 백엔드

  • 서버 안에서 구동되는 프로그램 혹은 서버 그 자체

 

2. Node.js로 서버 프로그램 구현하기

Node.js의 http 객체에 포함되어 있는 createServer( ) 함수를 호출하면 서버 객체가 리턴된다.

이 객체에 URL을 식별할 수 있는 처리를 추가하여 특정 URL을 통해 접근하는 클라이언트에게 전달할 데이터를 구성할 수 있다.

html

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>일반링크</h1>
  <a href="http://localhost:3217">페이지 이동을 통한 직접 백엔드 접속</a>
  <hr />
  <h1>Ajax</h1>
  <button id="get" type="button">get</button>
  <button id="post" type="button">post</button>
  <button id="put" type="button">put</button>
  <button id="delete" type="button">delete</button>
  <h1 id="console"></h1>

  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    document.getElementById('get').addEventListener('click', e => {
      e.preventDefault();

      (async () => {
        try {
          const response = await axios.get('http://localhost:3217/');
          document.getElementById('console').innerHTML = response.data.message;
        } catch(err) {
          const errorMsg = `[${err.response.status}] ${err.response.statusText}`;
          alert(errorMsg);
          return;
        }
      })();
    });

    document.getElementById('post').addEventListener('click', e => {
      e.preventDefault();

      (async () => {
        try {
          const response = await axios.post('http://localhost:3217/');
          document.getElementById('console').innerHTML = response.data.message;
        } catch(err) {
          const errorMsg = `[${err.response.status}] ${err.response.statusText}`;
          alert(errorMsg);
          return;
        }
      })();
    });

    document.getElementById('put').addEventListener('click', e => {
      e.preventDefault();

      (async () => {
        try {
          const response = await axios.put('http://localhost:3217/');
          document.getElementById('console').innerHTML = response.data.message;
        } catch(err) {
          const errorMsg = `[${err.response.status}] ${err.response.statusText}`;
          alert(errorMsg);
          return;
        }
      })();
    });

    document.getElementById('delete').addEventListener('click', e => {
      e.preventDefault();

      (async () => {
        try {
          const response = await axios.delete('http://localhost:3217/');
          document.getElementById('console').innerHTML = response.data.message;
        } catch(err) {
          const errorMsg = `[${err.response.status}] ${err.response.statusText}`;
          alert(errorMsg);
          return;
        }
      })();
    });
  </script>
</body>
</html>

 

Node.js

// 모듈참조
import logger from '../helper/logHelper.js';
import { myIp } from '../helper/UtilHelper.js';
import http from 'http';
import fs from 'fs';
import path from 'path';

const __dirname = path.resolve();

/** 웹 서버 구동 */
const port = 3217;  // 포트번호 설정
const ip = myIp();
const server = http.createServer();  // 웹 서버 객체 만들기

/** 포트번호에 대해 리스닝 시작 */
// listen을 시작하면 호출될 콜백함수 지정.
// listen을 시작 -> 백엔드(서버)가 가동을 시작했다는 의미
server.listen(port, () => {
  logger.debug(port + '번 포트에서 백엔드가 구동되었습니다.');
  logger.debug('- - - - - - - - - - - - - - - - - - -');

  // 백엔드에게 접속할 수 있는 주소를 출력
  ip.forEach((v,i) => {
    logger.debug(`http://${v}:${port}`);
  });
});

/** 프론트엔드가 접속했을 때 발생하는 이벤트 */
server.on('connection', (socket) => {
  logger.debug(`프론트엔드가 접속했습니다. : ${socket.remoteAddress}, ${socket.remotePort}`);
  logger.debug(socket);
});

/** connection 이벤트 발생 직후 프론트엔드에게 결과값을 되돌려 주기 위해 호출되는 이벤트 */
// req(request) -> 요청객체: 브라우저가 서버에게 전달하는 정보를 담고 있다.
// res(response) -> 응답객체: 서버가 브라우저에게 결과를 전송하는 기능을 갖는다.
server.on('request', (req, res) => {
  logger.debug(`프론트엔드의 요청 >> [${req.method}] ${req.url}`);

  // 프론트엔드가 요청한 URL에 따라 출력 내용을 분기
  if(req.url == '/sample.html') {
    // 클라이언트에게 전송할 응답 헤더 구성
    res.writeHead(200, {
      // 브라우저에게 인식시킬 출력 내용의 컨텐츠 형식
      'Conent-Type': 'text/html; charset=utf-8'
    });

    // html 파일을 읽어들여서 응답객체 (res)에 연결
    const path = __dirname + '/crud-axios-sample.html';
    fs.createReadStream(path).pipe(res);
  } else {
    // 클라이언트에게 전송할 응답 헤더 구성
    res.writeHead(200, {
      // 브라우저에게 인식시킬 출력 내용의 컨텐츠 형식
      'Content-Type': 'application/json; charset=utf-8',
      
      /** CORS 접근 허용을 위한 설정 */
      // 접근을 허용할 도메인 혹은 IP(브라우저에 출력되고 있는 도메인을 의미함, *은 ALL의 의미)
      'Access-Control-Allow-Origin': '*',
      // 접근을 허용할 전송방식 (기본값은 GET, POST만 허용함)
      'Access-Control-Allow-Methods': '*',
    });

    // 출력할 내용을 저장하기 위한 빈 변수
    let json = null;

    switch (req.method) {
      case 'GET':  // 데이터 조회 기능
        json = {
          rt: 'OK',
          message: 'GET방식에 대한 요청입니다.'
        }
        break;
      case 'POST':
        json = {
          rt: 'OK',
          message: 'POST방식에 대한 요청입니다.'
        }
        break;    
      case 'PUT':  // 데이터 조회 기능
        json = {
          rt: 'OK',
          message: 'PUT방식에 대한 요청입니다.'
        }
        break;
      case 'DELETE':
        json = {
          rt: 'OK',
          message: 'DELETE방식에 대한 요청입니다.'
        }
        break;    
    }

    // JSON을 문자열로 변환 후 출력
    res.write(JSON.stringify(json));

    // 클라이언트에 데이터 전송 (통신종료, 출력 종료를 알림)
    res.end();
  }
});

/** 서버 종료 이벤트 */
// 정상적인 상황에서는 발생할 가능성이 없다.
server.on('close', function() {
  logger.debug('백엔드가 종료되었습니다.');
});

 

'국비수업 > Node.js' 카테고리의 다른 글

[Node.js/express] Cookie / Session  (0) 2022.06.30
[Node.js] Express  (0) 2022.06.29
[Node.js] HTTP Client  (0) 2022.06.27
[Node.js] Scheduler  (0) 2022.06.27
[Node.js] Log  (0) 2022.06.27

+ Recent posts