🕵️♀️서버란?
네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램이다. 클라이언트의 요청에 대한 응답을 하는 역할을 한다.
localhost : 현재 컴퓨터의 내부 주소. 서버 개발할 때 테스트 용으로 많이 쓰인다.
port : 서버내에 프로세스를 구분하는 용도. 멋사 2기 교육 초반에 빌딩 안에 문으로 비유하여 작성한 적이 있다.
routing : 요청에 맞게 분기 처리하여 응답하는 것을 라우팅이라고 한다.
❓ localhost와 사설 IP의 차이는?
"내 컴퓨터의 IP와 localhost(127.0.0.1)는 같지 않을까?" 라는 생각을 했다.
localhost(127.0.0.1)로 서버를 띄울 경우, 서버를 띄운 PC에서만 접속이 가능하다.
내 컴퓨터의 IP(사설 IP)는 같은 대역의 사설 IP를 할당받은 모든 기기에서 접속이 가능하다.
const http = require("http"); // http 패키지 사용.
위 소스코드 처럼 패키지를 통해 서버 구축을 편리하게 할 수 있다. 서로 의존되는 패키지들이 있고, 버전마다 기능이 다를 수 있다. 이러한 패키지들을 모아서 관리해주는 툴이 npm(node package manager)이다. 패키지 의존성과 버전 관리를 package.json 파일로 할 수 있다.
✍ npm 사용
터미널에서 npm init 이라는 명령어로 초기환경을 구축할 수 있다. 입력사항들을 입력한 후 해당 폴더에 package.json이 생성된다.
✍ npm 패키지 설치 및 사용
"dependencies": { "express": "^4.18.1" }, "devDependencies": { "nodemon": "^2.0.16" }
터미널에 "npm install 패키지명"을 입력하여 패키지를 설치할 수 있다.터미널에 "npm install -D 패키지명"을 입력하면 패키지를 설치하는데 개발 환경에서만 사용하고 나중에 배포할 때는 사용하지 않는다는 의미이다.
터미널에 "npm install -g 패키지명"을 입력하면 한 번의 설치로 모든 프로젝트에서 사용한다는 의미이다.
💬 실습에서 설치한 패키지는 서버 구축시 필요한 express, nodemon, express-generator 이다.npm install express
,npm install -g express-generator nodemon
✍ package.json
{ "name": "npm_test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "hello": "echo hello" }, "author": "ayden", "license": "ISC" }
pakage.json 내부는 위와 같이 되어 있으며, "scripts" 부분에 명령어를 입력할 수 있다.
🕵️♀️Node.js란
const http = require("http"); // http 패키지 사용.
http.createServer((req, res)=>{
if(req.url ==="/"){
res.writeHead(200); // 정상 응답
res.end("main url"); // 사용자에게 보여질 코드
} else if(req.url === "/upload"){
res.writeHead(200);
res.end("upload url")
}
}).listen(3000, ()=>{
console.log('3000번 포트 서버 접속 완료~!!')
})
위 소스코드와 같이 일반 .js 파일에 작성하여 서버를 구축할 수 있다.
require("http")
은 서버를 쉽게 구축하기 위해 http 패키지를 불러오는 메소드이다.
createServer((req, res)=>{...})
은 서버를 생성하는 메소드이다. 콜백함수로 req, res 가 있어 요청과 응답을 받고 보낼 수 있다.
listen(3000)
는 서버를 대기 상태로 만드는 메소드이다. 클라이언트에서 요청이 있으면 그것을 받아 처리할 수 있다. 3000은 Port Number이다.
🕵️♀️routing이란?
클라이언트의 요청 URL를 보고 이 요청을 처리할 수 있는 곳으로 전달해주는 것이다. 즉, 요청에 따라 처리를 해주는 것을 라우팅이라고 한다.
// app.js 파일
const templateRouter = require('./routes/template')
app.use('/template', templateRouter);
app.js 파일 안에 위와 같은 소스코드를 볼 수 있는데, '/template' url로 요청이 왔을 때
./routes/template.js
파일을 실행한다는 의미로 생각하면 된다.
// routes 폴더 안에 js 파일.
// 위 소스코드를 보았을 때, user.js 또는 index.js 파일
const express = require("express");
const router = express.Router();
router.get('/ejs', (req, res)=>{
res.render('template', {data: "test data"});
})
routes 폴더에 js 파일 안에서 어떤 url로 요청 왔을 때 콜백함수로 어떤 것을 전달 받고 어떤 것을 전달해줄지 작성할 수 있습니다.
🕵️♀️express란?
express는 미들웨어 구조로 인하여 빠르고 간편하게 Node.js를 개발할 수 있도록 도와주는 웹 프레임워크이다.
express-generator는 express를 기본 구조를 간편하게 만들어주는 역할을 한다.
// 프로젝트 생성 명령문으로 터미널에 작성 express --ejs first-project
express-generator를 통해 프로젝트를 만들게 되면 위와 같은 구조로 생성된다.
bin 폴더의 www : 서버 실행 및 포트번호 지정.
public 폴더 : image, js, css 등 리소스.
routes 폴더 : 페이지 라우팅과 관련된 파일, 실제 서버 로직 작성
views 폴더: 템플릿 파일(.jade, .ejs 등) 포함.
app.js 파일 : 핵심적인 서버 역할, 라우팅의 시작점.
package.json 파일 : 의존성 관리 및 버전 관리.
✍ 템플릿 파일은 HTML 코드 안에 JS 코드를 넣을 수 있다.
🕵️♀️nodemon이란?
nodemon은 라이브 서버 같은 역할을 수행한다. nodemon을 설치하면 변경 사항이 있을 때 서버를 껐다가 킬 필요 없이 페이지 새로고침만으로 변경 사항이 업데이트된다.
// GET(data 가져오기)
router.get('/read', (req, res)=>{
res.status(200).json({
message: "read success"
})
})
// POST(생성)
router.post('/create', (req, res)=>{
const {data} = req.body;
arr.push(data);
res.status(200).json({
message: "create success",
result: arr,
})
})
// PUT(수정)
router.put('/update/:id', (req, res)=>{
const {id}= req.params;
const {data} = req.body;
arr[id] = data;
res.status(200).json({
message: "update success",
result: arr,
})
console.log(id);
})
// DELETE(삭제)
router.delete('/delete/:id', (req, res)=>{
const {id} = req.params;
arr.splice(id, 1);
res.status(200).json({
message: "delete success",
result: arr,
})
})
http 메소드를 사용하여 서버에 요청을 보내는 방법이다.
GET: 요청 받은 정보를 검색하여 응답(READ)
POST: 요청된 자원을 생성(CREATE)
PUT: 요청된 자원을 수정(UPDATE)
DELETE: 요청된 자원을 삭제(DELETE)
✍
localhost:3000/delete/0
url로 요청 시router.delete('/delete/:id', (req, res)=>{...}
코드에:id
는 url 요청으로 온 파라미터를 받아서 처리할 수 있다. 즉,:id===0
이 된다.
-- ../module/loginCheck --
const loginCheck = (req, res, next)=>{
const userLogin = true;
if(userLogin){
next()
} else{
res.status(400).json({
message: "login fail"
})
}
}
module.exports = loginCheck;
-- index.js --
const loginCheck = require('../module/loginCheck')
router.get('/', loginCheck, (req, res)=>{ // 두 번재 매개변수가 미들웨어
res.status(200).json({
message: "login success",
})
})
🕵️♀️미들웨어란?
요청과 응답 사이에 위치하여 목적에 맞게 처리하는 함수들이다.
예를 들어 게시판에 글을 쓴다고 가정해 보자. 게시판에 글을 쓰고 삭제하고 수정하는 작업은 로그인한 후에 가능한 작업이다. 즉, 글 작성, 삭제, 수정 요청 시 매번 로그인이되어 있는지 확인해야 한다. 이렇게 요청이 올 때마다 뭔가를 체크하는 작업의 코드를 작성한다면 비효율적이다. 글 작성, 삭제, 수정 요청 시 로그인 체크 하나의 함수로 응답해주는 게 미들웨어이다.
-- index.js --
const multer = require("multer");
const storage = multer.diskStorage({
destination: (req, file, cb) =>{
cb(null, "public/images/")
},
filename: (req, file, cb) =>{
cb(null, file.originalname)
}
})
const upload = multer({storage: storage})
-- imageUpload.js --
const multer = require("multer");
const storage = multer.diskStorage({
destination: (req, file, cb) =>{
cb(null, "public/images/")
},
filename: (req, file, cb) =>{
cb(null, file.originalname)
}
})
const upload = multer({storage: storage})
🕵️♀️multer란?
express는 사용자가 업로드한 파일을 받아서 저장하는 기능을 제공하지 않는다. 파일을 업로드할 때 사용하는 패키지가 multer이다.
🕵️♀️ejs란?
HTML이 정적 웹 페이지라면 ejs는 view 파일 안에 변수를 넣을 수 있는 동적 웹 페이지이다. 사용자 모두에게 똑같이 보이는 웹페이지를 ejs로 하나만 만들고 안에 내용만 변수로 사용하면 HTML 처럼 하나하나 다 만들지 않아도 된다.
✍문법 사용
<!DOCTYPE html> <html> <head></head> <body> <% if(true){ %> <div>ejs working</div> <% } else { %> <div>ejs not working</div> <% } %> <div></div> </body> </html>
js 코드는 위 소스코드와 같이 <%...%>로 작성한다.
-- ./routes/template.js -- router.get('/ejs', (req, res)=>{ //views 폴더 template 파일에 data 라는 key를 가진 값을 보낸다. res.render('template', {data: "test data"}); }) -- ./view/template.ejs -- <!DOCTYPE html> <html> <head></head> <body> <%= data %> </body> </html>
위와 같은 소스코드로 data라는 변수를 출력할 수 있다.
res.render('template', {data: "test data"});
✍ejs도 JS처럼 파일 분할이 가능하다.
<% include 파일명 %>
으로 외부 파일을 가져올 수 있다.
//app.js
const session = require('express-session')
app.use(session({
secret: "first project", // 세션 암호화
resave: false, // 세션이 변경되지 않았을 때는 저장 X
saveUninitialized: true, // 세션 저장될 때 초기화 X
}))
🕵️♀️express-session이란?
로그인이라는 기능을 구현한다고 가정했을 때, 사용자는 아이디와 비밀번호를 서버에 보내 로그인을 요청한다. 정상적으로 로그인이 되고 게시판에 글을 작성하려고 할 때, 서버는 상태에 대한 저장 기능이 없기 때문에 사용자가 로그인되어 있는 것을 확인할 수 없다. 즉, 로그인이 되어 있지 않다고 판단하여 게시판 글 작성에 대한 요청을 거절한다. 이때 필요한 것이 session이다. 즉, session은 사용자 정보를 저장하는 기능을 하는 패키지이다.
서버 개발 시 이를 테스트할 수 있는 툴이다. 브라우저 대신이라고 생각하면 될 것 같다. 또한, API 개발을 보다 빠르고 쉽게 구현할 수 있도록 도와주며, 개발된 API를 테스트하여 문서화 또는 공유할 수 있도록 도와주는 툴이다.
💬 API는 간단하게 요청을 받고 응답하는 서버이다.
❓ 브라우저에서 테스트하지 않고 왜 Postman을 사용할까?
너무나 당연하지만 브라우저는 기본적으로 테스트하기 위해 만들어지지 않았다. 따라서, 테스트 단계에서 사용하기에는 적합하지 않다.(파라미터를 전달하는 방법, 응답을 받고 출력하는 방법 등등)