본문 바로가기
프로그래밍/웹 개발

[Node. js] Mini Node Server 제작 스프린트 (createServer)

by 제이콥J 2021. 7. 1.

Mini Node Server 스프린트


스프린트 과제 설명

 

1. 목적

- 웹 서버를 구현하기 

- 클라이언트의 액션(버튼 클릭)에 따라 각기 다른 HTTP 요청을 서버로 보내고, HTTP 요청에 담아 보낸 단어를 소문자 또는 대문자로 변경된 단어를 응답으로 받아 화면에 보여주기

클라이언트 브라우저 예시

 

2. 방법

- HTTP 요청과 응답을 다루기 위해 HTTP 모듈 사용

- HTTP 트랜잭션 해부에 관한 공식문서 참고하기 : https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction/

 

3. 요구사항

- Endpoint(URL)에 따른 Method 기능 구현하기

/lower POST 문자열을 소문자로 만들어 응답해야 합니다
/upper POST 문자열을 대문자로 만들어 응답해야 합니다

- POST에 문자열을 담아 요청을 보낼 때는 HTTP 메시지의 body(payload)를 이용

- 서버는 POST 요청 이외의 다른 모든 요청에 대하여, 클라이언트에 잘못된 요청이라고 알려주기

- CORS 관련 헤더를 OPTIONS 응답에 적용하기 (클라이언트의 preflight request 에 대한 응답을 돌려주기)

 

4. 초기 코드

const http = require('http');

const PORT = 5000;

const ip = 'localhost';

const server = http.createServer((request, response) => {
  
  // 코드 작성
  
  response.writeHead(200, defaultCorsHeader);
  response.end('hello mini-server sprints');
});

server.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

const defaultCorsHeader = {
  '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
};

문제 해결 코드

 

1. 메소드가 OPTIONS인 경우, preflight request에 대한 응답 돌려주며 CORSE 관련 헤더를 응답하기

if (request.method === 'OPTIONS') {
response.writeHead(200, defaultCorsHeader);
response.end();
}

 

2. 메소드가 POST인 경우, url이 각각 '/upper', '/lower'인 경우에 따라 요청 바디 받기

else if (request.method === 'POST') {
  response.writeHead(201, defaultCorsHeader);
  
  if (request.url === '/upper') {
    let body = [];
    request.on('data', (chunk) => {
    body.push(chunk);
    }).on('end', () => {
    body = Buffer.concat(body).toString().toUpperCase();
    response.end(body)
    });
  }

  else if (request.url === '/lower') {
    let body = [];
    request.on('data', (chunk) => {
    body.push(chunk);
    }).on('end', () => {
    body = Buffer.concat(body).toString().toLowerCase();
    response.end(body)
    });
  };

}

 

3. 위 조건에 해당하지 않는 경우 에러메세지 전달

else {
  response.writeHead(404, defaultCorsHeader);
  response.end('Bad Request')
}

에러 핸들링

 

1. if문 2개 실행시 에러 발생

 

- (에러코드) code : 'ERR_STREAM_WRITE_AFTER_END'

 

- 문제상황 : if문을 2개 사용하자 에러 코드 발생

 

- 해결방법 : 조건문 안에 조건문을 넣어주어 if문을 하나로 만들어줌

 

- 코멘트 : 첫번째 if문과 마지막 else문에 모두 해당되어, 각기다른 2가지의 응답(reponse)을 동시에 발송해서 충돌이 일어남

//에러 수도코드

if (Method==='OPTIONS') { 내용 }
if (Method==='POST' && URL=== '/upper') { 내용 }
else if (Method==='POST' && URL=== '/lower') { 내용 }
else {내용}

 

// 에러 해결한 코드

if (Method==='OPTIONS') { 내용 }
else if (Method==='POST') { 
  if (URL=== '/upper') { 내용 }
  else if (URL=== '/lower') { 내용 }
}
else {내용}

 

 

2. Node.js의 비동기 처리방식으로 인한 에러

 

- (에러코드1) code: 'ERR_INVALID_ARG_TYPE'

 

- (에러코드2) TypeError: body.toUpperCase is not a function

 

- 문제상황 : response에서 body의 데이터를 수정하려고 했으나, 비동기적 처리방식으로 인해 body가 빈 배열

 

// 에러코드1
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString().toUpperCase();
});

response.end(body)

 

// 에러코드2
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
});

response.end(body.toUpperCase())

 

- 해결방법 : request.on의 콜백함수 안에 response.end를 넣어줌

 

//해결방법1
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  response.end(body.toUpperCase())
});
    
//해결방법2
let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString().toUpperCase();
  response.end(body)
});

 

 

- 코멘트

  • 비동기 처리방식에서 나타나는 현상
  • request 구문을 실행시키지만, 실행이 완료되길 기다리지 않고 다음 구문으로 넘어감
  • 따라서 request구문 밖의 body에는 여전히 빈 배열이 그대로 전달됨
  • 컴퓨터 언어의 공통점은 위에서부터 순차적으로 코드를 읽어나가며, 자바스크립트는 인터프리터 언어로 컴파일 언어와 달리 실행속도 느림
let body = [];

request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();

  console.log(body) // 엘리먼트가 포함된 배열 출력
});

console.log(body)   // 빈 배열 출력

 

 

 

 

반응형

댓글