Express 란 무엇인가? 간단 사용법

임동규·2022년 2월 3일
1

express

목록 보기
1/1

Express는 뭘까?

1. Express의 정의

Express 공식사이트에 나와있는 정의는 이렇다.

Node.js를 위한 빠르고 개방적인 간결한 웹 프레임워크

2. 프레임워크란 무슨말일까?

"프레임워크란, 소프트웨어의 구체적인 부분에 해당하는 설계와 구현을 재사용이 가능하게끔 일련의 협업화된 형태로 클래스들을 제공하는 것"

그렇다. Express는 소프트웨어의 구체적인 부분에 해당하는 설계와 구현을 재사용이 가능하게끔 클래스나 함수들을 제공하면서도 손쉽게 쓸 수 있을 만큼 개방 되어 있고 간단한 프레임 워크라는 말이다.

3. 어떻게 쓸까?

- 설치방법

npm init
npm install express

역시 npm은 정말 간단하다. 저렇게만 해주면 바로 사용이 가능하다. 그렇다면 사용은?

import express from 'express'

const app = express()

app 이라는 변수에다가 express 인스턴스를 만들어주면 끝이난다.....

- express로 서버 만들기

import express from 'express'
const app = express()
const port = 3000
app.use('/',(req,res)=>{
  res.status(200).send('Hello world!')
})

app.listen(3000,(req,res)=>{
  console.log(`${port} 서버 시작!`)
})

이렇게만 만들어주면 서버 만들기 끝이다.... 정말 간단한 듯 하다.

4. Express 뜯어보기

1. 미들웨어

Express에서 미들웨어라는 개념은 핵심개념이다! 꼭 알아두어야 한다.

미들웨어의 정의

미들웨어는 컴퓨터 제작 회사가 사용자의 특정한 요구대로 만들어 제공하는 프로그램으로, 운영 체제와 응용 소프트웨어의 중간에서 조정과 중개의 역할을 수행하는 소프트웨어이다. -위키백과-

Express 에서의 미들웨어란?
요청과 응답의 중간(미들) 에 위치하여 미들웨어라고 생각하자!

익스프레스는 모든? 처리자체를 미들웨어가 수행해버린다. 그러니 꼭 이해하고 넘어가는 것이 좋다.

미들웨어 사용법

//app.use(미들웨어) 
//use 같은 메서드들에 대해선 차차 알아보도록하자.

app.use('/',(req,res,next)=>{})
//'/' 라우팅 뒤에 오는 콜백함수가 바로 미들웨어다!!!

app.use(express.json()) //req의 바디를 파싱하는 미들웨어
app.use(express.static()) //정적 파일을 보내줄 수있는 미들웨어
app.use(cookieParser());  // 쿠키를 쉽게 추출할 수 있도록 해주는 미들웨어
app.use(morgan('common'));  // 요청을 받을때마다 log를 찍어주는 미들웨어
app.use(cors()); // cors를 허용해주는 미들웨어
app.use(helmet());  //공통적으로 보안에 필요한 header 를 추가해주는 미들웨어

express에는 내장 미들웨어가 있고 외장 미들웨어(라이브러리) 를 사용하는 경우가 있으며, 자신이 콜백함수로 미들웨어를 만들어서 사용도 가능하다!

내장 미들웨어
express 공식 문서

외장 미들웨어
cors
cookieParser
morgan
helmet

위의 링크들을 참고해서 공부해보면 좋을듯 하다!


2. 미들웨어 체이닝

만약 미들웨어들이 연속적으로 일어나지 않는다면 어떤 현상이 발생할까?
하나의 미들웨어가 수행된다면 밑의 코드들은 수행이 되지 않을 것이다...

그렇다면 어떤 방식으로 체이닝을 할까?

위의 그림을 보면 next() 함수가 있다. 즉, 미들웨어들은 next() 함수를 통해서 다음 미들웨어로 이동한다는 것을 쉽게 유추할 수 있다.

그러나 만약 res.send() 나 res.json() 같이 응답을 보낸다면? next() 함수는 호출되지 않는다. 응답을 했기 때문에 더이상 체이닝을 통하지 않아도 되기 때문이다.

만약 응답을 보냈는데도 계속 체이닝을 통한다면? 쓸데 없이 자원을 소비하기도 하고 내가 원하는 응답이 아닌 다른 응답이 처리될 수도 있을 것이다.

그렇다면 우리는 미들웨어 체이닝을 통해 중요한 사실을 알 수 있다.

순서가 굉장히 중요하다!!!!

잘못된 예시


import express from 'express'
const app = express()
const port = 3000
app.get('/',(req,res)=>{
  res.status(200).send('Hello world!')
}) //get 요청시 처리할 로직

app.post('/',(req,res)=>{
  res.status(200).send('Post success')
}) //post 요청시 처리할 로직

app.put('/',(req,res)=>{
  res.status(200).send('Put Success')
}) //put 요청시 처리할 로직

app.delete('/',(req,res)=>{
  res.status(200).send('delete Success')
}) //delete 요청시 처리할 로직

app.listen(3000,(req,res)=>{
  console.log(`${port} 서버 시작!`)
})

