Query String 이란 url의 일부로 클라이언트에서 서버로 데이터를 전송하는 방법이다. URL에 ?를 사용하여 시작하고 key=value형태로 데이터를 표현하고 여러개 데이터는 &로 구분한다. 아래의 코드를 보자.
app.get('/product', (req, res) => {
// res.send(`Response ok ${req.query.category}`)
const { category, id } = req.query;
res.send(`Product Category: ${category} & Product ID: ${id}`)
})
query는 request 객체에 들어있다.클라이언트가 주소창에 입력하거나 링크를 통해 접근하면 해당 URL이 서버로 전송되기 때문이다. 위에 말한 ?와 & 그리고 key=value 형태로 쓴 query string을 express.js가 자동으로 파싱해주어서 req.query객체로 만들어주는 것이다.예를 들어 query string에 카테고리가 있으면 req.query.category로 불러올 수 있는데, 여기서 필요한 데이터를 추출하기 위해서 const { category, id } = req.query;로 구조 분해 할당을 해준다.
예를 들어, postman에서 http://localhost:8000/product?category=iphone&id=12 주소로 get 요청을 보내면 Product Category: iphone & Product ID: 12 라는 응답을 받게 된다.
개인적으로URL parameter 과 이 개념이 헷갈렸는데, URL param은 경로의 일부로 : 뒤에 파라미터를 이름을 지정하지만 query string은 ?로 시작한다. 그래서 query string은 주로 선택적인 파라미터나 필터링, 정렬등에 사용된다. 예를 들면 검색결과 필터링이나, 페이지네이션이 그러하다. 반면에 URL parameter는 특정 제품 ID나 사용자 ID를 식별하는 데 사용된다. 이건 예를 들어 특정 사용자나 제품의 상세 정보 조회 할때 쓰이게 된다. 라우트 정의 시 query string은 URL parameter와 달리 별도로 지정해 주지 않아도 된다. 둘 다 클라이언트에서 서버로 데이터를 전송하는 방법이지만, 이렇게 사용 목적과 구현 방식에 차이가 있다.
다음으로 서버에서 클라이언트에게 JSON 형식의 데이터를 보내는 방법을 알아보자. JSON은 데이터 교환에 자주 사용되는 형식이다.
먼저 prdocuts.js라는 파일을 만들어주고 거기에 데이터를 넣어주었다. 예를 들어 아래와 같이 배열안에 객체를 가지고 있는 데이터이다.
const products = [
{
img: "https://m.media-amazon.com/images/I/6125yAfsJKL._AC_UX575_.jpg",
title: "Nike Air Monarch IV",
reviews: "(123 reviews)",
prevPrice: "$140,00",
newPrice: "200",
company: "Nike",
color: "white",
category: "sneakers",
},
{
img: "https://m.media-amazon.com/images/I/519MRhRKGFL._AC_UX575_.jpg",
title: "Nike Air Vapormax Plus",
reviews: "(123 reviews)",
prevPrice: "$140,00",
newPrice: "200",
company: "Nike",
color: "red",
category: "sneakers",
}
]
export default products
그 다음, 이 데이터를 사용하기 위해 'index.js' 파일에서 products.js를 import 한다.
import products from './products.js'
그리고 Express.js를 사용하여 /products 경로에 대한 GET 요청을 처리하는 라우트를 설정한다.
app.get('/products', (req, res) => {
res.json(products)
})
여기에 res.json()메소드가 사용된게 보이는데, 아까 배열안에 있는 객체 형태로 쓴 데이터를 자동으로 JSON 형식으로 변환해주는 역할을 한다. 이렇게 변환한 뒤 클라이언트에게 전송하여 JSON 형식을 보내주는 것이다.
따라서 클라이언트가 /products 경로로 get 요청을 보내면 서버는 products 데이터를 JSON 형식으로 응답한다.
미들웨어 함수는 요청(req)과 응답(res) 사이의 중간 단계에서 실행되는 함수를 말한다. function(req, res, next){} 이렇게 생긴 함수를 요청과 응답 중간에 추가하는 것이다. 예를 들어 아래와 같이 미들웨어 함수를 만들어준 뒤
function userCredentials(req, res, next) {
console.log('username: (alex)')
console.log('email: (alex21@gamil.com')
console.log('password: (alex222333)')
console.log('age: (18)')
next()
}
이 함수를 아래의 라우트 코드의 중간에 넣어주는 것이다.
app.get("/", userCredentials,(req, res) => {
res.send('<h1>hello admin </h1>')
});
하지만 여기서 코드 리팩터링을 할 수 있다. 먼저 middlewares라는 폴더를 만들고 logs.js라는 파일을 만들어 준 뒤, 여기에 위에서 만든 미들웨어 함수를 넣어주는 것이다. 그리고 export default를 해준 뒤
function userCredentials(req, res, next) {
console.log("username: (alex)");
console.log("email: (alex21@gamil.com");
console.log("password: (alex222333)");
console.log("age: (18)");
next();
}
export default userCredentials;
index.js에서 불러와주면 잘 작동된다.
import userCredentials from './middlewares/logs.js'
그런데 여기서 한 번 더 리팩터링을 할 수 있는데, 바로 중간에 써줬던 미들웨어 함수를 app.use에 넣어주는 것이다. 이렇게 넣어주면 Express.js가 우리가 보이지 않는 곳에서 중간에 이 함수를 넣어준다.
app.use(userCredentials)
app.get("/",(req, res) => {
res.send('<h1>hello admin </h1>')
});
app.get("/about", (req, res) => {
res.send("<h1>about section </h1>");
});
app.get("/contact", (req, res) => {
res.send("<h1>contact page </h1>");
});
위의 코드처럼 app.use에 미들웨어 함수를 넣어주면, 아래에 있는 모든 라우트에 userCredentials 함수가 적용되어 각 라우트로 요청이 들어올 때마다 콘솔에 로그가 출력되는 것을 볼 수 있다.

