본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[32일차 복습 및 정리] 라우터 / middle-ware 사용해서 node.js express 서버 분산 관리 middle-ware, 미들웨어란? / next() 사용법

반응형

Router, 라우터는 node.js express로 서버를 만들 때 필수가 아니지만

쓰면 좋은 점 -> 파일들을 분산시켜 관리에 용이함. 

 

 

오늘 라우터, 미들웨어를 배웠는데 이해가 잘 되지않아서 다시 찾아봤다. 

 Middle ware  (softward glue)  = pipe 의 기능 

middle ware를 이용하면 분산 컴퓨팅은 2tier 형태를 벗어나 3-tier, 더 나아가 n-tier 형태로 발전하게 된다.  사진출처: 위키백과

middle ware란 양 쪽을 연결하여 데이터를 주고 샆을 수 있도록 중간에서 매개 역할을 하는 소프트웨어,

네트워크를 통해 연결된 여러 개의 컴퓨터에 있는 많은 프로세스들에게 어떤 서비스를 사용할 수 있도록 연결해주는 소프트웨어이다. 3계층 client / server 구조에서 middle ware 가 사이에 존재. 

웹브라우저에서 데이터베이스로부터 데이터를 저장하거나 읽어올 수 있게 

 

공통 서비스 및 기능을 애플리케이션에 제공하는 소프트웨어 

데이터 관리, 애플리케이션 서비스, 메시징, 인증 및 API관리는 주로 미들웨어를 통해 처리가 됨

 

미들웨어는 프로그래머들이 애플리케이션을 효율적으로 구축할 수 있도록 도움 

애플리케이션, 데이터 및 사용자 사이를 연결하는 요소처럼 작동.

 

Middleware is a type of computer software that provides services to software applications beyond those available from the operating system. It can be described as "software glue".[1]

Middleware makes it easier for software developers to implement communication and input/output, so they can focus on the specific purpose of their application. It gained popularity in the 1980s as a solution to the problem of how to link newer applications to older legacy systems, although the term had been in use since 1968.

 

 

 장점 

 

1. 편리한 유지보수( 엄청난 페이지의 수의 서버를 한 파일에 관리한다면 찾기도 힘들고 스크롤 내리느라 고생할 것.. ) 

 

모든 비지니스 로직을 서버에서 관리하기 때문에 관리와 유지 보수가 쉬워진다. 만약 변경사항이 있다면 서버 측만 변경하기 때문에 유지 보수가 간편해짐 

 

2. 확장성이 좋아진다. 3-tier 는 thin-client 형태를 사용한다. thin-client형태란 client의 컴퓨터 성능이 약간 떨어져도 프로그램을 실행시키는데 문제가 없다. 하지만 server측에는 무리가 있을 수 있지만 server측은 Multi process system or clustering을 이용함으로써 문제 해결 가능.

 

3. 표준화된 인터페이스 제공 가능 

 

4. 다양한 환경 지원, 체계가 다른 업무와 상호 연동이 가능 

 

5. 분산된 업무를 동시에 처리 가능하여 자료의 일관성이 유지됨

 

6. 부하의 분산이 가능 

 

100% 이해는 안되었으나 일단 중간에서  도와주는 애구나 ~ 라고 생각해야겠다.  

 

 

 

 

 

참고 사이트

ko.wikipedia.org/wiki/%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4

 

미들웨어 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 소프트웨어 구조 중 미들웨어. 미들웨어(영어: middleware)는 컴퓨터 제작 회사가 사용자의 요구대로 만들어 제공하는 프로그램으로, 운영 체제와 응용 소프트웨

ko.wikipedia.org

 

 

 

---------------------------------------------------------------------------------------------------------------------------------

 

 

 

 NEXT(); 에 대해 

 

 

/* MIDDLE WARE */
const express = require('express');
const app = express();


function test (req,res,next){
    console.log('hello');
    next();
}
app.use(test);       
                      

app.get('/', (req,res, next)=>{
    res.send('good morning');
    next();
})

app.use('/', (req,res,next)=>{
    console.log('hello2');
    res.send("it's okay");
    next();
})