app.use(express.json()) //req의 바디를 파싱하는 미들웨어
app.use(express.static()) //정적 파일을 보내줄 수있는 미들웨어
app.use(cookieParser());  // 쿠키를 쉽게 추출할 수 있도록 해주는 미들웨어
app.use(morgan('common'));  // 요청을 받을때마다 log를 찍어주는 미들웨어
app.use(cors()); // cors를 허용해주는 미들웨어
app.use(helmet());  //공통적으로 보안에 필요한 header 를 추가해주는 미들웨어

이런식으로 미들웨어의 순서를 정하게 된다면 밑의 유용한 기능을 가지고 있는 미들웨어를 사용할 수 없을것이다.

왜냐하면 이미 요청에 대한 응답이 보내졌을 것이기 때문에 더이상 체이닝을 하지 않기 때문이다!

참고로, 내장 미들웨어나 외장 미들웨어 들은 내부에 next함수를 가지고 있고 실행을 한다.

올바른 예시


app.use(express.json()) //req의 바디를 파싱하는 미들웨어
app.use(express.static()) //정적 파일을 보내줄 수있는 미들웨어
app.use(cookieParser());  // 쿠키를 쉽게 추출할 수 있도록 해주는 미들웨어
app.use(morgan('common'));  // 요청을 받을때마다 log를 찍어주는 미들웨어
app.use(cors()); // cors를 허용해주는 미들웨어
app.use(helmet());  //공통적으로 보안에 필요한 header 를 추가해주는 미들웨어

app.get('/',(req,res)=>{
  res.status(200).send('Hello world!')
}) //get 요청시 처리할 로직

app.post('/',(req,res)=>{
  res.status(200).send('Post success')
}) //post 요청시 처리할 로직

app.put('/',(req,res)=>{
  res.status(200).send('Put Success')
}) //put 요청시 처리할 로직

app.delete('/',(req,res)=>{
  res.status(200).send('delete Success')
}) //delete 요청시 처리할 로직

app.listen(3000,(req,res)=>{
  console.log(`${port} 서버 시작!`)
})

3. CRUD 에 따른 처리방식

!! localhost:3000 서버에 GET,POST,PUT,DELETE 하는 방식에 대해 알아보자

import express from 'express'
const app = express()
const port = 3000
app.get('/',(req,res)=>{
  res.status(200).send('Hello world!')
}) //get 요청시 처리할 로직

app.post('/',(req,res)=>{
  res.status(200).send('Post success')
}) //post 요청시 처리할 로직

app.put('/',(req,res)=>{
  res.status(200).send('Put Success')
}) //put 요청시 처리할 로직

app.delete('/',(req,res)=>{
  res.status(200).send('delete Success')
}) //delete 요청시 처리할 로직

app.listen(3000,(req,res)=>{
  console.log(`${port} 서버 시작!`)
})

코드를 보고 눈치가 빠른 분들은 눈치를 챘을 것이다. app 뒤에 붙는 메서드 이름이 HTTP Request Method 와 같다는 것을!
정말 직관적인듯 하다. 코드를 한눈에 보기만 하더라도 이게 get 요청때 처리될지, post 요청때 처리될지 알 수 있다는 것은 정말 큰 장점이다.

4. 라우팅

만약에 app.get app.post 이런것들이 너무 많아지면 어떻게 될까? 우리의 프로젝트들은 굉장히 커질 가능성이 높다. 그런데 app.js 라는 모든 로직을 우겨넣게 된다면 유지보수하기 쉬울까? 아니다. 우리는 코드를 모듈화 시켜놓는 것이 굉장히 좋다. 그래야 유지보수도 편하고 가독성도 좋다.

라우팅 안한 예시

app.get('/hello',(req,res)=>{
  res.status(200).send('Hello world!')
}) //get 요청시 처리할 로직

app.post('/hello',(req,res)=>{
  res.status(200).send('Post success')
}) //post 요청시 처리할 로직

app.put('/hello',(req,res)=>{
  res.status(200).send('Put Success')
}) //put 요청시 처리할 로직

app.delete('/hello',(req,res)=>{
  res.status(200).send('delete Success')
}) //delete 요청시 처리할 로직

app.listen(3000,(req,res)=>{
  console.log(`${port} 서버 시작!`)
})

이처럼 hello 라우팅에 대한 로직들을 한 파일에 모아둘 수 있을까?

라우팅 한 예시

// app.js
import express from 'express'
import helloRouter from './router/helloRouter.js'
app.use('/hello', helloRouter)
//hello.js
import express from 'express'

const router = express.Router()

router.use(express.json())
router.get('/',미들웨어)
router.post('/',미들웨어)
router.put('/',미들웨어)
router.delete('/',미들웨어)

export default router

hello.js 파일을 보면 express를 import 하고 express.Router 인스턴스를 만든 후 사용법은 app과 같다.

router.(메서드) 형식으로 사용한 후 export 로 router객체를 내보내 주면 끝이다!

끝마치며..

express를 배우기 전엔 http 로 서버를 만들어 보았는데 굉장히 어려웠다. 이해가 가질 않았다... 수많은 메서드들과 복잡한 로직 때문에 나는 백앤드는 평생 못배우겠구나 싶었지만
express 를 만나면서부터 조금씩 백앤드에 대해 (정말...조금이지만) 이해도 갔으며 자신감도 조금씩은 오르는 모양이다.

나처럼 정말 이해가 안가는 분들에게 조금이나마 도움이 되면 정말 뿌듯할 듯 하다.

profile
I will be Blockchain Core Developer

0개의 댓글