ChatterBOX client - server

hareguu·2020년 11월 17일
0
post-thumbnail

INTRO.

ChatterBox sprint 를 진행하면서. client와 server의 역할. 그리고 세부적인것들을 알아보았다.


CLIENT AND SERVER ROLE

서버

서비스를 제공(serve)하는 컴퓨터로, 다수의 클라이언트 컴퓨터의 요청을 처리하기 위해 존재
Web Server, File Server 등
웹페이지 지원이나, 공유 데이터의 처리 및 저장 등의 비즈니스 로직을 주로 수행

클라이언트

터미널의 역할을 수행하는 컴퓨터
웹 브라우저는 대표적인 터미널
사용자 입력을 주로 수행
서버에 대한 응답을 화면에 표시
현대의 복잡한 시스템은 클라이언트이면서 서버의 역할을 동시에 수행하는 경우도 있음 (e.g. P2P)

COMMUNICATION BETWEEN CLIENT AND SERVER

클라이언트와 서버는 프로토콜(Protocol)이라고 불리는 정해진 규약에 따라 메시지를 교환
클라이언트는 서버가 어떤식으로 요청을 처리하는지에 대해선 구체적으로 알 필요없이, 추상화된 인터페이스(API; Application programing Interface)를 바탕으로 원격 서버에 요청(RPC; Remote Procedure Call)을 하고, 응답에 대해 적절한 형태로 화면에 표시


CORS (Cross-originn Resource Sharing)

Background

  • 예전에는 웹-프론트엔드 사이트 따로, 서버 따로 두었고 웹 프론트엔드 에서 다른 도메인이 위치한 API 서버로 요청을 넣어야하는 상황이 생겼다. 이런것이 당연해 보이지만,
    웹 브라우저의 기본정책에 따르면 도메인이 다르면 요청을 주고 받을 수 없게 하는것이 일반적이였다.
    그 이유로는 개인정보 유출, 피싱사이트와 같은 보안상 악의적인 행동을 하는 걸로 의심하는게 자연스러울 때였기 때문이다. 그랬기 때문에 같은 도메인이 아니면 요청 자체가 불가능한게 일반적인 이유였다.
    예를들어, 기존 웹에서 날씨 weget 을 추가하고싶어한다면 라우터를 통해 우회하여 추가해야했는데, 이런 비효율적인 방식을 사용하던 과도기를 거쳐 지금의 CORS가 탄생하게 되었다.

Client

const app = {
  server: 'http://localhost:3000/messages',
  init: () => {
    app.fetch()
  },
  fetch: () => { //fetch API 를 통해 GET 요청을 제출.
    fetch(app.server) // 할당안해주면 GET 으로 감.
      .then((data) => data.json())  // GET 요청으로 받은 data 객체를 json() 해서 받음.
      .then((json) => {
        json.results.forEach((el) => app.renderMessage(el));  // json화 된 data를 렌더메소드의 매개변수로 받음.
      })
  },
  send: (message) => { // fetch API 를 통해 POST 요청 제출.
    fetch(app.server, {
      method: 'POST',
      body: JSON.stringify(message), // message 를 JSON.stringify 해서 서버에 요청.
      headers: {
        "Content-Type": "application/json",    // hearder 설정
      }
    }).then((data) => data.json())   // POST요청을 통해 서버에서 받은 data를 json() 해서 받음
      .then((json) => {
        app.renderMessage(json);     // json() 화 된 data를 렌더메소드의 매개변수로 받음.
      })
  },
  clearMessages: () => {              //clearMessages 를 통해 출력된 메세지 목록을 지움. 
    document.querySelector("#chats").textContent = "";
  },
  renderMessage: message => {  // rendering 
    let chats = document.querySelector("#chats")
    let main = document.createElement('div')
    main.className = 'chat'
    let user = document.createElement('div')
    user.className = 'username'
    user.textContent = message.username
    let msg = document.createElement('div')
    msg.className = 'message'
    msg.textContent = message.text
    let date = document.createElement('div')
    date.className = 'date'
    date.textContent = message.date
    let room = document.createElement('div')
    room.className = 'roomname'
    room.textContent = message.roomname;
    main.append(user, msg, date, room)
    chats.prepend(main)
  }
}

DOM 조작은 따로 설명하지 않겠다.
클라이언트를 만듦으로써 CORS의 header와 body가 왜 중요한지.
그리고 JSON.stringify 와 JSON.parse 의 용도를 알게되었다.


SERVER

1. nodejs

const http = require("http");
const port = 3000;
const ip = "127.0.0.1";
let message = { results: [] };
server.listen(port, ip);
const server = http.createServer((request, response) => {
    if (request.method === "OPTIONS") {
        response.writeHead(200, defaultCorsHeaders);
        response.end();
    }
    else if (request.method === "GET" && request.url === "/messages") {
        response.writeHead(200, defaultCorsHeaders);
        response.end(JSON.stringify(message));
    }
    else if (request.method === "POST" && request.url === "/messages") {
        let body = [];
        request
        .on("data", (chunk) => {
           body.push(chunk);
        })
        .on("end", () => {
           body = Buffer.concat(body).toString();
           message.results.push(JSON.parse(body));
           response.writeHead(201, defaultCorsHeaders); 
           //201 Created 요청이 성공적이었으며 그 결과로 새로운 리소스가 생성, 
           //이 응답은 일반적으로 POST 요청 또는 일부 PUT 요청 이후에 따라옵니다.
           response.end(JSON.stringify(message));
        })
    } else { // 매칭되는 주소가 없으면
        response.statusCode = 404; // 404 상태 코드
        response.end('주소가 없습니다');
    }
    const headers = defaultCorsHeaders;
    headers["Content-Type"] = "application/json";
    const defaultCorsHeaders = {
        "access-control-allow-origin": "*",
        "access-control-allow-methods": "GET, POST, PUT, DELETE, OPTIONS",
        "access-control-allow-headers": "content-type, accept",
        "access-control-max-age": 10 // Seconds.
    }

2. Express

const express = require('express')
const app = express()
const cors = require('cors') // cors 미들웨어
const bodyParser = require('body-parser') // body-parser 미들웨어
const jsonParser = bodyParser.json()
// body-parser 가 만들어내는 미들웨어가 들어옴 요청으로 들어오는 body 의 부분을 해석
app.use(cors())
app.use(jsonParser) // 전역에 jsonParser 설정.
let message = { results: []};
app.get('/messages', (req, res) => { // doesnt need to be parsing.
    res.status(200).send(message);
    // console.log(message)
})
app.post('/messages', jsonParser, (req, res) => { // why jsonParser? = > "POST"
    // console.log(req)
    message.results.push(req.body);
    res.status(201).send(JSON.stringify(req.body));
})
app.listen(3000)

REFERENCE

  1. < https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction/ >
  2. < https://expressjs.com/ko/ >
profile
Who wanna be a programming nerd.

0개의 댓글