app.listen(3000,()=>{
    console.log('server start posrt : 3000');

 

 

 

 

콘솔 로그 오류 메세지 :cannot set headers after they are sent to the client 

 

콜백함수 3번째 인자값으로 next 가 들어간다.

next(); 가 있으면 아래의 코드들을 계속 실행해도되~ 다음 middle ware 이 있으면 계쏙 진행해~ 라는 뜻 같음 

next(); 가 없다면 해당 middle ware는 ' 내가 마지막이야 !' 느낌임 

 

 

처음으로 돌아가서 다시 하나하나 해보기 

const express = require('express');
const app = express();

function test (req,res, next){
    console.log('hello');
}

app.use(test);

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

결과 : js 터미널에 'hello' 찍힘 

 

const express = require('express');
const app = express();

function test (req,res, next){
    console.log('hello');
}
app.use(test);

app.get('/',(req,res)=>{
    res.send('good afternoon');
})


app.listen(3000,()=>{
    console.log('server start port : 3000');
})

결과 : js 터미널에 'hello' 찍힘 (res.send는 실행 X) 

이미 '/' 값을 app.use(test) 에서 처리함 

 

이 경우 NEXT 를 넣어서 다음 코드도 실행되게 허용하기 

const express = require('express');
const app = express();

function test (req,res, next){
    console.log('hello');
    next();                   ////////////// NEXT 추가 
}
app.use(test);

app.get('/',(req,res)=>{
    res.send('good afternoon');
})


app.listen(3000,()=>{
    console.log('server start port : 3000');
})

결과 : js 터미널 'hello' / 브라우저 창 'good afternoon' 이 뜬다. 

같은 url 값을 받지만 next로 허용하게함 

 

만약 위치를 바꾸면 ? 

const express = require('express');
const app = express();

app.get('/',(req,res)=>{
    res.send('good afternoon');
})


function test (req,res, next){
    console.log('hello');
    next();                   ////////////// NEXT 추가 
}
app.use(test);



app.listen(3000,()=>{
    console.log('server start port : 3000');
})

결과 : 브라우저 'good afternoon' only 

터미널 콘솔로그는 찍히지 않음 

 

가장 처음의 app.get 을 처리하고 get 안에 next(); 가 없어서 아래 function은 처리가 안됨 

 

get 안에 next() 넣기 ** 여기서 인자값 3가지를 다 넣어주기 req,res, next 

const express = require('express');
const app = express();

app.get('/',(req,res,next)=>{
    res.send('good afternoon');
    next();
})


function test (req,res, next){
    console.log('hello');
    next();                   ////////////// NEXT 추가 
}
app.use(test);



app.listen(3000,()=>{
    console.log('server start port : 3000');
})

결과 : 브라우저 'good afternoon' + vs 터미널 콘솔 'hello'  

 

즉, next() 가 있음으로 두 쪽다 한번에 실행이 가능하다 ! 

 

같은 결과, 다른 방식 

 

 

---------------------------------------------------------------------------------------------------------------------------------

 

app.use() 의 첫번째 인자값은 함수이다. (함수가 꼭 들어간다.) 

모든 middle ware 실행 전, body-parser가 실행된것 

 

const express = require('express');
const app = express();

function test (req,res,next){
    console.log('첫번째 실행입니다.');
    next();
}
app.use(test);

app.get('/',(req,res)=>{
    console.log('두번째 실행입니다.');
    res.send('HELLOOO');
})

app.use('/board', (req,res,next)=>{
    console.log('첫번째 실행입니다');
    next();
})

app.get('/board', (req,res)=>{
    console.log('두번째 실행입니다.');
    res.send('게시판입니다.');
})

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

localhost:3000 - 콘솔로그 : '첫번째 실행입니다.' '두번째 실행입니다.'

                     브라우저 : 'HELLOOO'

 

localhost:3000/board - 콘솔로크 : '첫번째 실행입니다' '첫번째 실행입니다. '두번째 실행입니다.' 

                              브라우저 : '게시판입니다' 

 

- >/board 에서는 app.use(test) 도 함게 실행되서 첫번째 실행 콘솔로그가 2번 나옴. 

 

 

 

App.use vs App.get/post 의 차이 

 

app.use('/')  모 ~ 든 url을 뜻함

app.use('/board') uri 가 board 로 시작하는 모두 다 실행

 

-> 그래서 위의 코드의 경우 localhost:3000/dalksdjfalskdjf 이렇게 치면 터미널에 콘솔로그 '첫 번째 실행입니다.'  

localhost:3000/board/djkldsafkl 라고 치면 '두 번째 실행입니다' 라고 뜬다. 

 

 

 

유용한 예 

중복 코드 시 이걸 쓰면 된다.  쓰는 이유는 

const express = require('express');
const app = express();


app.get('/', (req,res)=>{
    console.log('두번째 실행입니다.');
    res.send('hello world!');
})

app.get('/list',(req,res)=>{
    let url=`http://localhost${req.url}`;
    console.log('client가 요청한 url : '+url);
    console.log('list입니다');
    res.send('내가list다');
})


app.get('/view',(req,res)=>{
    let url=`http://localhost${req.url}`;
    console.log('client가 요청한 url : '+url);
    console.log('view입니다');
    res.send('내가view다');
})

app.get('/write',(req,res)=>{
    let url=`http://localhost${req.url}`;
    console.log('client가 요청한 url : '+url);
    console.log('wirte입니다');
    res.send('내가wirte다');
})

app.get('/modify',(req,res)=>{
    let url=`http://localhost${req.url}`;
    console.log('client가 요청한 url : '+url);
    console.log('modify입니다');
    res.send('내가modify다');
})

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

여기서 /wirte, /modify, /view, /list 든 어떤 것 uri가 오던 나는 console.log창에 url값을 찍히게 하고 싶을 때 위와 같은 노가다를 하게 된다. 모두 /이후의 것들이기 때문에 공통의 부분을 app.use('/')로 묶어버리면 된다. 

 

app.use('/', function (req,res,next){
    let url=`http://localhost${req.url}`;
    console.log('client가 요청한 url : '+url);
    next();
})

이걸 써서 아래와 같이 코드를 조금 단순화 할 수 있다. 

req.url 은 교수님이 console.log(req); 로 찍어서 나온 결과물 중 url나오는 'url'이라는 req 객체의 속성을 찾은 것

const express = require('express');
const app = express();

app.use('/', function (req,res,next){
    let url=`http://localhost${req.url}`;
    console.log('client가 요청한 url : '+url);
    next();
})

app.get('/', (req,res)=>{
    console.log('두번째 실행입니다.');
    res.send('hello world!');
})

app.get('/list',(req,res)=>{
    console.log('list입니다');
    res.send('내가list다');
})


app.get('/view',(req,res)=>{
    console.log('view입니다');
    res.send('내가view다');
})

app.get('/write',(req,res)=>{
    console.log('wirte입니다');
    res.send('내가wirte다');
})

app.get('/modify',(req,res)=>{
    console.log('modify입니다');
    res.send('내가modify다');
})


app.listen(3000,()=>{
    console.log('server start port : 3000');
})

 

그럼 localhose:3000/write 을 입력하면 요렇게 나온다. 

1. get('/write')요청 -> 2. app.use('/') -> 3. app.get('/list') 응답. 

 

 

 

 

------------------------> 여기까지가 middle ware를 쓰는 이유 

 

 

 

HTTP STATUS CODE 

브라우저 Page 가 잘 열리면 200 그게 아니면 404 

 

 

http status code from developer.mozilla.org/ko/docs/Web/HTTP/Status

 

HTTP 상태 코드 - HTTP | MDN

HTTP 상태 코드BCD tables only load in the browser HTTP 응답 상태 코드는 특정 HTTP 요청이 성공적으로 완료되었는지 알려줍니다. 응답은 5개의 그룹으로 나누어집니다: 정보를 제공하는 응답, 성공적인 응

developer.mozilla.org

 

이를 이용해서 not found page를 만들기 

/* ★ 미 들 웨 어 ★ */
const express=require('express');
const app = express();

app.get('/',(req,res)=>{
    res.send('치킨먹고싶다');
})

app.use((req,res,next)=>{
    res.status(404).send("That's an error.")
})

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

app.use((req,res,next)=>{}) 여기서 '/' 생략 가능- default 값 : '/' 

 

 

 

 

이렇게 page를 꾸밀 수도 있음. 

 

 

 

 

 

-------------------------------------------------------실 습-------------------------------------------------------

 

 Router 활용하여 파일 분산시키기 

1. Server.js 에 Index.js 파일 연결하기 

파일 세팅 하기 - 파일 경로가 왔다갔다 하면 헷갈려서 오늘 한대로 그대로 다시 만듬  

앞으로 만들 구조는 

server.js 를 index.js (게시판의 초입) board.js (게시판 보기, 쓰기, 수정, 등등 부분) 으로 나눔

여기서 먼저 큰 세세한 부분을 만들고 구조를 나누려니 헷갈렸다. 

 

 

이제 Server.js 부터 작성

/* ★ 미 들 웨 어 ★ */
const express=require('express');
const app=express();
const main=require('./routes/index');


app.use('/', main); 

app.get('/',(req,res)=>{                /// 요건 비교위해 쓴 것 . 추후 삭제 함 
    res.send('router is on')
})


app.listen(3000,()=>{
    console.log('server start port : 3000');
})

기본 express 작성하는 구조에 

const main = require('/'routes/index') 

app.use('/', main); 을 추가 했다. 

localhost:3000/ 기본 주소를 받으면 main이라는 객체(변수)를 사용해라 ! 

그리고 main이라는 변수 안에는 routes폴더 안 index.js 파일을 넣을거다. 

 

**여기서 특이한 점 

const main=require('./routes/index');

 

 

const main=require('./routes');

요렇게 가능 (반드시 파일 명이index 만 가능) 

 

 

 

index.js 파일을 작성하지않고 node server.js 실행하면 

요런 에러가 뜬다. 

'/'을 받아 main (index.js)을 실행해야하는데 없어서 뜨는 것 같다. 

 

 

 

index.js

/* Server.js -> Index.js */
const express=require('express'); 
const router = express.Router(); //////////////////////변경 1 

router.get('/',(req,res)=>{      //////////////////////변경 2
    res.send('index.js이다.')
})

module.exports=router;           //////////////////////변경 3

는 server.js 의 연결된 js으로 sub.js 이다. 

최초 js가 아닌 파일은 위와 같이 

const app=express ------------> const router=express.Router(); 로 변경

app.get('/',(req,res)=>{})) ------> router.get('/',(req,res)~  으로 변경 

app.listen(3000, ()=>{})  -------> module.exports=routerl 로 변경

 

최초의JS가 아닌 연결된 js들은 위와 같은 3가지 주의사항이 있음 

 

이렇게 index.js 까지 하고 node server.js 로 실행해보면 

 

요렇게 뜬다. 

/* ★ 미 들 웨 어 ★ */
const express=require('express');
const app=express();
const main=require('./routes/index');


app.use('/', main); 

app.get('/',(req,res)=>{
    res.send('router is on')
})


app.listen(3000,()=>{
    console.log('server start port : 3000');
})

여기서 app.use가 app.get 보다 위에 있어서 main.js가 실행됨

만약 app.get이 use위에 있다면 브라우저에는 'router is on' 이 뜨게됨 

 

 

 

 

2. server.js 에 board.js 연결 

위와 똑같이 server.js 에 board.js 연결 추가 , board.js 작성

 

server.js

/* ★ 미 들 웨 어 ★ */
const express=require('express');
const app=express();
const main=require('./routes/index');
const board=require('./routes/board');          ///////////// 추가 1 

app.use('/', main);
app.use('/board', board);                     /////////////// 추가 2

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

 

board.js

/* 내가 BOARD 다  */
const express=require('express');
const router=express.Router();

router.get('/', (req,res)=>{    /// == /board라는 뜻 
    res.send('I am the BOARD');
})

module.exports=router;

**주의할 점** 쓰다가 틀린 점 ** 

router.get('/', ) -> 요 부분의 / 이후에는 board 가 생략된것... 

 

server.js 에서 연결할 때 연결 /url 

main 이라는 객체는 / 이후에 쓴다. board라는 객체는 /board 이렇게 쓸꺼다. 

그리고 board.js 들어가면 / = /board 

 

 

/board 를 지면 결과물 

 

 

 

 

 

 

3. Board.js 에 list, write, view, modify 등 만들기 

board.js에 추가

/* Server.js --> board.js  */
const express = require('express');
const router = express.Router();

router.get('/list', (req,res)=>{
    res.send('LIST in board.js')
})

router.get('/view', (req,res)=>{
    res.send('VIEW in board.js')
})

router.get('/write', (req,res)=>{
    res.send('WRITE in board.js')
})

router.get('/modify', (req,res)=>{
    res.send('MODIFY in board.js')
})

module.exports=router;

 

창에 입력할 때 localhose:3000/board/list 요렇게 써야함 ** board는 생략된 상태 

 

-------------------------------------------------------여기까지 외우기---------------------------------------------------

 

 

 

4. nunjucks 작동 시키기 (html 연결) 

html연결을 위한nunjucks  작동 해보기 

Visual Studio - terminal : npm install nunjucks chokidar  설치 

server.js, index.js,... 관련 파일들 nunjucks 추가 + htmls 작성

 

server.js

/* ★ 미 들 웨 어 ★ */
const express=require('express');
const app = express();
const nunjucks = require('nunjucks');       //nunjucks 추가 1
const main = require('./routes/index');
const board = require('./routes/board');

nunjucks.configure('view',{                 //nunjucks 추가 2 (view폴더 환경설정)
    express:app,
})

app.set('view engine', 'html');             //nunjucks 추가 3 view engine을 html으로
app.use('/', main);
app.use('/board', board);

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

index.js

/* Server.js -> Index.js */
const express=require('express');
const router=express.Router();

router.get('/', (req,res)=>{
    res.render('index.html',{
        title:'안녕!',
    })
    
})

module.exports=router;

board.js

/* Server.js --> board.js  */
const express=require('express');
const router=express.Router();

router.get('/list', (req,res)=>{    
    res.render('board/list.html');
})

router.get('/view', (req,res)=>{
    res.render('board/view.html');
})

router.get('/write', (req,res)=>{
    res.render('board/write.html');
})

router.get('/modify', (req,res)=>{
    res.render('board/modify.html');
})

module.exports=router;

여기서 중요한 점 ! 

res.render('어떤파일') -> 파일을 선택해 줄 때 view/board/modify.html 이 아니라 boar/modify.html 이다. 

왜냐하면 nunjucks 설정 시 app.set('view', {express:app}) "view" 파일을 이미 설정해놔서 view를 거치지 않아도 됨. 

 

 

index.html

<!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>Document</title>
</head>
<body>
    {{titile}}<br/>
    나는 index 메인이지. 
</body>
</html>

list.html

<!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>Document</title>
</head>
<body>
    나는 list야호
</body>
</html>

view.html

<!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>Document</title>
</head>
<body>
    나는 view야 
</body>
</html>

write.html

<!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>Document</title>
</head>
<body>
    나는 write이야호
</body>
</html>

modify.html

<!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>Document</title>
</head>
<body>
    나는 modify야 
</body>
</html>

 

 

---------------------------------------------------------------------------------------------------------------------------------

 

 

5. css, js 등 공유를 위한 html 묶기  

nunjucks 사용할 폴더 view 안에 layout 폴더 생성 -> bottom, top.html 만들기 

 

top 에는 <body> 시작 이전까지 담기 

bottom 에는 </body> 끝 전까지 담기 

 

그리고 html 에 top, bottom 에 나눠 담은 공통 부분들을 다 지우고 

{% include "../layout/top.html' %} include함수 + 경로 지정해준다. (파일의 위치마다 경로가 다르니 주의 ) 

 

{ } -> nunjucks 사용할꺼야

&& - > nunjucks 기능 활용할꺼야

 

-> css를 위한 <link rel="tylesheet" href=""> 요거를 이제 top에다가 한 번만 쓰면 모든 html이 공유. (js도!) 

 

index.html/list/view/write/modify.html

*여기서 틀린점 : index.html 에서 경로 지정을 다른 html 파일들처럼 ../layout/top.html 이렇게 지정했더니 오류남. 

index.html은 잘 보면 view 파일의 직속 파일이므로 ./layout/top.html 이렇게 한번만 위로 올라가서 layout파일로 경로타면 됨 !! 파일 경로 타는게 헷갈린다. 

include 경로는 nunjucks 에 맞춰서 생각

<a href="/board/list"> 이건 server기준 

 

* 다시 만들다가 또 틀린점 -> {% include "./layout/top.html" %} ->  .html 안쓰면 오류남. 

 

 

 

 

 

 

6. method="post" 위한  body-parser 설치 

npm install body-parser 설치 

body-parser관련 js 추가 

 

server.js

/* ★ 미 들 웨 어 ★ */
const express=require('express');
const app = express();
const nunjucks = require('nunjucks');   
const main = require('./routes/index');
const board = require('./routes/board');
const bodyParser=require('body-parser');  //////////// body-parser 추가요 ~ 1

nunjucks.configure('view',{                
    express:app,
})

app.use(bodyParser.urlencoded({extended:false}));  //////////// body-parser 추가요 ~ 2
app.set('view engine', 'html');           
app.use('/', main);
app.use('/board', board);

app.listen(3000,()=>{
    console.log('server start port : 3000');
})

board.js

/* Server.js --> board.js  */
const express=require('express');
const router=express.Router();

router.get('/list', (req,res)=>{    
    res.render('board/list.html');
})

router.post('/list', (req,res)=>{    ////// post 받는거 추가요 ~ 
    res.redirect('/board/list');
})

router.get('/view', (req,res)=>{
    res.render('board/view.html');
})

router.get('/write', (req,res)=>{
    res.render('board/write.html');
})

router.get('/modify', (req,res)=>{
    res.render('board/modify.html');
})

module.exports=router;

write.html 부분만 post 사용함

{% include "../layout/top.html" %}


    나는 wirte이야호

    <form method="post" action="/board/list">   /////////////post로 넘길거 추가요 ~ 
        <input >
        <input  type="submit" value="submit">


    </form>


{% include "../layout/bottom.html" %}

 

 

 

 

---------------------------------------------------------요기까지 정리 ---------------------------------------------------------

 

 

router 쓸 js 파일을 Server.js에 추가  index.js  / board.js 작성 index,list,write등 html 작성 및 연결
최초 js인 server.js에 
객체 생성 
const mian = require('path')
* router 사용
app.use('/', main); 
* router 객체 생성
const router = express.Router();
* router.get 이용 
* port 는 module.exports=router;로 연결하기
요html에는 router 연결을 위한 무언가 쓰는게 사실 없음. 
css,js 공유를 위한 include함수 쓸 때 수정 필요

 

 

 

 

---------------------------------------------------------------------------------------------------------------------------------

 

 

 

6. DB 연결을 위한 mysql 연결 및 작성  

npm install mysql 

 

mysql관련 3가지 작성 

쓰는 곳은 원래는  server.js 이지만 connection이라는 변수를 쓸 곳은 board.js이기 때문에 현재로서는 일단 board.js에다가 추가함. 추후 connection pool 이라는 것을 사용해서 더 편하게 바꿀 예정

 

const mysql=require('mysql');

let connection = mysql.createConnection({
    host:'localhost',
    user:'root',
    pasword:'holololo',
    database:'homepage1'
})

connection.connect();

아래 그림 보면 server.js 에 connection 설정하고 board.js에서 connection 변수를 사용 - 연결 안됨 X 

 

 

 

----------------------------------------------------총 정 뤼------------------------------------------------------

 

 

 

 Router 활용하여 파일 분산시키기 

1. Server.js 에 Index.js 파일 연결하기 

2. server.js 에 board.js 연결 

3. Board.js 에 list, write, view, modify 등 만들기 

4. nunjucks 작동 시키기 (html 연결) 

5. css, js 등 공유를 위한 html 묶기  

6. DB 연결을 위한 mysql 연결 및 작성 

 

 

 

 

 

 

방금 복습한 수업 내용 

blckchainetc.tistory.com/74

 

[32일차] 20210427 라우터 middle ware 사용해서 express server 분산시켜 만들기 배움

라우터 없어도 서버를 만들 수 있지만 많은 정보 (?) 가 들어갈 수록 떠 깔끔하게 + 더 관리를 잘 하도록 쓰는거다.  middle ware url 바로 써서 보내기 -> get input form -> post Client가 req 요청 보낼 때 ap..

blckchainetc.tistory.com

 

 

 

 

 

------------------------------------------------------------------------------------------------------------------------------

server.js

const express=require('express');
const app=express();
const main=require("./routes/index");
const board=require("./routes/board");
const nunjucks = require('nunjucks');
const bodyParser=require('body-parser');

nunjucks.configure('view',{
    express:app,
})

app.use(bodyParser.urlencoded({extended:false}));
app.set('view engine', 'html');
app.use(express.static('public'));

app.use('/', main);
app.use('/board',board);


app.listen(3000,()=>{
    console.log('server start port is 3000');
})

index.js

const express=require('express');
const router=express.Router();

router.get('/', (req,res)=>{
    res.render('index.html');
})

module.exports=router;

board.js

const express=require('express');
const router=express.Router();
const mysql=require('mysql');

let connection = mysql.createConnection({
    host:'localhost',
    user:'root',
    password:'0000',
    database:'homepage1'
})

connection.connect();

router.get('/list',(req,res)=>{

    connection.query("select *, date_format(today, '%H:%i %d.%m.%Y') as today, date_format(motoday, '%H:%i %d.%m.%Y') as motoday from board order by idx desc", (error,results)=>{
        if(error){ 
            console.log(error);
        }else{
            console.log(results);

            let total_record = results.length;
            results.forEach(ele=>{
                ele.number = total_record;
                total_record--;
            })
            console.log(results);

            res.render('board/list.html',{  
                board_db:results, 
            })
        }
    })
})

router.get('/write',(req,res)=>{
    res.render('board/write.html')
})

router.post('/writedone',(req,res)=>{
    let subject = req.body.subject;
    let writer=req.body.writer;
    let content=req.body.content;
    let sql=`insert into board (subject,writer,content, today, hit) values ('${subject}','${writer}','${content}', now(),0)`

    connection.query(sql,(error,results)=>{
        if(error){
            console.log(error);
        }else {
            res.redirect('/board/list');  
        }
    })
})

router.get('/view',(req,res)=>{
    let idx = req.query.idx;
    console.log(idx);
    
    connection.query(`select * from board where idx='${idx}'`,(error,results)=>{
        if(error){
            console.log(error)
        }else{
            console.log(results)
            res.render('board/view.html',{
                view_db:results[0],
                
            });
        }
    })

    connection.query(`update board set hit=hit+1 where idx='${idx}'`);
    
})

router.get('/modify',(req,res)=>{
    let idx=req.query.idx;

    connection.query(`select * from board where idx=${idx}`,(error,results)=>{
        if(error){
            console.log(error)
        }else{
            console.log(results);
            res.render('board/modify.html',{
                modify_db:results[0],
            });
        }
    })
})

router.post('/modifydone',(req,res)=>{
    let idx = req.body.idx;
    console.log(req.body);
    let subject = req.body.subject;
    let writer = req.body.writer;
    let content = req.body.content;

    let sql = `update board set subject='${subject}', writer='${writer}', content='${content}', motoday=now() where idx='${idx}'`;

    connection.query(sql,(error,results)=> {
        if(error){
            console.log(error);
        }else{
            console.log(results);
            res.redirect('/board/list');
        }
    })
})

router.get('/delete',(req,res)=>{
    
    let idx=req.query.idx;
    let sql=`delete from board where idx='${idx}'`;
    connection.query(sql,(error,results)=>{
        if(error){
            console.log(error);
        }else{
            res.redirect('/board/list');
        }
    })
})

module.exports=router;

index.html

{% include "./layout/top.html" %}

<div class="wrap">
    <div class="outerbox" >
        <div class="innerbox">
            <h2 class="welcome">WELCOME!</h2> 
            <div id = "gogobox">
                <a  id="gogo" href="/board/list" >게시판 구경하기</a>
            </div>
        </div>
    </div>
</div>


{% include "./layout/bottom.html" %}

list.html

{% include "../layout/top.html" %}

<div class="wrap">
    <div class="outerbox" >
        <div class="innerbox">
            <h2 class="main">게시판</h2>
            <div class="mainbox">
                <table id="table1">
                    <tr id ="fields" class="tb">
                        <td class="td0">
                            <span>All</span>
                            <span><input name="chk" type="checkbox" onclick="checkAll()"></span>
                            
                        </td>
                        <td class="td1">번호</td>
                        <td class="td2">제목</td>
                        <td class="td3">작성자</td>
                        <td class="td4">수정 날짜</td>
                        <td class="td4">작성 날짜</td>
                        <td class="td5">조회수</td>
                    </tr>
                    <tr class="tb">{% for item in board_db %}
                        <td class="td0"><input  name="chk" type="checkbox" ></td>
                        <td class="td1">{{item.number}}</td>
                        <td class="td2" id="aa"><a href="/board/view?idx={{item.idx}}">{{item.subject}}</a></td>
                        <td class="td3">{{item.writer}}</td>
                        <td class="td4">{{item.motoday}}</td>
                        <td class="td4">{{item.today}}</td>
                        <td class="td5">{{item.hit}}</td>
                    </tr>{% endfor %}
                </table>
                <div class="btnbox">
                    <button class="btn"><a href="/">돌아가기</a></button>
                    <button class="btn"><a href="/board/write">글쓰기</a></button>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">

    function checkAll(checkAll){
        console.log(checkAll);
        let checkboxes=document.getElementsByName("chk");
        console.log(checkboxes);
        checkboxes.forEach((checkbox)=>{
            checkbox.checked=checkAll.checked;
        })
    }

</script>

{% include "../layout/bottom.html" %}

view.html

{% include "../layout/top.html" %}
<div class="wrap">
    <div class="outerbox" >
        <div class="innerbox">

                <h2 class="main">VIEW PAGE </h2>
                <div class="mainbox1">
                        <div class="subbox">
                            <div class="subsubbox">
                                <span class="sub">글 번호 :</span>
                            </div>
                            <input class ="txbox" type="text" name="subject" disabled value="{{view_db.idx}}"> 

                        </div>
                        <div class="subbox">
                            <div class="subsubbox">
                                <span class="sub">제목 :</span>
                            </div>
                            <input class ="txbox" type="text" name="subject"  disabled  value="{{view_db.subject}}"> 

                        </div>
                        <div class="wribox">
                                <div class="subsubbox">
                            <span class="wri">작성자 :</span>
                                </div>
                            <input class = "txbox" type="text" name="writer"  disabled  value="{{view_db.writer}}">
                            <br/>
                        </div>
                        <div class="d">
                            <div class="subsubbox">
                                <span class="con">내용 :</span>
                            </div>
                            <input class = "conbox" type="text"   disabled  name="content" value="{{view_db.content}} ">
                               
                        </div>
                </div>

            <div class="btnbox" class="btnbox3">   
                <button class="btn"><a href="/board/list">뒤로가기</a></button>
                <button class="btn"><a href="/board/modify?idx={{view_db.idx}}">글 수정하기</a></button>
                <button class="btn"><a href="/board/delete?idx={{view_db.idx}}">글 삭제하기</a></button>
            </div>
        </div>
    </div>
</div>

{% include "../layout/bottom.html" %}

write.html

{% include "../layout/top.html" %}

내가 write이야

<div class="wrap">
    <div class="outerbox" >
        <div class="innerbox">
            <h2 class="main"> 글 작성하기</h2>
            <form method="post"  action="/board/writedone">
                <button type=submit name = "name" disabled onclick="enter()"; style="display:none;"></button> <!-- enter하면 입력되지 않도록 방지-->
                <div class="mainbox">
                    <div class="subbox">
                        <div class="subsubbox">
                            <span class="sub">제목 :</span>
                        </div>
                        <input id="subject_tx" class ="txbox" type="text" name="subject"> 

                    </div>
                    <div class="wribox">
                            <div class="subsubbox">
                        <span class="wri">작성자 :</span>
                            </div>
                        <input id="writer_tx" class = "txbox" type="text" name="writer">
                        <br/>
                    </div>
                    <div class="d">
                        <div class="subsubbox">
                            <span class="con">내용 :</span>
                        </div>
                        <textarea id="content_tx" onckeyup="enter()" class = "conbox" type="textbox" name="content"> </textarea>
                        <!--textarea name="content"></textarea-->
                                
                    </div>
                </div>

                <div class="btnbox">       
                    <button class="btn"><a href="/board/list">돌아가기</a></button>
                    <input class ="btn" type="submit" value="글작성" onclick="val()">
                </div> 
            </form>
        </div>
    </div>
</div>
<script type="text/javascript">
    function val (){
        let subject_tx = document.getElementById("subject_tx");
        let writer_tx = document.getElementById("writer_tx");
        let content_tx = document.getElementById("content_tx");

        if(subject_tx.value==""){
            alert("제목을 입력해주세요르레히호");
            event.preventDefault();
        } else if(writer_tx.value==""){
            alert("작성자를 입력해주세요");
            event.preventDefault();
        } else if(content_tx.value==""){
            alert("내용을 입력해주세요");
            event.preventDefault();
        }
    }
    function enter(){
        if(window.event.keyCode ==13){
            alert("d");
        document.getElementsByName("content").innerHTML+="<br/>";
    }
}
</script>

{% include "../layout/bottom.html" %}

modify.html

{% include "../layout/top.html" %}

<div class="wrap">
    <div class="outerbox" >
        <div class="innerbox">
            <h2 class="main"> 글 수정하기 </h2>
            <form method="post" action="/board/modifydone">
                <button disabled type=submit onclick="return flase;" style="display:none;"></button> <!--enter하면 입력되지 않도록 방지-->
                <div class="mainbox">
                    <div class="subbox">
                        <div class="subsubbox">
                            <span class="sub">글 번호 :</span>
                        </div>
                        <input class="txbox" type="text" name="idx" value="{{modify_db.idx}}" readonly >
                    </div>
                    <div class="subbox">
                        <div class="subsubbox">
                            <span class="sub">제목 :</span>
                        </div>
                        <input id ="subject_tx" class="txbox" type="text" name="subject" value="{{modify_db.subject}}"> 
                    </div>
                    <div class="wribox">
                        <div class="subsubbox">
                            <span class="wri">작성자 :</span>
                        </div>
                        <input id="writer_tx" class="txbox" type="text" name="writer" value="{{modify_db.writer}}"> 
                    </div>
                    <div class="d">
                        <div class="subsubbox">
                            <span class="con">내용 :</span>
                        </div>
                        <input id="content_tx" class="conbox" type="text" name="content" value="{{modify_db.content}}"> 
                    </div>
                </div>


                <div class ="btnbox">
                    <button class ="btn"><a href="/list">돌아가기</a></button>
                    <input class ="btn" type="submit" value="글 수정 완료" onclick="val()">
                </div>
                </form>
            </div>

        </div>
    </div>
</div>
<script type="text/javascript">
    function val (){
        let subject_tx = document.getElementById("subject_tx");
        let writer_tx = document.getElementById("writer_tx");
        let content_tx = document.getElementById("content_tx");

        if(subject_tx.value==""){
            alert("제목을 입력해주세요르레히호");
            event.preventDefault();
        } else if(writer_tx.value==""){
            alert("작성자를 입력해주세요");
            event.preventDefault();
        } else if(content_tx.value==""){
            alert("내용을 입력해주세요");
            event.preventDefault();
        }
    }
</script>

{% include "../layout/bottom.html" %}

 

top.html

<!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>Document</title>
    <link rel="stylesheet" href="../index.css">
    <link href="https://fonts.googleapis.com/css2?family=Gaegu&family=Gamja+Flower&display=swap" rel="stylesheet">
</head>
<body>

bottom.html

</body>
</html>

index.css

*{
    margin:0;
    padding:0;
    font-family: 'Gamja Flower', cursive;    

}



a{
    text-decoration: none;
    color:black;
    
}

a:hover{
    color:lightcoral;
}

ul,li{
    list-style: none;
}



/*         in COMMON         */




.wrap{
    width:100%;
    background-color: rgb(218, 157, 153);
}

.outerbox{
    width:100%;
    height:100%;
    
}

.innerbox{
    background-color: white;
    width:1080px;
    height:750px;
    border: 2px solid rgb(202, 202, 202);
    border-radius: 2px;
    position: absolute;
    left:50%;
    transform: translateX(-50%);
    top:8%;

}
#gogo{
    width:100px;
    height:50px;
    background-color: white;
    border-radius: 5px;
    padding:5px;
    box-sizing: border-box;
}

#gogo:hover{
    transition: .5s ease-in-out;
    background-color: darkseagreen;
    color:white;
}

.main{
    width:1080px;
    height:80px;
    text-align: center;
    font-size:50px;
    color:salmon;
    margin-top:30px;
}


.mainbox{
    width:1000px;
    height:550px;
    padding:20px 20px 20px 38px;
}

.mainbox1{
    width:1000px;
    height:520px;
    padding:20px;
}

.btn{
    width:120px;
    height:40px;
    font-size: 16px;
    background-color: lightcoral;
    border-radius: 4px;
    border:1px solid lightcoral;
    color:white;
    align-items: center;
    margin-left: 20px;

}

.btn:hover{    
    color:lightcoral;
    background-color: white;
    border:2px solid lightcoral;
}

.btnbox{
    width:500px;
    height:50px;
    position: absolute;
    top: 660px;
    left: 54%;
    
}


.btn>a{
    padding:10px;
}



.subbox,.wribox{
    width:940px;
    height:40px;

}

.subsubbox{
    width:100px;
    height:40px;
    display: inline-block;
    float:left;
    text-align: center;
    padding: 0 0 0 7px;
    box-sizing: border-box;
}

.conbox{
    width:835px;
    /* height:400px; */
    float:left;
    display: inline;
    border:1px solid darkslategray;
    text-align: left;
    padding:10px 0 350px 7px;
    box-sizing: border-box;
}

.sub,.wri,.con{
    font-size: 20px;
    line-height: 35px;
    text-align: center;
}

.txbox{
    width:835px;
    height:35px;
    border:1px solid darkslategray;
    padding:5px;
    box-sizing: border-box;
    
}


input{
    width:100%;
    
}







/*          index            */

.welcome{
    width:1000px;
    height:200px;
    color:darkseagreen;
    text-align: center;
    padding:90px 0 0 0 ;
    font-size:70px;
    display:inline-block;
}

#gogobox{
    width:1000px;
    height:400px;
    padding:250px 0 0 550px;
    display:inline-block;
    box-sizing: border-box;
}

#gogo{
    font-size: 40px;
    text-align:center;
    color:darkslategray;

}





