1. URL 구조
https://www.example.com:80/path/to/index.html?key1=value1#hash
1) http - protocol = 프로토콜
2) www.example.com - honstname = 도메인명
3) 80 - port = 포트 번호
4) path/to/index.html - pathname = 웹 서버 자원에 대한 경로
5) ?key1=value1 - query = 웹 서버에서 제공하는 추가 매개변수
6) #hash - hash = 일종의 북마크(서버에 전송하지 않음)
2. 라우팅
: URL 경로에 따라 다른 응답을 주는 기능
3. 라우팅 요청 처리하는 서버 예시
// 명령어 실행
node app.js
const http = require("http");
const url = require("url");
http
.createServer((req, res) => {
const path = url.parse(req.url, true).pathname; // url 모듈을 사용해 요청(req)으로 받은 url의 pathname을 얻어냄
res.setHeader("Content-Type", "text/html; charset=utf-8"); // 응답 헤더 설정
if (path === "/test") {
res.end("<h1>Hello World Test</h1>");
} else if (path === "/hello") {
res.end("<h1>Hello World Hello</h1>");
} else {
res.statusCode = 404;
res.end("404 Page not found");
}
})
.listen(3000, () => {
console.log("Server is running on http://localhost:3000");
});
* 쿼리스트링 : HTTP 요청을 보낼 때 사용자가 원하는 값을 보내는 방식, 경로값 뒤에 ?를 붙인 다음 key=value 형식으로 사용 가능하다. 여러 개일 경우 &로 구분해 추가해줌
4. createServer()
: 위처럼 하면 createServer()안에서 직접 컨트롤 하게 되는데 모든 코드를 다추가해야 하므로 좋지 않다.
아래와 같이 밖으로 뺴줄 수 있다.
const http = require("http");
const url = require("url");
http
.createServer((req, res) => {
const path = url.parse(req.url, true).pathname; // url 모듈을 사용해 요청(req)으로 받은 url의 pathname을 얻어냄
res.setHeader("Content-Type", "text/html", "charset=UTF-8");
if (path === "/user") {
user(req, res);
} else if (path === "/board") {
board(req, res);
} else {
notFound(req, res);
}
})
.listen("3000", () => {
console.log("Server is running on http://localhost:3000");
});
const user = (req, res) => {
res.end(`[user] name : andy, age: '30`);
};
const board = (req, res) => {
res.end(`[board] title : hello, hit: 100`);
};
const notFound = (req, res) => {
res.statusCode = 404;
res.end("404 Page not found");
};
5. 동적으로 응답하기
: 위에서 만든 user() 함수를 수정해서 매개변수에 따라 동적으로 응답이 변경되도록 해본다.
const http = require("http");
const url = require("url");
http
.createServer((req, res) => {
const path = url.parse(req.url, true).pathname; // url 紐⑤뱢?쓣 ?궗?슜?빐 ?슂泥?(req)?쑝濡? 諛쏆?? url?쓽 pathname?쓣 ?뼸?뼱?깂
res.setHeader("Content-Type", "text/html", "charset=UTF-8");
if (path === "/user") {
user(req, res);
} else if (path === "/board") {
board(req, res);
} else {
notFound(req, res);
}
})
.listen("3000", () => {
console.log("Server is running on http://localhost:3000");
});
const user = (req, res) => {
const userInfo = url.parse(req.url, true).query; // 쿼리 스트링을 통해 동적으로 데이터를 받아옴
res.end(`[user] name : ${userInfo.name}, age: ${userInfo.age}`);
};
const board = (req, res) => {
res.end(`[board] title : hello, hit: 100`);
};
const notFound = (req, res) => {
res.statusCode = 404;
res.end("페이지를 찾을 수 없습니다.");
};
6. 라우터 리팩토링하기
: 현재 분기문에서 모든 요청을 분석하지만 라우터 경로가 늘어나면 가독성이 심하게 떨어진다.
맵을 사용해서 분기문을 더 깔끔하게 할 수 있다.
const http = require("http");
const url = require("url");
http
.createServer((req, res) => {
const path = url.parse(req.url, true).pathname;
res.setHeader("Content-Type", "text/html", "charset=UTF-8");
if (path in urlMap) {
urlMap[path](req, res);
} else {
notFound(req, res);
}
})
.listen("3001", () => console.log("하이요"));
const user = (req, res) => {
res.end(`<h1>hello user</h1>`);
};
const board = (req, res) => {
res.end(`<h1>hello board</h1>`);
};
const notFound = (req, res) => {
res.end("404 not found");
};
// 라우터 규칭 매핑 키로 path가 들어가고 값에 함수를 할당함
const urlMap = {
"/": (req, res) => res.end("HOME"),
"/user": user,
"/board": board,
};
* 자바스크립트에서는 함수는 일급 객체다. 즉 값으로 할당이 가능하고 함수의 결과로 반환받을 수도 있다.
* 호이스팅 : 함수, 클래스 ,변수를 끌어올려서 선언되기 전에 사용하도록 하는 기능
7. express 사용하기
* 일반적으로 웹 서버가 제공하는 기능
1) 라우팅 : URL 요청을 함수와 매핑시켜주는 기능
2) 정적 파일 서비스 : CSS, JS , 이미지 등의 정적인 파일을 다루는 기능
3) 템플릿 엔진 : 동적인 웹페이지를 HTML과 인스턴스를 사용해 생성하는 기능
4) 요청 데이터 다루기 : HTTP 요청을 추상화해 편리하게 다룰 수 있게 하는 기능
5) 응답 데이터 다루기 : HTTP 응답을 커스터마이징 할 수 있는 기능, 파일 내려받기, 이미지 출력 등
6) 파일 업로드 : HTTP로 전송된 파일을 읽고 다룰 수 있는 기능
7) 쿠키 및 세션 지원 : 클라이언트 측 혹은 서버 측의 메모리에 일정 기간 동안 저장해야 하는 데이터를 다루는 기능
8) 리다이렉트 : 서버의 응답 시 다른 페이지로 전달 시키는 기능
9) 에러 페이지 : 요청이 잘못되었거나, 서버 에러 시 특정 에러 페이지를 보여주기
10) 미들웨어 : 요청 혹은 응답 사이에 공통된 기능을 추가하는 기능
npm install express
const express = require("express"); // express 모듈 불러오기
const app = express(); // express를 초기화 한 후 app에 할ㄷㅇ
const port = 3000;
app.get("/", (req, res) => {
res.set({ "Content-Type": "text/html; charset=utf-8" });
res.end("Hello express");
});
app.listen(port, () => {
console.log(`START SERVER : ${port}`);
});
8. route 코드를 익스프레스로 구현
const url = require("url");
const express = require("express");
const app = express();
const port = 3000;
app.listen(port,() => {
console.log("Express routing");
});
app.get("/", (_,res) => res.end("HOME"));
app.get("/user" , user);
app.get("/board", board);
function user(req, res) {
const user = url.parse(req.url, true).query;
// 결괏값으로 유저명과 나이 제공
res.json(`[user] name : ${user.name}, age: ${user.age}`);
}
function board(_,res){
res.json(`<h1> hello board</h1>`);
}
9. 간단한 게시판 API 만들어보기 (DB 연동 X)
const express = require("express");
const app = express();
let posts =[]; // 게시글 리스트로 담을 배열 선언
// 1. req.body를 사용하기 위한 express.json() 미들웨어 사용
app.use(express.json());
// 2. POST 요청 시 컨텐트 타입이 application/x-www-form-urlencoded인 경우 파싱
// POST 요청 대부분 content-type이 application/x-www-form-urlendcoded인 경우가 많음
// application/x-www-form-urlendcoded = body가 키=값&키2=값2 같은 키=값 조합 데이터
app.use(express.urlencoded({extended: true}));
// 3. GET 요청이 올 때 posts (게시글 리스트)를 보여줌
app.get("/", (req,res) => {
res.json(posts);
});
// 4. 기존 posts에 새 게시글 추가하는 POST 요청
app.post("/posts" , (req,res) => {
const {title, name, text} = req.body;
// 새로운 게시글을 기존 게시글 리스트에 추가
posts.push({id: posts.length + 1, title, name, text, createdAt: Date()});
res.json({ title, name , text });
});
// 5. 게시글 삭제 API
app.delete("/posts/:id", (req,res) => {
const id = req.params.id; // app.delete에 설정한 path 정보에서 id 값 가져옴
const filteredPosts = posts.filter((post) => post.id !== +id); // 삭제 로직
const isLengthChanged = posts.length !== filteredPosts.length; // 삭제 확인
posts = filteredPosts;
if(isLengthChanged) {
res.json("OK");
return;
}
res.json("NoTT changed");
});
// 6. 서버 실행
app.listen(3000, () => {
console.log("hello post word");
});
* const { title, name, text } = req.body;
body에 있는 title=타이들&name=이름 등을 객체로 바꿔서 req.body에 추가해준다.
* +id => 문자열인 id를 숫자형으로 바꿔준다는 뜻
10. 게시판 API 테스트하기
: 브라우저에서만 테스트하기 어려움
: curl을 사용하면 쉽게 테스트 가능
curl -X GET http://localhost:3000
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "title=제목1&name=hello&text=hello" http://localhost:3000/posts
=> 여기서 -d란 POST 통신 시 body 데이터를 뜻함
: curl -X DELETE localhost:3000/posts/2
11. 정리
1) RESTful API = REST 구조를 사용하는 API (POST, GET, DELETE, PUT)
2) charset = 컴퓨터에서 문자를 표현하는데 사용하는 각 문자를 표에 대응시켜 놓은 체계 , 한글은 utf-8
3) 일급 객체: 값으로 취급할 수 있는 객체
4) 라우터 : 네트워크에서 패킷의 위치를 찾고, 경로를 찾아주는 장비의 의미로 많이 쓰인다.
5) 미들웨어 : express에서 미들웨어는 HTTP 요청과 응답 사이에 함수를 추가하여 새로운 기능을 추가하는 것을 뜻함
'BackEnd Skils' 카테고리의 다른 글
백엔드 입문 (4) - NoSQL DB 알아보기 - 몽고디비 (0) | 2024.12.03 |
---|---|
백엔드 입문 (3) - npm 과 yarn 패키지 (0) | 2024.12.01 |
백엔드 입문 (1) - Node.js로 백엔드 시작해보기 (1) | 2024.11.27 |
백엔드 사전 지식 (3) - 자바스크립트 생태계 (1) | 2024.11.26 |
백엔드 사전 지식 (2) - 백엔드 배포 방법부터 클라우드 서비스까지 (0) | 2024.11.26 |