서버 실행시키는 방법
터미널에 node 파일명.js => 서버실행 => 브라우저로 localhost:3000 접속
1. OK를 반환하는 서버
-모든 접속에 "OK"로 답하는 서버 만들기
const http = require("http");
const server = http.createServer((req, res) => {
res.setHeader("Content-Type", "text/html");
res.end("OK");
});
server.listen("3000", () => { console.log("OK 서버 시작!")})
🙋♀️일반적인 웹서버는 URL경로에 따라 다른 응답을 주기때문에 URL의 경로를 읽어서 다른 응답을 주는 코드를 작성해보자.
2. 라우터 만들기
-라우팅 : URL경로에 따라서 다른 응답을 주는 기능.
-URL이라는 모듈을 사용하면 URL경로를 간단하게 읽어올 수 있다.
-HREF(Hypertext REFerence) : URL 구조를 간략하게 나타낸 것
https://www.example.com:80/path/to/file.html?key1=vale1#hash
프로토콜 | 도메인명 | 포트번호 | 웹서버 자원 대한 경로 |
쿼리 (추가매개변수) |
hash(북마크) 서버에 전송X |
https | www.example.com | :80 | path/to/file.html | ?key1=vale1 | #hash |
-localhost:3000/user와 localhost:3000/feed라는 두 URL이 있다고 가정하고 두 요청에 대해 다른 응답을 주는 코드를 작성
-user와 feed요청을 처리하는 서버
const http = require("http");
const url = require("url");
http.createServer((req, res) => {
//요청으로 받은 url의 pathname을 얻는다.
//parse()함수의 두번째 인수는 true는 쿼리스트링도 함께 파싱할지 여부를 설정하는 변수
const path = url.parse(req.url, true).pathname;
//한글을 쓰면 출력된 값이 깨지기 때문에 text/html에 charset=utf-8을 추가해준다.
res.setHeader("Content-Type", "text/html; charset=utf-8");
if(path === "/user"){
res.end("[user] name: andy, age: 30");
}else if(path === "/feed"){
res.end(`
<ul>
<li>picture1</li>
<li>picture2</li>
<li>picture2</li>
<ul>
`);
} else {
res.statusCode = 404;
res.end("404 page not found")
}
})
.listen("3000", () => { console.log("라우터를 만들어보자!")})
-터미널에 node 파일명.js
-결과
🙋♀️위의 코드는 요청에 대한 응답을 createServer()안에서 직접 컨트롤하는데 이 안의 콜백함수에 모든 코드를 다 추가해야 하므로 좋지 않다.
🙋♀️라우팅 이후의 처리를 별도의 함수를 만들어서 처리해보자.
3. createServer() 리팩터링하기
-메인루틴을 유지하면서도 요청별 함수만 요구사항에 맞게 변경되는 코드 작성
-라우터와 실행하는 함수코드를 나누어보기
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 === "/user"){
user(req, res);
}else if(path === "/feed"){
feed(req, res);
} else {
notFound(req, res);
}
})
.listen("3000", () => { console.log("라우터를 만들어보자!")})
//경로 요청을 처리하는 코드를 함수로 분리시킴.
const user = (req, res) => {
res.end(`[uer] name : andy, age: 30`);
}
const feed = (req, res) => {
res.end(`
<ul>
<li>picture1</li>
<li>picture2</li>
<li>picture3</li>
</ul>
`)
}
const notFound = (req, res) => {
res.statusCode = 404;
res.end("404 page not found")
}
🙋♀️해당 경로에 접속하면 언제나 같은 결과만 보여주기 때문에 매개변수에 따라 동적으로 응답이 변경되도록 쿼리를 추가해보자.
4. 동적으로 응답하기
-user()함수는 응답으로 고정된 name과 age정보를 반환했다.
-user()함수를 수정해서 매개변수에 따라 동적으로 응답이 변경되도록 수정해본다.
-url의 query부분에 name, age정보를 추가해본다.
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 === "/user"){
user(req, res);
}else if(path === "/feed"){
feed(req, res);
} else {
notFound(req, res);
}
})
.listen("3000", () => { console.log("라우터를 만들어보자!")})
const user = (req, res) => {
//쿼리스트링 데이터를 userInfo에 할당한다.
const userInfo = url.parse(req.url, true).query
//결과값으로 이름과 나이를 설정한다.
res.end(`[uer] name : ${userInfo.name}, age: ${userInfo.age}`);
}
const feed = (req, res) => {
res.end(`
<ul>
<li>picture1</li>
<li>picture2</li>
<li>picture3</li>
</ul>
`)
}
const notFound = (req, res) => {
res.statusCode = 404;
res.end("404 page not found")
}
-서버에 접속하면서 query부분에 아무런 값도 주지 않았기 때문에 undefined가 뜬다.
-url의 query에 매개변수로 name과 age를 추가해본다.
매개변수가 하나일 때 : ?키=값
매개변수가 두개 이상 일때 : ?키=값&키=값
🙋♀️위의 코드는 분기문에서 모든 요청을 분석한다. 지금은 함수가 3개뿐이지만 함수가 더 많아지면 유지보수가 매우 힘들어진다. 유지보수성을 높이기 위해 라우터를 리팩토링해본다.
5. 라우터 리팩토링하기
-분기문에 사용되는 매개변수가 같은 패턴을 보일 때는 맵 자료구조가 유용하다.
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");
//urlMap에 path가 있는지 확인한다.
if(path in urlMap){
//ulrMap에 path값으로 매핑된 함수 실행
urlMap[path](req, res);
} else {
notFound(req, res);
}
})
.listen("3000", () => { console.log("라우터를 만들어보자!")})
//경로 요청을 처리하는 코드를 함수로 분리시킴.
const user = (req, res) => {
const userInfo = url.parse(req.url, true).query
res.end(`[uer] name : ${userInfo.name}, age: ${userInfo.age}`);
}
const feed = (req, res) => {
res.end(`
<ul>
<li>picture1</li>
<li>picture2</li>
<li>picture3</li>
</ul>
`)
}
const notFound = (req, res) => {
res.statusCode = 404;
res.end("404 page not found")
}
//라우터 규칙 매핑 키로 path가 들어가고 값에 함수를 할당하였다.
const urlMap = {
"/": () => {},
"/user": user,
"/feed": feed,
}
🙋♀️위의 기본 웹서버로도 서비스가 가능하지만 기능이 많이 부족하다.
🙋♀️실전에서 사용하는 서버라면 라우터에서 HTTP메서드로 각각 요청을 받는 기능, 템플릿 엔진 기능, 미들웨어 등의 기능을 제공해야한다.
'Node.js' 카테고리의 다른 글
npm (0) | 2023.08.13 |
---|---|
익스프레스 프레임워크 사용하 (0) | 2023.08.13 |
Formdata (0) | 2023.06.29 |
브라우저-서버의 요청-응답 (0) | 2023.06.29 |
널병합 연산자 / 옵셔널 체이닝 (0) | 2023.06.29 |