Search
🎁

클라이언트와 서버 간 HTTP 요청 주고 받기

Created
2023/04/04
Tags
HTTP
Category
Project
Parent item
Sub-item
2 more properties

 TODO

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

조건

Endpoint(URL)
Method
기능
/lower
POST
문자열을 소문자로 만들어 응답해야 합니다
/upper
POST
문자열을 대문자로 만들어 응답해야 합니다
POST에 문자열을 담아 요청을 보낼 때는 HTTP 메시지의 body(payload)를 이용한다.
서버는 요청에 따른 적절한 응답을 클라이언트로 보내야 한다.
CORS 관련 헤더를 OPTIONS 응답에 적용해야 한다.
클라이언트의 preflight request에 대한 응답을 돌려줘야 한다.
preflight request에 대한 응답 헤더는 이미 작성되어 있다.

서버 실행

해당 디렉토리로 진입한 다음, 아래 커맨드를 CLI에 입력하고, 서버를 종료하려면 Ctrl+C를 눌러 프로그램을 강제 종료한다.
node server/basic-server.js
Shell
복사
서버 코드를 수정하고 저장했다면 프로그램을 매번 다시 실행해야 하지만, nodemon을 이용하면 서버를 매번 실행시킬 필요가 없이 npm start만 입력해도 된다.
# 1. nodemon 설치 npm install nodemon # 2. package.json의 "scripts"에 아래 코드를 추가 "start": "nodemon server/basic-server.js" # 3. 이후 서버 실행 시 npm start만 입력하면 된다.
Shell
복사

클라이언트 실행

Client/index.html 을 웹 브라우저에서 실행하거나, 특정 포트로 실행하고 싶다면 vercel의 serve 이용한다.
npx serve -l 포트번호 client/
Shell
복사

내 코드 1 : 요청 body에서 문자열 선언

const http = require('http'); const PORT = 4999; const ip = 'localhost'; const server = http.createServer((request, response) => { // CORS 관련 헤더를 OPTIONS 응답에 적용 // Method가 OPTIONS인지 분기 if (request.method === 'OPTIONS') { response.writeHead(200, defaultCorsHeader); response.end(); } // Method가 POST라면 url 확인 후 알맞은 요청을 보내주기 if (request.method === 'POST') { // Method가 POST고 url이 /lower라면 if(request.url === '/lower') { // 빈 문자열 선언 let data = ''; request.on('data', chunk => { data = data + chunk; }); request.on('end', () => { data = data.toLowerCase(); // 소문자로 된 응답을 돌려주기 response.writeHead(201, defaultCorsHeader); response.end(data); }); // Method가 POST고 url이 /upper라면 } else if (request.url === '/upper') { let data = ''; request.on('data', chunk => { data = data + chunk; }); request.on('end', () => { data = data.toUpperCase(); // 대문자로 된 응답을 돌려주기 response.writeHead(201, defaultCorsHeader); response.end(data); }); // 위 두 가지 경우 모두 아니라면 } else { // 에러로 응답하기 response.writeHead(404, defaultCorsHeader); response.end(); } } }); 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 };
JavaScript
복사

내 코드 2 : 요청 body에서 배열 선언

const http = require('http'); const PORT = 4999; const ip = 'localhost'; const server = http.createServer((request, response) => { // CORS 관련 헤더를 OPTIONS 응답에 적용 // Method가 OPTIONS인지 분기 if (request.method === 'OPTIONS') { // 클라이언트의 preflight request에 대한 응답 response.writeHead(200, defaultCorsHeader); response.end(); } // Method가 POST라면 url 확인 후 알맞은 요청을 보내주기 if (request.method === 'POST') { // PUT request body(payload) ------------------ // 빈 배열로 선언 let body = []; request // 'data'에 이벤트 리스너 등록해 데이터 받기 .on('data', (chunk) => { // body 배열에 chunk를 담기 body.push(chunk); }) // 'end'에 이벤트 리스너 등록해 데이터 받기 .on('end', () => { // 'data' 이벤트에서 발생시킨 청크 Buffer(문자열 데이터)를 배열에 수집 후 // end 이벤트에서 이어 붙이고 문자열로 만들기 body = Buffer.concat(body).toString(); response.writeHead(201, defaultCorsHeader); // Method가 POST고 url이 /lower라면 if (request.url === '/lower') { // 소문자로 된 응답을 돌려주기 response.end(body.toLowerCase()); // Method가 POST고 url이 /upper라면 } else if (request.url === '/upper') { // 대문자로 된 응답을 돌려주기 response.end(body.toUpperCase()); // 위 두 가지 경우 모두 아니라면 } else { // 에러로 처리할 것 response.writeHead(404, defaultCorsHeader); response.end(); } }); } }); 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, };
JavaScript
복사

결과 화면

대문자를 입력하면 소문자로, 소문자를 입력하면 대문자로 나와야 하며, 개발자 도구에서도 에러 없이 잘 띄워지면 성공이다.

배운 점

처음에는 HTTP 트랜잭션 해부에 나와있는 대로 배열을 선언하는 방법을 사용했는데, 이유는 모르겠지만 메소드도 안 뜨고 에러가 떠서 문자열을 선언하는 방법으로 변경해 시도했더니 성공했다.
다 끝내놓고 원인을 알았는데, nodemon을 설치하면 처음부터 서버 실행을 따로 안해도 되는 줄 알았던 것이다. nodemon을 설치한 이유는 코드를 수정할 때마다 node server/basic-server.js로 서버를 실행하지 않아도 되고, 처음에 npm start만 입력해도 코드 수정과 동시에 서버를 실행할 수 있다는 것이었다.
코드는 다 써놓고 서버 실행 방법에 익숙하지 않아 날려버린건 매우 안타까웠던 일... 하지만 결과적으로는 코드 한 줄 한 줄 더 자세히 뜯어보고, HTTP 트랜잭션 해부 가이드도 더 자세히 읽어보고, 두 가지 방법을 사용하면서 이해가 잘 되었다. 오늘의 시행착오가 결코 헛되지 않았다.

 참고 자료