[TIL] 엘리스 SW 엔지니어 트랙 Day 029
글 작성자: 망고좋아
반응형
📖 오늘 배운 내용 - 2021.12.02
- 시맨틱 버전 규칙
- 라우터
- 미들웨어
- .env
- REST API
📝 시맨틱 버전 규칙
- 패치 버전 Z : 하위 호환을 하지만 버그 수정이 있을 때 올라간다. 버그 수정은 내부적으로 잘못 처리되고 있는 것을 고치는 것을 의미한다.
- 작은 버전 Y : 새로운 기능이 추가되었지만 기존의 공개 API가 하위 호환되고 있을 때 올라간다. 이는 패치 수준의 변화를 포함할 수 있으나, 작은 버전이 올라가면 패치 버전은 꼭 0이 되어야 한다.
- 주요 버전 X : 하위 호환되지 않는 변화가 추가될 때 반드시 올라가야 한다. 이는 패치 수준과 작은 수준의 변화를 포함할 수 있으나, 주요 버전이 올라가면 작은 버전과 패치 버전은 꼭 0이 되어야 한다.
📝 라우터란?
- 하나의 페이지를 만들기 위해서
app.get()
을 사용했다. - 만약에 배민을 웹 버전으로 출시한다면 필요한 페이지로는 회원가입, 가게 목록, 가게 정보, 이벤트 목록, 결제, 프로필, 리뷰 등 많다. 이 많은 페이지를 app.js에 app.get으로 한 파일에 넣기엔 무리다.
- app.js에 라우터를 만들고 라우터 파일을 연결해 준다. ⇒ 구조적으로 짤 수 있다.
- 예를 들면 가게 관련 따로, 프로필 따로 등등 나눠준다.
- Route는 해석하면
길
이다. 즉, 라우터는 어느 페이지로 보낼지 결정해 준다.
const express = require("express");
const path = require("path");
// routes에 있는 index.js 가져오기
const index = require("./routes/index");
const app = express();
const port = 9999;
// http:localhost:9999/
app.get("/", (req, res) => {
res.send("hello");
});
// http:localhost:9999/hello
app.get("/hello", (req, res) => {
// 파일 보내기
//path.join()는 2개 서로 다른 경로를 합쳐준다.
res.sendFile(path.join(__dirname, "./static/index.html"));
});
app.listen(port, () => {
console.log(`${port}번 포트에서 서버가 돌아가고 있어요!`);
});
📝 라우팅 해보기
🛠 app.js
const express = require("express");
const path = require("path");
// reoutes에 있는 index.js 가져오기
const index = require("./routes/index");
const app = express();
const port = 9999;
// routes의 index 연결
app.use("/routes", index);
app.listen(port, () => {
console.log(`${port}번 포트에서 서버가 돌아가고 있어요!`);
});
🛠 /routes/index.js
const express = require("express");
// ** router로 생성
const router = express.Router();
// app이 아닌 router
router.get("/", (req, res) => {
res.send("안녕!");
});
// 다른 파일에서 index.js을 사용하기 위해 exports로 빼주기
module.exports = router;
📕 값 넣어서 넘겨주기
const express = require("express");
// ** router로 생성
const router = express.Router();
// app이 아닌 router
router.get("/", (req, res) => {
res.send("안녕!");
});
// 동적으로 값 넣어주기
router.get("/is_odd_1/:id", (req, res) => {
const id = parseInt(req.params.id); // id 값 가져오기
if (isNaN(id)) res.send("아 숫자만 넣으라고 --;;");
else if (id % 2 === 0) res.send(`${id}는 짝수에요!`);
else res.send(`${id}는 홀수에요!`);
});
// 다른 파일에서 index.js을 사용하기 위해 exports로 빼주기
module.exports = router;
- /search/(:numver)/:(option1)/:(option2) ⇒ 이렇게 웹사이트를 설계하는 것은 너무 지저분하다!! ⇒ form태그의 method를 활용하자!
📕 값 넣어서 넘겨주기 리팩토링
const express = require("express");
const path = require("path");
// ** router로 생성
const router = express.Router();
// app이 아닌 router
router.get("/", (req, res) => {
res.send("안녕!");
});
// 동적으로 값 넣어주기
router.get("/is_odd_1/:id", (req, res) => {
const id = parseInt(req.params.id);
if (isNaN(id)) res.send("아 숫자만 넣으라고 --;;");
else if (id % 2 === 0) res.send(`${id}는 짝수에요!`);
else res.send(`${id}는 홀수에요!`);
});
router.get("/is_odd_2_page", (req, res) => {
res.sendFile(path.join(__dirname, "../static/get_test.html"));
});
router.get("/is_odd_2", (req, res) => {
// params가 query로 바뀜
// number는 form태그 안에 있는 name값이 number, query string는 form 태그로 보낸 데이터를 자동으로 받아옴
const id = parseInt(req.query.number);
// http://localhost:9999/routes/is_odd_2?number=23 이렇게 주소 전달 된다.
if (isNaN(id)) res.send("아 숫자만 넣으라고 --;;");
else if (id % 2 === 0) res.send(`${id}는 짝수에요!`);
else res.send(`${id}는 홀수에요!`);
});
// 다른 파일에서 index.js을 사용하기 위해 exports로 빼주기
module.exports = router;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>테스트</title>
<body>
<form action="/routes/is_odd_2" method="get">
숫자 : <input type="text" name="number" /><br />
<input type="submit" />
</form>
</body>
</html>
- 입력하면 이렇게 주소가 이동된다. ⇒
http://localhost:9999/routes/is_odd_2?number=10
- 매개변수 : 서버에 요청하는 추가적인 데이터로, 키와 값으로 구분됨
- 매개변수가 2개 이상이 넘어오면
&
로 구분한다.
📝 .env
- 환경변수 파일
npm i dotenv
로 설치const dotenv = require("dotenv");
dotenv.config();
const express = require("express");
const dotenv = require("dotenv"); // env
const index = require("./routes/index");
const app = express();
dotenv.config(); // env
// app.set -> 환경설정을 저장할 수 있음.
// app.set("이름", 값)
// process -> Node.js 내장 객체
// dotenv -> process.env에 .env 파일에 있는 값을 다 넣음.
// .env 파일 없음 -> ? process.env.PORT => undefined
// .env 파일이 있으면 거기에 있는 PORT를 쓰고, 없으면 9999로 함.
app.set("port", process.env.PORT || 9999);
app.use("/routes/", index);
app.listen(app.get("port"), () => {
console.log(`${app.get("port")}번 포트에서 서버가 돌아가고 있어요!`);
});
- 이렇게 env파일로 따로 관리하지만 결국엔 env 파일을 수정하면 문제 반복 아닌가요?!
gitignore
을 사용하자. 포트번호는 각자 알아서 쓰고 env파일만 gitignore 해줘서 커밋하자.
- gitignore.io : 프로젝트에서 사용하는 환경에 맞게 gitignore을 자동으로 생성해준다.
📝 미들웨어
- router.get.은 목적지와 함수로 이루어져 있다.
- 미들웨어란 클라이언트에서 요청을 받아 그 요청을 처리하는 과정에서 거치는 모든 함수들이다.
- express.js에서는 미들웨어를 순차적으로 처리할 수 있다.
- 즉, 요청과 응답 사이에서 추가적인 구현을 해주는 것이 미들웨어이다.
router.use(func1);
router.get("/", (req, res) => {
res.send("/");
});
router.get("/test", (req, res, next) => {
res.send("/test");
next();
});
router.use(func2);
next()
란 다음으로 넘긴다는 말이다. ⇒그래서 다음에 뭔데?! ⇒ next가 있으면 다음까지 오케이, 없으면 여기서 끝!
📕 미들웨어를 사용하는 이유?
- 그냥 미들웨어를 밖에서 빼서 따로 쓰는 이유는? 그냥 router.get()으로 사용해도 되지 않나요? ⇒ 아니다. 미들웨어를 유용한 상황이 있다. ⇒ 역할의 구분!!!!
- 예를 들면 쇼핑몰에 내 주문 선물함 등 보려면 일단 로그인을 해야 하니까 로그인이라는 미들웨어를 만들고 그 아래에 라우터들을 구현하면 한번 로그인 되면 그 아래 라우터들이 실행시킬 수 있다. ⇒ 이런 목적으로 미들웨어를 사용한다.
📝 미들웨어 예제
🛠 app.js
const express = require("express");
const dotenv = require("dotenv"); // env
// reoutes에 있는 index.js 가져오기
const index = require("./routes/index");
// 미들웨어 연결
const middleware_test = require("./routes/middleware_test");
const rest_api = require("./routes/rest_api_practice");
const kakao = require("./routes/kakao");
const app = express();
dotenv.config(); // env
// app.set -> 환경설정을 저장할 수 있음.
// app.set("이름", 값)
// process -> Node.js 내장 객체
// dotenv -> process.env에 .env 파일에 있는 값을 다 넣음.
// .env 파일 없으면? -> process.env.PORT => undefined
// .env 파일이 있으면 거기에 있는 PORT를 쓰고, 없으면 9999로 함. => process.env.PORT || 9999
app.set("port", process.env.PORT || 9999);
app.use("/routes/", index);
app.use("/middleware", middleware_test);
app.use("/restapi", rest_api);
app.use("/kakao", kakao);
app.listen(app.get("port"), () => {
console.log(`${app.get("port")}번 포트에서 서버가 돌아가고 있어요!`);
});
🛠 /routes/middleware_test.js
const express = require("express");
const router = express.Router();
const func1 = (req, res, next) => {
console.log("무조건 거쳐가야 해요!");
next(); // 2. 왔더니 next가 있어서 다음 미들웨어가 실행 되어야 한다.
};
const func2 = (req, res) => {
console.log("이건 뜰까요?"); // 5. 출력
};
// use는 여기에 도달하면 해당 미들웨어를 실행한다!!
router.use(func1); // 1. 여기를 먼저 도착, 조건 없이 실행
// 해당 조건을 충족하면 실행
router.get("/", (req, res) => {
res.send("/"); // 3. 조건을 충족해서 코드가 실행되고 그 후 next가 없어서 여기서 종료
});
// 해당 조건을 충족하면 실행
router.get("/test", (req, res, next) => {
res.send("/test");
next(); // 3. 조건을 충족해서 코드가 실행되고 다음 미들웨어가 실행 되어야 한다.
});
// use는 여기에 도달하면 해당 미들웨어를 실행한다!!
router.use(func2); // 4. /middleware/test로 들어오면 위 next가 실행되어서 실행
module.exports = router;
🛠 /routes/index.js
const express = require("express");
const path = require("path");
// ** router로 생성
const router = express.Router();
// app이 아닌 router
router.get("/", (req, res) => {
res.send("안녕!");
});
// 동적으로 값 넣어주기
router.get("/is_odd_1/:id", (req, res) => {
const id = parseInt(req.params.id);
if (isNaN(id)) res.send("아 숫자만 넣으라고 --;;");
else if (id % 2 === 0) res.send(`${id}는 짝수에요!`);
else res.send(`${id}는 홀수에요!`);
});
router.get("/is_odd_2_page", (req, res) => {
res.sendFile(path.join(__dirname, "../static/get_test.html"));
});
router.get("/is_odd_2", (req, res) => {
// params가 query로 바뀜
// number는 form태그 안에 있는 name값이 number, query string는 form 태그로 보낸 데이터를 자동으로 받아옴
const id = parseInt(req.query.number);
// http://localhost:9999/routes/is_odd_2?number=23 이렇게 주소 전달 된다.
if (isNaN(id)) res.send("아 숫자만 넣으라고 --;;");
else if (id % 2 === 0) res.send(`${id}는 짝수에요!`);
else res.send(`${id}는 홀수에요!`);
});
// 다른 파일에서 index.js을 사용하기 위해 exports로 빼주기
module.exports = router;
📝 API
- 응용 프로그램 프로그래밍 인터페이스
- 인터페이스가 뭐냐? 사용자가 기기. 프로그램을 쉽게 동작시키기 위해 도움을 주는 것
- 프로그램을 만들 때 도움을 주는 something
- 즉, 내부 동작 과정을 몰라도 api를 통해 응용 프로그램 개발이 가능하다.
📝REST API란?
- API지만, 웹을 통해 원하는 요청을 보내고, 그 요청을 받는 것!
- 실제 클라이언트는 url로 리퀘스트 요청을 보낸다.
- 그러면 서버는 http 상태 코드와 함께 결괏값을 보낸다.
- http 코드를 체크하고 적절한 데이터 가공을 처리한다.
📕 GET - 읽을 때 사용
- 주로 데이터를 읽거나, 검색할 때 사용하는 메서드
- http명세에 의하면 get요청은 데이터를 읽을 때만 사용되어야 되고 수정될 때는 사용하지 않아야 한다.
📕 POST - 생성할 때 사용
- 주로 새로운 리소스를 생성할 때 사용된다. (성공 시 201 return)
- 일반적으로 get은 유알엘에 모든 정보를 담는데 비해, POST는 HTML Body나 JSON으로 전달한다.
📕 JSON
- 일반적으로 서버와 클라이언트로 데이터를 보낼 때 사용하는 방식
- 기존에 사용했던 xml방식에 의해 더 사용하기 쉬워 널리 사용됨
📝REST API 사용 예제
🛠 app.js
const express = require("express");
const dotenv = require("dotenv"); // env
// reoutes에 있는 index.js 가져오기
const index = require("./routes/index");
// 미들웨어 연결
const middleware_test = require("./routes/middleware_test");
const rest_api = require("./routes/rest_api_practice");
const kakao = require("./routes/kakao");
const app = express();
dotenv.config(); // env
// app.set -> 환경설정을 저장할 수 있음.
// app.set("이름", 값)
// process -> Node.js 내장 객체
// dotenv -> process.env에 .env 파일에 있는 값을 다 넣음.
// .env 파일 없으면? -> process.env.PORT => undefined
// .env 파일이 있으면 거기에 있는 PORT를 쓰고, 없으면 9999로 함. => process.env.PORT || 9999
app.set("port", process.env.PORT || 9999);
app.use("/routes/", index);
app.use("/middleware", middleware_test);
app.use("/restapi", rest_api);
app.use("/kakao", kakao);
app.listen(app.get("port"), () => {
console.log(`${app.get("port")}번 포트에서 서버가 돌아가고 있어요!`);
});
🛠 /routes/rest_api_practice.js
const express = require("express");
const router = express.Router();
// 사용법 찾아보기 express.json() 이게 뭔지
router.use(express.json()); // 이 페이지에 들어가 있는 내용들은 json 형식으로 통신할 수 있다.
const users = [
{ id: 1, username: "kim" },
{ id: 2, username: "lee" },
{ id: 3, username: "park" },
];
router.get("/", (req, res) => {
res.json(users); // send가 아닌 json!
});
/*
const data = {
id: 123,
username: "jam"
};
-> username 꺼낼 때 => data.username
*/
// 주소가 똑같아도 get post가 다르면 다르게 인식한다.
router.post("/", (req, res) => {
//클라이언트 측에서 요청을 보냄
//요청을 까봐야겠다!
// 일반적으로 id는 서로 다르게 하는게 좋다. => 시간을 넣어준다. => nodejs는 싱글쓰레드라서 동시에 요청을 처리할 수 없어서 같은 시간이 나올 수 없다.
// 만약에 이미 똑같은 유저가 있다거나, 권한이 없다거나, username이 없거나에 대해서 에러 코드를 넣어보자!
// try catch를 사용하자
try {
const req_data = req.body; // 자바스크립트 객체를 들고 왔다.
if (!req_data.username) {
return res.status(400).end(); // username이 올바르지 않으면 상태코드를 400으로 설정하고 end!
}
const user_data = {
id: Date.now(),
username: req_data.username,
};
users.push(user_data);
res.json(user_data); // 요청이 있다면 항상 응답이 있어야 한다. 데이터가 잘 들어갔는지 확인하기, 반환값 넣어주기
} catch (err) {
console.log(err);
return res.status(500).end();
}
});
module.exports = router;
📝 KAKAO API 사용해보기
🛠 app.js
const express = require("express");
const dotenv = require("dotenv"); // env
// reoutes에 있는 index.js 가져오기
const index = require("./routes/index");
// 미들웨어 연결
const middleware_test = require("./routes/middleware_test");
const rest_api = require("./routes/rest_api_practice");
const kakao = require("./routes/kakao");
const app = express();
dotenv.config(); // env
// app.set -> 환경설정을 저장할 수 있음.
// app.set("이름", 값)
// process -> Node.js 내장 객체
// dotenv -> process.env에 .env 파일에 있는 값을 다 넣음.
// .env 파일 없으면? -> process.env.PORT => undefined
// .env 파일이 있으면 거기에 있는 PORT를 쓰고, 없으면 9999로 함. => process.env.PORT || 9999
app.set("port", process.env.PORT || 9999);
app.use("/routes/", index);
app.use("/middleware", middleware_test);
app.use("/restapi", rest_api);
app.use("/kakao", kakao);
app.listen(app.get("port"), () => {
console.log(`${app.get("port")}번 포트에서 서버가 돌아가고 있어요!`);
});
🛠 /routeskakao.js
const express = require("express");
const axios = require("axios");
const router = express.Router();
// dotenv를 링크 안 해도 되는 이유는? app.js에서 코드가 합쳐지면서 kakao,js에서도 dotenv를 사용할 수 있다.
router.get("/search", (req, res) => {
const search = req.query.search;
axios
.get("https://dapi.kakao.com/v2/search/web", {
headers: {
Authorization: `KakaoAK ${process.env.KAKAO_REST_API_KEY}`,
},
params: {
query: search,
},
})
.then((result) => {
const titles = [];
for (let idx in result.data.documents) {
titles.push(result.data.documents[idx].title);
}
res.json(titles);
})
.catch((err) => console.log(err));
});
module.exports = router;
💡 오늘 깨달은 것
- 라우터는 역할의 구분이다.
- api 서버를 만들면 api 명세서를 만들어야 한다. 그래야 백이랑 프론트랑 소통이 가능하다.
- 프로젝트 시작 시 제일 먼저 해야 될 거는 api 규약 확정. ⇒ Swagger
📌 참고
반응형
'프로그래밍 > Today I Learned' 카테고리의 다른 글
[TIL] 엘리스 SW 엔지니어 트랙 Day 031 (0) | 2021.12.07 |
---|---|
[TIL] 엘리스 SW 엔지니어 트랙 Day 030 (0) | 2021.12.07 |
[TIL] 엘리스 SW 엔지니어 트랙 Day 028 (0) | 2021.12.02 |
[TIL] 엘리스 SW 엔지니어 트랙 Day 027 (0) | 2021.11.30 |
[TIL] 엘리스 SW 엔지니어 트랙 Day 026 (0) | 2021.11.29 |
댓글
이 글 공유하기
다른 글
-
[TIL] 엘리스 SW 엔지니어 트랙 Day 031
[TIL] 엘리스 SW 엔지니어 트랙 Day 031
2021.12.07 -
[TIL] 엘리스 SW 엔지니어 트랙 Day 030
[TIL] 엘리스 SW 엔지니어 트랙 Day 030
2021.12.07 -
[TIL] 엘리스 SW 엔지니어 트랙 Day 028
[TIL] 엘리스 SW 엔지니어 트랙 Day 028
2021.12.02 -
[TIL] 엘리스 SW 엔지니어 트랙 Day 027
[TIL] 엘리스 SW 엔지니어 트랙 Day 027
2021.11.30