Node.js 학습_http 모듈로 서버 만들기

Node.js 학습_http 모듈로 서버 만들기

728x90

반응형

# http 모듈로 서버 만들기

1. HTTP 서버 만들기

### 서버와 클라이언트

클라이언트가 서버로 요청(request)을 보냄

서버는 요청을 처리

처리 후 클라이언트로 응답(response)을 보냄.

### 노드로 http 서버 만들기

http 요청에 응답하는 노드 서버

createServer로 요청 이벤트에 대기

req 객체는 요청에 관한 정보가 / res 객체는 응답에 관한 정보가 담겨 있다.

# createServer.js const http = require('http'); http.createServer((req, res) => { // 여기에 어떻게 응답할지 작성. });

### 8080 포트 연결하기.

res 메서드로 응답 보냄 : write로 응답 내용을 적고, end로 응답 마무리(내용을 넣어도 됨)

listen(포트) 메서드로 특정 포트에 연결

8080포트 연결 후 로컬에서 http://localhost:8080/ 으로 접속하여 확인 가능.

const http = require('http'); const server = http.createServer((req, res) => { // 요청에 대한 응답 작성. (응답 거부 가능.) res.write('Hello Node!'); res.write('Hello server'); res.end('Hello Zero'); }) .listen(8080); server.on('listening', () => { console.log('8080번 포트에서 서버 대기 중입니다.'); }); server.on('error', (error) => { console.error(error); });

### localhost와 포트

localhost는 컴퓨터 내부 주소로, 외부에서는 접근 불가능

포트는 서버 내에서 프로세스를 구분하는 번호이다.

기본적으로 http 서버는 80번 포트 사용(생략 가능, https는 443)

예) www.gilbut.com:80 -> www.gilbut.com

다른 포트로 데이터베이스나 다른 서버 동시에 연결 가능함.

2. fs로 HTML 읽어 제공하기

수정 후에는 Ctrl + C 입력하여 서버를 내렸다가 node 파일명으로 다시 실행시켜줘야 정상적으로 반영 됨.

# server1.js const http = require('http'); const server = http.createServer((req, res) => { // 요청에 대한 응답 작성. (응답 거부 가능.) res.writeHead(200, { 'Content-Type' : 'text/html; charset=utf-8'}); res.write('Hello Node!'); res.write('Hello server'); res.end('Hello Zero'); }) .listen(8080); server.on('listening', () => { console.log('8080번 포트에서 서버 대기 중입니다.'); }); server.on('error', (error) => { console.error(error); });

아래와 같이 포트 추가하여 서버 2개, 3개도 돌릴수 있음

# server1.js const http = require('http'); // 8080 포트 서버 const server = http.createServer((req, res) => { // 요청에 대한 응답 작성. (응답 거부 가능.) res.writeHead(200, { 'Content-Type' : 'text/html; charset=utf-8'}); res.write('Hello Node!'); res.write('Hello server'); res.end('Hello Zero'); }) .listen(8080); server.on('listening', () => { console.log('8080번 포트에서 서버 대기 중입니다.'); }); server.on('error', (error) => { console.error(error); }); // 8081 포트 서버 const server1 = http.createServer((req, res) => { // 요청에 대한 응답 작성. (응답 거부 가능.) res.writeHead(200, { 'Content-Type' : 'text/html; charset=utf-8'}); res.write('Hello Node!'); res.write('Hello server'); res.end('Hello Zero'); }) .listen(8081);

아래와 같이 html 파일을 별도로 생성하여 연결할 수 있다.

# server2.html Node.js 웹 서버 Node.js 웹 서버 만들 준비 됨? # server2.js const http = require('http'); const fs = require('fs').promises; const server = http.createServer(async (req, res) => { res.writeHead(200, { 'Context-Type' : 'text/html; charset=utf-8' }); const data = await fs.readFile('./server2.html'); res.end(data); }) .listen(8080); server.on('listenig', () => { console.log('8080번 포트에서 서버 대기 중.'); }); server.on('error', (error) => { console.log(error); });

3. REST API 서버 만들기 / POST, PUT, DELETE 요청 보내기

서버에 요청을 보낼 때는 주소를 통해 요청의 내용을 표현.

/index.html이면 index.html을 보내달라는 뜻. 항상 html 요구할 필요는 없음 서버가 이해하기 쉬운 주소가 좋음

REST API (Represenational State Transfer)

서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법 /user이면 사용자 정보에 관한 정보를 요청하는 것 /post면 게시글에 관련된 자원을 요청하는 것

HTTP 요청 메서드

GET : 서버 자원을 가져오라고 할 때 사용 POST : 서버에 새로 등록하고자 할 때 사용(또는 뭘 써야할 지 애매할 때) PUT : 서버의 자원을 요청에 들어있는 자원으로 치환하고자 할 때 사용 (전체 수정) PATCH : 서버 자원의 일부만 수정하고자 할 때 사용 (부분 수정) DELETE : 서버의 자원을 삭제하고 할 때 사용

### HTTP 프로토콜

클라이언트가 누구든 서버와 HTTP 프로토콜로 소통 가능

IOS, 안드로이드, 웹이 모두 같은 주소로 요청 보낼 수 있음 서버와 클라이언트의 분리

RESTful

REST API를 사용한 주소 체계를 이용하는 서버 GET /user는 사용자를 조회하는 요청, POST / user는 사용자를 등록하는 요청

### REST API 서버 만들기

restServer.js

const http = require('http'); const fs = require('fs').promises; const users = {}; // 데이터 저장용 http.createServer(async (req, res) => { try { if (req.method === 'GET') { if (req.url === '/') { const data = await fs.readFile('./restFront.html'); res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(data); } else if (req.url === '/about') { const data = await fs.readFile('./about.html'); res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); return res.end(data); } else if (req.url === '/users') { res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); return res.end(JSON.stringify(users)); } // /도 /about도 /users도 아니면 try { const data = await fs.readFile(`.${req.url}`); return res.end(data); } catch (err) { // 주소에 해당하는 라우트를 못 찾았다는 404 Not Found error 발생 } } else if (req.method === 'POST') { if (req.url === '/user') { let body = ''; // 요청의 body를 stream 형식으로 받음 req.on('data', (data) => { body += data; }); // 요청의 body를 다 받은 후 실행됨 return req.on('end', () => { console.log('POST 본문(Body):', body); const { name } = JSON.parse(body); const id = Date.now(); users[id] = name; res.writeHead(201, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end('ok'); }); } } else if (req.method === 'PUT') { if (req.url.startsWith('/user/')) { const key = req.url.split('/')[2]; let body = ''; req.on('data', (data) => { body += data; }); return req.on('end', () => { console.log('PUT 본문(Body):', body); users[key] = JSON.parse(body).name; res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); return res.end('ok'); }); } } else if (req.method === 'DELETE') { if (req.url.startsWith('/user/')) { const key = req.url.split('/')[2]; delete users[key]; res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); return res.end('ok'); } } res.writeHead(404); return res.end('NOT FOUND'); } catch (err) { console.error(err); res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end(err.message); } }) .listen(8082, () => { console.log('8082번 포트에서 서버 대기 중입니다'); });

restFront.js

async function getUser() { // 로딩 시 사용자 가져오는 함수 try { const res = await axios.get('/users'); const users = res.data; const list = document.getElementById('list'); list.innerHTML = ''; // 사용자마다 반복적으로 화면 표시 및 이벤트 연결 Object.keys(users).map(function (key) { const userDiv = document.createElement('div'); const span = document.createElement('span'); span.textContent = users[key]; const edit = document.createElement('button'); edit.textContent = '수정'; edit.addEventListener('click', async () => { // 수정 버튼 클릭 const name = prompt('바꿀 이름을 입력하세요'); if (!name) { return alert('이름을 반드시 입력하셔야 합니다'); } try { await axios.put('/user/' + key, { name }); getUser(); } catch (err) { console.error(err); } }); const remove = document.createElement('button'); remove.textContent = '삭제'; remove.addEventListener('click', async () => { // 삭제 버튼 클릭 try { await axios.delete('/user/' + key); getUser(); } catch (err) { console.error(err); } }); userDiv.appendChild(span); userDiv.appendChild(edit); userDiv.appendChild(remove); list.appendChild(userDiv); console.log(res.data); }); } catch (err) { console.error(err); } } window.onload = getUser; // 화면 로딩 시 getUser 호출 // 폼 제출(submit) 시 실행 document.getElementById('form').addEventListener('submit', async (e) => { e.preventDefault(); const name = e.target.username.value; if (!name) { return alert('이름을 입력하세요'); } try { await axios.post('/user', { name }); getUser(); } catch (err) { console.error(err); } e.target.username.value = ''; });

restFront.html

RESTful SERVER Home About 등록

about.html

RESTful SERVER Home About 소개 페이지입니다. 사용자 이름을 등록하세요!

4. 쿠키 이해하기

728x90

반응형

from http://dlagusgh1.tistory.com/837 by ccl(A) rewrite - 2021-10-04 14:01:10