728x90
목차
2022.04.22 - [Programming/BACKEND] - Node.JS)04.21(HttpServer, Axios )
1. ExpressServer
Express서버의 다른서버와의 특징
- http 모듈 웹서버의 확장판으로 코드 가독성이 좋고 확장성이 뛰어나다.
- 프레임이 잡혀있어 파일관리 및 운영이 용이하다.
- 비슷한 서버로서 Koa, Hapi 드이 있지만 Express서버를 가장 많이 사용한다.
- 코드관리 및 편의성에서 많은 장점을 제공한다.>
nodemon의 이점
- 서버구동 및 운용에 발생한 모든 과정을 로깅으로 보여준다.
- 에러 수정이 용이하다.
- 일정 시간이 지나거나 주요파일이 저장되면 서버가 다시 재구동되므로, 수동으로 서버 재시작의 불편함이 없다.
package.json
- Express 서버의 초기 설정 값들을 넣고 조절하는 파일
- 직접 작성하여 파일을 생성해도 되고, npm init 명령어를 실행하여 생성하는 방법이 있다.
1.1. 사용될 명령어
1.1.1. npm init :
express프로젝트를 구성하는 명령어 (초기화) (필요한 디렉토리들이 생성된다)
1.1.2. npm i express :
현재 폴더에 디펜던시를 설치한다.
package-lock.json : 각 프로그램들의 버전들이 저장됨 (노드 모듈이 삭제되더라도 npm i 명령어로 모듈을 다시 받을 수 있다)
1.1.3. npm i -D nodemon :
Nodemon은 프로젝트 폴더의 파일들을 모니터링 하고 있다가 파일이 수정되면 서버를 자동으로 restart 시켜주는 패키지이다
1.1.4. npm start:
express서버를 실행시키는 명령어
1.2. express서버 구동에 핵심이 되는 파일 app.js 중요 메서드
- app.set('port', 포트)로 서버가 실행될 포트 지정
- app.get('키워드', 익명함수)로 GET요청이 올 때 어떤 동작을 할지 지정
- app/get('포트', 익명함수)로 몇 번 포트에서 서버를 실행할지 지정
1.3. express 서버 구동 순서
- npm init
- npm i express
- npm i -D nodemon : 개발환경용이므로 필수 사항은 아니다.
- app.js 또는 index.js 또는 main에 지정한 파일 (서버의 시작파일)을 제작
- package.json의 scripts에 "start" : "nodemon app"을 추가
- npm app 또는 npm run start(npm start)로 서버를 시작한다.
1.4. express 서버 실행하기
const express = require("express");
const app = express(); //서버 객체를 변수에 저장
app.set('port', process.env.PORT || 3000);
// 서버내에서 port라는 변수를 만들어서 현재 환경의 포트
// 또는 포트가 지정되지 않았다면 3000을 저장한다.
app.get('/', (req, res)=>{
res.send('<h1>Hello, ExpressServer</h1>');
});
app.get("/login", (req, res)=>{
// 로그인 관련 페이지 동작
});
app.listen(app.get('port'), ()=>{ console.log(app.get('port'), '번 포트에서 대기중입니다.');})
// app.listen(3000, ()=>{ console.log(3000, '번 포트에서 대기중입니다.');})
2. Express서버 - html파일 send하기
- path모듈을 활용하여
'__dirname'과 'html파일명'의 조합으로 경로가 생성되고 클라이언트에 파일 자체를 전달한다.
const express = require('express');
const path = require('path');
const app = express();
app.set('port', process.env.PORT || 3000);
app.get('/', (req, res)=>{
// __dirname의 내용과 index.html파일명이 조합된 종합경로가 만들어지고
// 해당 파일의 내용으로 클라이언트에 응답할 예정.
// 02_Internal_Module의 path 파일내용을 참고
// 파일을 열어서 내용을 꺼내어 클라이언트에게 보내주는것이 아닌, 파일 자체를 보낸다.
// 사용되는 메서드 res.sendFile();
console.log('__dirname의 경로 : ' + path.join(__dirname)); // D:\Java\00_JS\04_Express\npm02
res.sendFile( path.join(__dirname, '/index.html') ); // 'D:\Java\00_JS\04_Express\npm02' + /index.html
});
app.get('/users', (req, res)=>{});
// 이와 같은 함수를 라우터라고 부른다.
// 하나의 라우터에는 method와 url이 같이 표시되어 해당 내용으로 응답을 보내준다.
app.listen(app.get('port'), ()=>{ console.log( app.get('port'),'번 포트에서 대기중입니다.'); }) ;
<!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>index.html</title>
</head>
<body>
<h1>익스프레스</h1>
<h2>함께 배워보자고~😮</h2>
</body>
</html>
3. Express서버 - 라우터/미들웨어
- 라우터 :
app.get() 또는 app.post 등... 리퀘스트로 키워드를 받아 해당 요청에 응답을 보내주는 메서드들을 '라우터'라고 부른다. - 미들웨어 :
첫 번째 매개변수 전달요소별로 리퀘스트 키워드를 요청받아 익명함수를 실행해서 응답한다.
그 메서드 안에 들어가는 익명함수들 ( )=>{ }을 '미들웨어'라고 부른다
- app.get('(url)', ... ); -> '라우터'
- req, res) => { res.sendFile(path.join(__dirname, '/index.html')); } -> '미들웨어'
3.1. 모든 라우터가 실행되기 전 실행되는 라우터
// 미들웨어만을 위한 멤버함수(라우터)가 존재한다.
// 1. 모든 라우터들이 실행되기 전 실행되는 라우터 : 보통 다른 라우터들의 위쪽에 기술되어져서 모든 라우터들이 실행되기 전 실행의 대상으로 인식왼다.
app.use( (req, res, next)=>{
console.log('모든 요청에 실행하고 싶어요');
next();
// 모든 라우터에 next가 있지만 사용하지 않아서 생략된 상태.
// 필요하면 꺼내어 사용할 수 있다.
// next()가 없으면 현재 라우터에서 요청에 대한 응답이 종료되니, 미들웨어를 위한 라우터는 반드시 next()를 사용한다.
});
// ----------
app.get('/', (req, res)=>{
res.sendFile(path.join(__dirname, '/index.html'));
});
app.get('/abc', (req, res)=>{
res.sendFile(path.join(__dirname, '/index1.html'));
});
3.2. 특정 리퀘스트요청 시 같이 실행할 미들웨어
// 2. 특정 리퀘스트에서만 실행할 미들웨어
app.use('/about', (req, res, next)=>{
console.log('about 요청에만 실행되는 미들웨어입니다.');
next();
})
//get과 post등 모든 method에서 리퀘스트 키워드만 같으면 실행된다.
// 실행 후 next()로 인해 제어권이 아래로 이동하여, 해당 get이나 post등이 추가 실행된다.
// --------------
app.get('/about', (req, res)=>{
res.send('<h2>Hello About</h2>');
});
3.3. 미들웨어의 특성
- 하나는 미들웨어에서 'res.send()' 또는 'res.sendFile()'등을 두 번이상 쓸 수 없다. 'res.json()'도 예외는 아니다.
- http서버에서 사용하던 res.writeHeader() + res.end()가 합쳐져서 res.send()가 된 것이므로 send()는 두 번이상 쓰는 것은 의도치 않은 에러를 발생한다.
- res.json()또한 res.writeHeader(200, {'Content-Type' : application/json'});와 res.end(FJSON.stringify({hello:'hong'}));
위 둘이 합쳐져서 res.json({hello:'hong'});로 사용되는 것이므로 , 두 번이상 사용되지 않는다.
4. Express서버 - 에러처리
4.1. 에러 발생
app.use((req, res, next)=>{
throw new Error("서버 - 에러를 발생시켜주마~~");
...
next();
});
- '에러를 처리하는 라우터가 존재하지 않아' 에러내역이 브라우저에 모두 표시되어 서버구조가 노출되어버린다. (500에러)
- 에러내역은 서버의 콘솔에만 나오고 브라우저에는 에러처리에 의한 내용만 나오도록 "에러처리 라우터"를 마지막에 추가해준다.
4.2. 에러처리 라우터
- 위 라우터 또는 미들웨어에서 '에러가 발생했을 때 실행되는 미들웨어'.
- 에러처리 라우터에 있는 미들웨어는 반드시 매개변수가 err, req, res, next 네 개가 쓰여져야 에러처리로 인식된다.
넷 중에 하나라도 없으면 에러처리 라우터로 인식되지 못한다.
//4.2. 에러처리 라우터 --------------------
// 위 라우터 또는 미들웨어에서 에러가 발생했을 때 실행되는 미들웨어.
// 에러처리 라우터에 있는 미들웨어는 반드시 매개변수가 err, req, res, next 네개가 쓰여져야 에러처리로 인식된다.
// 넷 중에 하나만 빠져도 에러처리 라우터로 인식되지 못한다.
app.use((err, req, res, next)=>{
console.error(err);
res.status(200).send('에러내용을 브라우저에 알려주지 않을래');
});
5. 404 에러처리
// 6. 404에러 처리
app.use((req,res,next)=>{
res.send('비정상적 접근~ 에러입니다~');
// 400, 500번대 에러가 노출될 경우 보안에 취약하기 때문에 브라우저에 직접적으로 표시되지 않는편이 좋다.
// res.status(404).send('404 에러임!');
});
6. 리퀘스트 키워드의 '와일드카드 문자'
- 해당 라우터가 존재하지 않을 경우 받아주는 와일드카드 문자 키워드가 존재한다.
- 이것은 404 에러를 방지하여 조금 더 ux친화적인 방법으로 사용될 수 있다.
- 가능한 다양한 라우터의 아래쪽에 위치시켜 명확한 라우터가 우선 실행되도록 한다.
// 7. 리퀘스트 키워드의 와일드카드 문자.
// 부츠 카테고리 라우터
app.get('/category/Boots', (req, res)=>{
res.send('<h2>Hello Boots</h2>');
});
// 힐 카테고리 라우터
app.get('/category/Heel', (req, res)=>{
res.send('<h2>Hello Heel</h2>');
});
// 와일드카드 라우터
// 와일드카드 키워드를 사용한 라우터는 범위가 넓으므로 가능한 아래쪽에 위치시켜서, 명확한 구분은 먼저 실행되게 하고,
// 해당 라우터가 없을 때 실행되게 하는것이 효과적이다.
app.get('/category/:name', (req, res)=>{
res.send(`<h2>Hello wild Card Char ${req.params.name}</h2>`);
})
7. 추가 모듈 설치
7.1. 추가적으로 설치할 모듈을 require한다.
// 추가 모듈 설치 ------------------
// 각각의 요청과 응답에 대한 필요정보를 보기 위한모듈
const morgan = require('morgan');
//쿠키사용을 보다 간결하게 사용하기 위한 모듈
const cookieParser = require('cookie-parser');
// 세션사용을 보다 간결하게 사용하기 위한 모듈
const session = require('express-session');
// 요청의 본문을 해석, 구분하는 모듈
const bodyParser = require('body-parser');
7.2. cmd에 npm i 모듈명1 모듈명2 ... 방식으로 디펜던시?를 받아온다.
7.3. 추가한 모듈과 관련된 미들웨어 설정을 진행한다.
// 공통 미들웨어 설정 ------------
app.use(morgan('dev'));
// 실행결과 : GET / 200 5.316 ms - 165
// method방식, 응답결과코드, 요청과실행에 걸린 시간 등등
// app.use(morgan('combined')); 더 자세한 내용을 볼 수도 있다.
app.use(cookieParser());
app.use(express.json()); //바디파서 json : json 사용을 위한 모듈
app.use(express.urlencoded({extended:true})); //바디파서 폼데이터 모듈
//app.use(body-Parser.json());
//app.use(body-Parser.urlencoded({extend : false}));
//세션 활용을 위한 미들웨어
app.use(session({
resave : false,
saveUninitialized : false,
secret : 'keonhee',
}));
// ---------------------------------------------------
8 . Express 서버와 쿠키
8.1. Express서버에서 쿠키 저장 / 삭제
app.get('/', (req, res)=>{
// ** express 서버에서 쿠키를 읽어오거나 저장하는 방식 **
// 1. 저장된 쿠키를 불러와서 활용할 변수 ' req.cookies '
console.log(req.cookies);
// 2. 새로운 쿠키 저장
const name = 'HongGillDong';
res.cookies('name', encodeURIComponent(name),{
expires:new Date(),
httpOnly : true,
path:'/'
});
// 3. 쿠키 삭제
res.clearCookie('name', encodeURIComponent(name),{
httpOnly:true,
path:'/'
});
});
8.2. Express서버의 쿠키 생성/활용 ( 로그인 )
app.get('/', (req, res)=>{
// id라는 이름의 쿠키가 있으면 ' 000님 반갑습니다 ' 를 send
if(req.cookies.id){
res.send(`${req.cookies.id}님 안녕하세요` + '<br><a href="/logout">로그아웃</a>');
}else{ // id 쿠키가 없으면 index.html을 send
res.sendFile(path.join(__dirname, '/index.html'));
}
});
app.post('/login',(req,res)=>{
// post이기 때문에 localhost:3000/login 까지만 보여진다.
// ** http 서버에서는 다음과 같이 전달 파라미터를 분해한다 **
// const { query } = url.parse(req.url);
// const { name } = qs.parse(query);
// ** express 서버에서 전달 파라미터를 활용하는 과정 **
//console.log(req.body.name);
const name = req.body.name;
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 1);
// 파라미터 내용을 쿠키로 추가
res.cookie( 'id', name, {
expires : expires,
httpOnly : true,
path:'/'
});
res.redirect('/'); // redirect('/'); 특정 리퀘스트로 이동한다.
});
<!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>index.html</title>
</head>
<body>
<h1>익스프레스 : 라우터</h1>
<h2>배워보자고</h2>
<form action="/login" method="post">
<input id="name" name="name" placeholder="이름을 입력하세요"/>
<button id="login">로그인</button>
</form>
</body>
</html>
8.3. Express서버의 쿠키 삭제 ( 로그아웃 )
// id 쿠키를 지우고, '/'로 리다이렉트 하는 라우터를 만든다.
app.get('/logout',(req, res)=>{
res.clearCookie('id', req.cookies.name, {
httpOnly:true,
path:'/'
});
res.redirect('/');
});
8.4. 예제1
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const morgan = require('morgan');
const app = express();
// 추가모듈 설정
app.use(morgan('dev'));
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({extended:true}));
// 포트설정
app.set('port', process.env.PORT || 3000);
// 라우팅
// 루트 라우터
app.get('/', (req, res)=>{
if(req.cookies.id){
res.send(`${req.cookies.id} 님 반갑습니다.` + '<a href="/logout">로그아웃</a>');
} else {
res.sendFile(path.join(__dirname, '/index.html'));
}
});
// 로그인 라우터
app.post('/login',(req,res)=>{
const id = req.body.id;
const pw = req.body.pw;
const expires = new Date();
expires.setMinutes(expires.getMinutes() + 1);
if( id=='scott' && pw == 'tiger'){
res.cookie('id', id, {
expires : expires,
httpOnly : true,
path : '/'
});
return res.json( {msg : 'ok'} ); //json 데이터를 갖고 호출위치로 돌아간다.
}else if(id!='scott'){
return res.json({msg:'없는 아이디입니다.'});
}else if(pw!='tiger'){
return res.json({msg:'비밀번호 오류입니다.'});
}else {
return res.json({msg:'알수없는 오류'});
}
});
// 로그아웃 라우터
app.get('/logout', (req,res)=>{
res.clearCookie('id', req.cookies.id,{
httpOnly : true,
path : '/'
});
res.redirect('/');
})
app.listen(app.get('port'), ()=>{
console.log(app.get('port'), '번 포트에서 대기 중');
});
<!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>index.html</title>
<!-- axios -->
<script src="https://unpkg.com/axios@0.25.0/dist/axios.min.js"></script>
</head>
<body>
<form method="post" id="form">
<input type="text" name="id"><br>
<input type="password" name="pw"><br>
<input type="submit" value="로그인"><br>
<div id="message"></div>
</form>
<script type="text/javascript">
document.getElementById('form').addEventListener('submit', async (e)=>{
e.preventDefault(); // 이벤트 중단(submit)
// 이벤트가 발생한 요소 값 저장 (target속성)
const id = e.target.id.value;
const pw = e.target.pw.value;
if(id == ''){
alert('아이디를 입력하세요');
return;
}else if(pw == ''){
alert("비밀번호를 입력하세요");
return;
}
try{
// axios로 '/login' 라우터에서 가져온 값을 res에 담기
const res = await axios.post('/login', {id, pw});
// 로그인이 잘 되었다면?
if(res.data.msg == 'ok') location.href='/';
document.getElementById('message').innerHTML = res.data.msg;
}catch(err){
console.error(err);
}
e.target.id.value='';
e.target.pw.value='';
});
</script>
</body>
</html>
9. Express와 session
- 'express-session' 모듈을 사용한다.
9.1. 세션의 저장/삭제
...
// 추가모듈 require
const session = require('express-session');
// express-session 모듈 설정
app.use(session({
resave:false,
saveUninitialized:false,
secret:"keon", // 세션값의 암호화 코드
}));
...
// 세션의 저장
req.session.id = 'hello';
req.session.data = 'asdfadf';
// 다른 미들웨어에서 req.session.data 라는 이름으로 사용가능 (영구적인 저장)
9.2. 예제1
const express = require('express');
// 추가모듈 require
const path = require('path');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const app = express();
app.set('port', process.env.PORT || 3000);
// 추가모듈 설정
app.use(morgan('dev'));
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({extended:true}));
// express-session 모듈 설정
app.use(session({
resave:false,
saveUninitialized:false,
secret:"keon", // 세션값의 암호화 코드
}));
// 세션의 저장
// req.session.id = 'hello';
// req.session.data = 'asdfadf';
// 다른 미들웨어에서 req.session.data 라는 이름으로 사용가능 (영구적인 저장)
// 라우팅
app.get('/', (req, res)=>{
if(req.session.userid){
res.send(`${req.session.userid}님 반갑습니다.` + '<a href="/logout">로그아웃</a>');
}else{
res.sendFile(path.join(__dirname,'/index.html'));
}
});
app.post('/login', (req, res)=>{
const id = req.body.id;
const pw = req.body.pw;
if(id=='scott' && pw=='tiger'){
req.session.userid = id;
return res.json({msg:'ok'});
}else if(id!='scott'){
return res.json({msg:'없는 아이디'});
}else if(pw!='tiger'){
return res.json({msg:'비번 오류'});
}else {
return res.json({msg:'알수없느 ㄴ오류'});
}
});
app.get('/logout', (req,res)=>{
// 세션 삭제
req.session.destroy(function(){
req.session;
});
res.redirect('/');
});
app.listen(app.get('port'), ()=>{
console.log(app.get('port'),'번 포트에서 대기 중');
});
<!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>index.html</title>
<!-- axios -->
<script src="https://unpkg.com/axios@0.25.0/dist/axios.min.js"></script>
</head>
<body>
<form method="post" id="form">
<input type="text" name="id"><br>
<input type="password" name="pw"><br>
<input type="submit" value="로그인"><br>
<div id="message"></div>
</form>
<script type="text/javascript">
document.getElementById('form').addEventListener('submit', async (e)=>{
e.preventDefault(); // 이벤트 중단(submit)
// 이벤트가 발생한 요소 값 저장 (target속성)
const id = e.target.id.value;
const pw = e.target.pw.value;
if(id == ''){
alert('아이디를 입력하세요');
return;
}else if(pw == ''){
alert("비밀번호를 입력하세요");
return;
}
try{
// axios로 '/login' 라우터에서 가져온 값을 res에 담기
const res = await axios.post('/login', {id, pw});
// 로그인이 잘 되었다면?
if(res.data.msg == 'ok') location.href='/';
document.getElementById('message').innerHTML = res.data.msg;
}catch(err){
console.error(err);
}
e.target.id.value='';
e.target.pw.value='';
});
</script>
</body>
</html>
10. multer 모듈 ( 파일 업로드 )
'multer' 모듈을 사용하여 파일 업로드를 구현한다.
10.1. 업로드된 파일 저장 디렉토리 생성
- 업로드를 하려면 업로드된 파일이 저장될 폴더를 지정해야한다.
- 지난 프로젝트처럼 폴더를 직접 만들지는 않고, 'fs모듈을 활용'하여 이용하려는 폴더가 있으면 그 폴더를 사용하며,없으면 새로 생성하는 기능을 사용한다. ( readdirSync( ), mkdirSync( ) 활용 )
- 파일 폴더와 같은 외부의 리소스를 다루는 작업은 명령 오류와 상관없이 디스크 상태에 따라 오류가 발생할 수 있으며, 스스로 예외처리를 해준다.
- 특히 지금은 'readdirSync( )'가 실행될 때 해당 폴더가 없다면 에러가 발생하므로 그에 대한 처리로 예외처리를 이용한다.
try{
fs.readdirSync('uploads');
}catch(err){
console.error('uploads폴더가 없어 새로 생성합니다.');
fs.mkdirSync('uploads');
}
10.2. multer객체 생성 / 설정
- 현재 프로젝트에서 사용할 multer 객체를 생성한다. 객체이름은 upload
- multer함수에 전달인수로 객체 하나를 전달하는데 그 객체에는 storage와 limits라는 속성이 포함된다.
// 현재 프로젝트에서 사용할 multer 객체를 생성한다. 객체이름은 upload
// multer함수에 전달인수로 객체 하나를 전달하는데 그 객체에는 storage와 limits라는 속성이 포함된다.
const upload = multer({
// storage : multer.diskStorage()로 저장위치(destination), 파일명(filename) 옵션을 설정.
storage:multer.diskStorage( { destination(){} , filename(){} } ),
limits : {}, // 파일 용량제한
});
10.3. 예제
const express = require('express');
// 추가모듈 require
const path=require('path');
const fs = require('fs');
const multer = require('multer');
const app = express();
app.set('port', process.env.PORT || 3000);
app.use(express.json());
app.use(express.urlencoded({extended:false}));
// static( 정적 )폴더 지정
app.use('/', express.static(path.join(__dirname, 'uploads')));
// 업로드 폴더 생성
try{
fs.readdirSync('uploads');
}catch(err){
console.error('uploads폴더가 없어 새로 생성합니다.');
fs.mkdirSync('uploads');
}
// 현재 프로젝트에서 사용할 multer 객체를 생성한다. 객체이름은 upload
const upload = multer({
storage:multer.diskStorage(
{
destination(req, file, done){
done(null, 'uploads/'); //폴더 설정
// 첫번째 인수 null은 현재파일(file)의 경로와 이름 그대로 사용.
// (변경 및 추가 없음)
},
filename(req, file, done){
const ext = path.extname(file.originalname); //확장자 추출
//확장자를 뺀 파일이름 + 오늘 날짜(밀리초) + 추출된 확장자로 저장 파일명 변경
done(null, path.basename(file.originalname,ext)+Date.now()+ext);
// abc.jpg -> 'abc' + 12345214 + '.jpg' -> abc12345214.jpg
// 업로드 파일명이 같은 경우 cos처럼 처리할 객체가 없고, 위와같은 방법으로 파일명의 충돌을 방지한다(오늘날짜시간의 밀리초 값)
},
}
),
limits : {
fileSize: 5* 1024 * 1024
},
});
// 라우팅
app.get('/', (req, res)=>{
res.sendFile( path.join(__dirname, 'multer.html'));
});
app.post('/upload', upload.single('image'), (req,res)=>{
console.log( req.file );
console.log( req.body.title );
return res.json({
title:req.body.title,
filename : req.file.filename,
})
});
app.listen(app.get('port'), ()=>{
console.log(app.get('port'), '번 포트에서 대기 중');
});
<!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>multer.html</title>
</head>
<body>
<form id="form" method="post" enctype="multipart/form-data">
<input type="file" name="image"/>
<input type="text" name="title"/>
<button type="submit">업로드</button>
<div id="message"></div>
<div id="filename"></div>
<div id="img"></div>
</form>
<!-- axios -->
<script src = "https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
document.getElementById('form').addEventListener('submit', async (e)=>{
e.preventDefault(); // 이벤트 중지( submit )
const formData = new FormData(); // 새로운 FormData 객체 생성
// 생성된 FormData 객체에 업로드 될 image과 title을 담는다.
formData.append('image', e.target.image.files[0]);
formData.append('title', e.target.title.value);
try{
const res = await axios.post('/upload', formData); // 완성된 formData객체를 /upload request로 전송
// 현재 페이지 요소에 전달받은 데이터로 표시한다.
document.getElementById("message").innerHTML = "제목: " + res.data.title;
document.getElementById("filename").innerHTML = "업로드된 파일의 저장 이름 : " + res.data.filename;
document.getElementById("filename").innerHTML = '<img src="' + res.data.filename + '" width=200>';
}catch(err){
console.error(err);
}
e.target.image.value='';
e.target.title.value='';
});
</script>
</body>
</html>
300x250