개발 블로깅/Server&DataBase 개념

[2019.04.23] API 서버를 만들어보자 - http 방식

Hello이뇽 2019. 4. 23. 11:22

node.js를 이용한 API를 직접 만들어 볼 기회가 올 줄이야. 정말 내가 원하는 작업이였다...ㅜㅜ (그렇다고 백엔드를 갈구하는 편은 아니다..)

 

지금부터 API 서버를 만들어 보는 작은 프로젝트를 작업해보자.

 

프로젝트로 쓸 디렉토리 생성

mkdir serverProject

cd serverproject

 

 

module 관리자 package.json 생성

npm init -y

 

 

서버 개발 중 코드를 작업 후 저장하면 바로 적용되는 nodemon 모듈을 로컬로 설치 (새로고침을 안해도 됨)

npm i -D nodemon

 

 

package.json에 nodemon 설정 (npm start 명령어로 바로 실행 시킬 수 있도록 설정)

{
  "name": "testServer",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "./node_modules/nodemon/bin/nodemon.js server/runServer.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^1.18.11"
  }
}
// package.json 파일

 

 

이제 VSCode를 켜서 서버와 클라이언트로 쓸 파일을 생성한다. 

각 파일 정보

  • index.html : 서버에게 요청 및 응답받을 클라이언트
  • server/runServer.js : 서버를 생성하여 돌릴 파일 (경로 주의)
  • server/handle_Server.js : 실제 서버가 요청, 응답에 대한 작업을 처리하는 파일 (경로 주의)

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>

</head>
<body>
  <input type="text" id='inputText' />
  <input type="button" id="btn" value="go" onclick="test()" />
  <input type="text" id='resultText' />
  
  <script>
    function test(){
      var input = document.getElementById('inputText').value;
    }
  </script>
</body>
</html>

클라이언트는 최대한 간결하게 만들었다.

왼쪽 인풋박스는 서버에 요청 값을 보낼 박스, 오른쪽 input은 응답받아서 표시할 박스이다.

 

# server/runServer.js

const http = require('http'); // node에 내장된 http 모듈
const handle = require('./handle_Server'); // 실제 요청, 응답 작업을 처리할 파일

const port = 3000;  // 서버 요청 포트
const ip = '127.0.0.1'; // 서버 ip

const server = http.createServer(handle); // 서버 생성
server.listen(port, ip); // 서버 접속경로 설정

 

서버를 생성해주는 부분이다. 서버를 직접 작업하는 파일을 따로 분리시켜놔서, require로 받아서 사용한다.

 

# server/handle_Server.js

const requestHandler = function (request, response){

  const headers = defaultCorsHeaders;
  headers['Content-Type'] = 'text/plain'; // 응답하는 컨텐츠의 자료 타입을, 응답 헤더에 기록

  let statusCode = 200;  // 200 : 요청 성공, 404: 실패
  let responseValue = '';

  if(request.method === 'POST'){
    
  }else if(request.method === 'GET'){

  }else if(request.method === 'OPTIONS'){

  }
  response.writeHead(statusCode, headers);
  response.end(JSON.stringify(responseValue));
}

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.
};

module.exports = requestHandler; // 외부에서 사용할 수 있도록 exports

 

기본적인 세팅이다. 클라이언트에서는 요청 방식이 POST,GET,PUT,DELETE 방식 중 하나를 쓰지만, 일반적으로는 GET,POST를 쓰므로, 이렇게 설정을 해준다.

∴ OPTIONS란? 클라이언트는 서버에게 요청을 보내면 두개의 신호를 보낸다. 하나는 서버에 요청 및 응답이 잘 되는지 테스트 신호인 OPTIONS, 두번째가 실제 클라이언트가 보내고자 하는 방식의 신호를 보낸다.

 

첫번째 신호인 OPTIONS가 응답 및 요청에 실패를 하면, 두번째 신호는 보내지 않고 바로 요청 실패로 처리한다.

 

이제 우리는 클라이언트가 소문자 알파벳을 보내면, 서버는 대문자로 변환하여 응답을 보내는 작업을 해보자.

 

# index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>

</head>
<body>
  <input type="text" id='inputText' />
  <input type="button" id="btn" value="go" onclick="test()" />
  <input type="text" id='resultText' />
  
  <script>
    function test(){
      var input = document.getElementById('inputText').value;

      fetch('http://localhost:3000/upper',{
        method: 'POST',
        body: JSON.stringify(input),
        headers: {
          'content-type': 'text/json'
        }
      })
      .then(res => {res.json()})
      .then(res => {document.getElementById('resultText').value = res;});

    }
  </script>
</body>
</html>

 

fetch 서버요청 방식은 앞 단에서 배웠을 것이다. 위 와 같이 입력한 내용을 서버에게 보내는 POST 요청 방식을 한다. (경로에 주의한다.)

서버에게 응답받은 데이터를 오른쪽 input 박스에 넣는 작업을 한다.

 

# handle_Server.js

클라이언트에게서 데이터를 받는 방식은 아래와 같다.

    let body = ''; // 클라이언트가 보낸 데이터를 담을 변수
    request.on('data', data => {
      body += data.toString(); // 버퍼 상태의 데이터를 데이터로 변환(?)
    }); 

왜 이렇게 되는지는 모르겠다. 그냥 외워야 한다.

 

데이터를 클라이언트에게 보내느 방식은 아래와 가다.

    request.on('end', () => {
      response.writeHead('200', headers);
      response.end('보낼 데이터');
    }

 

그럼 위 방식을 이용해서 handle_Server.js 파일을 적절히 작업해보자. 조금 복잡할 수 있다...

const requestHandler = function (request, response){

  const headers = defaultCorsHeaders;
  headers['Content-Type'] = 'text/plain'; // 응답하는 컨텐츠의 자료 타입을, 응답 헤더에 기록

  let statusCode = 200;  // 200 : 요청 성공, 404: 실패
  let responseValue = '';

  if(request.method === 'POST'){
    let body = ''; // 클라이언트가 보낸 데이터를 담을 변수
    request.on('data', data => {
      body += data.toString(); // 버퍼 상태의 데이터를 데이터로 변환(?)
    });                         // 사실 나도 여기는 잘 모르겠다..

    request.on('end', () => {
      if(request.url === '/upper'){
        responseValue = body.toUpperCase();
      }else if(request.url ==='/lower'){
        // 미구현
      }
      response.writeHead(statusCode, headers); // 응답헤더 설정
      response.end(responseValue); // 응답 메세지 전달 및 서버 요청 종료
    }
    );
  }else if(request.method === 'GET'){
    
  }else if(request.method === 'OPTIONS'){
    response.writeHead(statusCode, headers);
    response.end('1');
  }
  
}

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.
};

module.exports = requestHandler; // 외부에서 사용할 수 있도록 exports

 

 

제대로 서버에 요청하고 대문자로 변환된 데이터를 받아오는 것을 확인할 수 있다.

반응형