먼저 public 폴더에 app.js, index.html, style.css를 만들어준다. 그리고 index.js에서는 path 모듈을 import 해준 뒤 app.use를 이용해 static 미들웨어 함수를 지정해준다.
import express from 'express'
import path from 'path'
const app = express() //create server
app.use(express.static('./public'))
app.get('/', (req, res) => {
res.sendFile(path.join(process.cwd(), './public/index.html'))//current working directory and join it with the second argument
})
여기서는 res.sendFile을 이용해 파일을 불러오고 process.cwd()로 현재 작업 중인 디렉토리를 불러온 뒤, 두 번째 인자로 그 디렉토리 경로에 파일 경로를 붙여준다. 이렇게 하면 public 안에 있는 index.html 파일이 불러와지는 것이다.
다음으로 ejs 사용하는 법을 알아보자. 먼저 index.js파일을 보자
import express from 'express'
import route from './routes/route.js'
const app = express() //create server
app.use("/", route);
app.set('view engine', "ejs")
app.set('view engine', 'ejs')는 EJS를 뷰 엔진으로 설정하는 코드다. app.use("/", route)는 route에 있는 경로가 모두 /로 시작한다는 것을 의미한다. 위에 import route로 불러왔기 때문에 사용할 수 있는 것이다. 그럼 routes 폴더에 있는 route.js 파일의 코드를 보자.
import express from 'express'
import { homeController } from "../controllers/homeController.js";
import { aboutController } from "../controllers/aboutController.js";
const router = express.Router()
router.get('/',homeController)
router.get('/about', aboutController)
export default router;
router.get('/', homeController)는 기본 경로(/)로 요청이 들어오면 homeController를 실행하고, router.get('/about', aboutController)는 /about 경로로 요청이 들어오면 aboutController를 실행한다는 것을 의미한다. 위에 각각 컨트롤러들을 import 했기 때문에 가능한 것이다. 그럼 controllers 폴더에 있는 각각의 homeController, aboutController 파일을 보자.
const homeController = (req, res) => {
res.render("index")
}
export {homeController}
이 컨트롤러는 index.ejs 파일을 렌더링하여 클라이언트에게 응답한다.
const aboutController = (req, res) => {
res.render("about");
};
export { aboutController };
이 컨트롤러는 about.ejs 파일을 렌더링하여 클라이언트에게 응답한다.여기서 EJS 파일을 쓸 수 있는 이유는 index.js에서 app.set('view engine', "ejs") 이렇게 설정해주었기 때문이다.
ejs 기본 문법은 아래의 코드를 참고하자
<!-- Display Variable -->
<%=name.toUpperCase()%>
<%=2+2%>
<!-- conditional statement -->
<% if(userId === 20) {%>
<h1>User ID: <%=userId%></h1>
<% } else if(userId === 30){ %>
<h2>User Id <%=userId%></h2>
<%} else { %>
<h1>Nothing...</h1>
<%}%>
<!-- For loop -->
<% for(let i=0; i<10; i++){%>
<h1><%=i%></h1>
<%}%>
<!--for in loop -->
<% const data = [1,2,3,4,5]%>
<% for(d in data){%>
<h1><%=d%></h1>
<%}%>
<!-- built in method-->
<%var current = new Date()%> <%=current%>
마지막으로 포스트맨을 이용해서 서버에서 JSON을 보내고 그 값을 렌더링 하는 방법을 적어보겠다.

postman에서 위와 같이 body - raw 를 선택하고 JSON 형식으로 데이터를 보냈다. 그리고 index.js 에서 다음과 같이 렌더링했다.
app.post("/post", (req, res) => {
const { name, nationality, age} = req.body
res.send(`${name}, ${nationality}, ${age}`)
})
결과값은 이렇게 나오는것을 볼 수 있다.