/*          board           */

#table1{
    border:1px solid rgba(221, 220, 220, 0.994);
    box-sizing: border-box;
    border-collapse:collapse;
}

#fields{
    color:rgb(48, 48, 48);
    font-size: 20px;
    text-align: center;
    background-color: rgb(255, 227, 232);
    font-weight: bold;
}   



td{
    text-align: center;
    border:1px solid rgba(221, 220, 220, 0.994);
    box-sizing: border-box;
}

#aa{
    text-align:center;
}


.td0{
    width:100px;
    height:40px;
    padding:9px 0;
}
.td0>span>input{
    width:15px;

}

.td1{
    width:70px;
    height:40px;
    
}


.td2{
    width:400px;
    height:40px;
}

.td3{
    width:150px;
    height:40px;
}

.td4{
    width:200px;
    height:40px;
}

.td5{
    width:100px;
    height:40px;
}

 

 

 

 

 

 

----------------------------------------------------------------------------------------------------------------------------------

 

 질문 1 

 

 

1. next(test) 라는 값을 넣을 때 왜 function 전체가 뜨는지? ? 

test를 넣었으니까... 그 뒤로는 실행 안됨. 

 

 

 질문 2  

bodyparser 추가구문 require & urlencoded.가 없어도 왜 post가 넘어가지?? 

