on
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