넘ㄱ어가기도 하는데 잘 모르겠음.. 

서버 통신에 의해 넘어가기는 하는데

bodyParser는 넘어간 값을 가져오기 위해 쓰는거기 때문에 

 

 질문 3 

redirect 정확하게 이해하기 render와의 차이

redirect : link와 같은 의미 

html 로 치면 a tag

 

render : html가져와서 그 내용을 표현해주는거

 

            document.write('<div class="wrap"></div>');

            res.render('board/list.html',{   요렇게 

 

 

render 하려면 render 쓴것처럼 다시 sql 거 다 다시 가져와야함 

 

 질문 4 

 

{% include "path/index.html" %}

.html 안쓰면 오류나는 이유 

html도 view 폴더 안에 있어서 nunjucks 되지 않는지?? 

html 애들 in view 폴더 = nunjucks 언어로 이루어져잇음. 

 

{% include  ../layout/top.html" %} = 본이 위치로 경로가 시작됨. nunjucks의 언어 임. html이 아니야. 자기파일 기준으로 생각 

 

 

 질문 5 

leejungyeoul.tistory.com/83

 

node server/npm mysql/connection pool 구현

connection pool(CP)의 정의는 '소프트웨어 공학에서 데이터베이스로의 추가 요청이 필요할 때 연결을 재사용할 수 있도록 관리되는 데이터베이스 연결의 캐시'이다.  사이트에 사용자가 접속하면

leejungyeoul.tistory.com

여기의 코드에서 

router.use(bodyParser.json());의 뜻

router.use(bodyParser.urlencoded({exteneded:true})); 의 뜻 객체 안 객체 생성 허락 

json -  > JS 의 객체 

서버 통신할 떄 좋다. 

 

 질문 6 

 

board.js 와 list 아래 코드 관계 

 <td class="td2" id="aa"><a href="/board/view?idx={{item.idx}}&number={{item.number}}">

get 값을 넘겨 주는 것

get 은 ? endpoint? 뒤로 부터 써서 전달 
post 는 name 안에 들은 값을 body로 전달 

 

 

질문7

pool 

* pool을 여러개 만든다는 건 ??x  -> 이미 limit: 10 에서 10개 쓸 수 있도록 만듬 

const mysql=require('mysql');

const config1 = {
    host:'localhost',
    user:'root',
    password:'root',
    database:'homepage1',
    connectionLimit:10
}

const config2 = {
    host:'localhost',
    user:'root',
    password:'root',
    database:'homepage1',
    connectionLimit:10
}

const config3 = {
    host:'localhost',
    user:'root',
    password:'root',
    database:'homepage1',
    connectionLimit:10
}

const pool1 = mysql.createPool(config1);
const pool2 = mysql.createPool(config2);
const pool3 = mysql.createPool(config3);

pool1.getConnection((err,connection)=>{
    if(err) throw err;
    
    connection.query("select * from board", (error,results,fields)=>{
        connection.release();
        if(error) throw error;
        results.render('index.html',{
            list:results
        });
    })
})

pool2.getConnection((err,connection)=>{
    if(err) throw err;
    
    connection.query("select * from board", (error,results,fields)=>{
        connection.release();
        if(error) throw error;
        results.render('index.html',{
            list:results
        });
    })
})
pool3.getConnection((err,connection)=>{
    if(err) throw err;
    
    connection.query("select * from board", (error,results,fields)=>{
        connection.release();
        if(error) throw error;
        results.render('index.html',{
            list:results
        });
    })
})
반응형