Express 기초 공부하기

dana·2022년 10월 3일
6

backend

목록 보기
7/7
post-thumbnail

현재 회사에서 백엔드 코드를 express를 이용해 짜고 있었는데, 기본적인 개념 없이 필요에 따라 공부해 작성하고 있었어서 express 기초부터 공부해보려고 한다. Express 공식 웹사이트에서 제공하는 starter instruction을 따라 진행했다.

기본 셋팅

설치 방법

연습 버전

node.js가 이미 설치되었다는 전제하에 테스트할 폴더 생성하기
만약 node.js가 없다면 https://nodejs.org/en/ 에서 LTS 버전으로 설치!

npm init

npm init으로 package.json을 생성해준다. package.json 파일은 프로젝트의 config에 영향을 받는 내용으로 구성되어있다.
해당 명령어를 입력하게 되면 차례대로 다음과 같은 설정 입력 인풋이 뜨는데, 엔터를 눌러 기본 설정으로 셋팅해주면 된다.

다만 여기서 entry pointindex.js 대신 app.js로 설정해주어 실행시 메인 파일이 app.js로 동작하도록 해주도록 권장하는데 만약 그냥 엔터를 눌러 이미 생성해버렸다면, package.json 파일에 들어가서 수정해주면 된다.

npm install express`

그 다음 npm install express를 입력해 express를 설치해준다.

서버가 잘 동작하는 지, 잘 설치되었는지 확인하기 위해 앞서 메인 파일로 지정한 app.js 파일을 생성해준다.

// app.js
const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

app.js에 다음의 코드를 작성하고 node app.js를 입력해 실행시켜 준다. 터미널에 코드에서 설정한 메세지가 찍히고, http://localhost:3000/ 으로 이동하면 실행된 노드 환경을 볼 수 있다.

이렇게 만들어진 서버는 실시간으로 변경사항이 반영되는데, Runkit이라는 프로그램을 통해 노드가 웹사이트 상에서 보여질 수 있도록 도와준다.

express-generator

위에 작성된 코드는 '/' 라우팅에만 대응된 코드기 때문에 다른 패스로 이동시 404 에러가 발생하게 된다. 다양한 js코드를 커버하기 위해선 위와 같이 일일히 파일을 생성하는게 아니라 Express generator를 이용해 프로젝트를 생성해주어야 한다.

npx express-generator

express-generator를 이용해 프로젝트를 생성하면 app.js를 포함한 다음과 같은 파일들이 자동으로 생성된다.
안내된 대로 의존성 설치를 위해 npm install 실행 후, 서버를 동작시키기 위해 다음의 명령어를 입력해준다.

//mac
DEBUG=(프로젝트명):* npm start
DEBUG=express:* npm start

//window
set DEBUG=(프로젝트명):* & npm start
set DEBUG=express:* & npm start

그럼 http://localhost:3000/ 에 다음과 같은 화면이 뜨게 된다.

응용하기

기본 라우팅 설정

Routing은 클라이언트가 url이나 method에 따라 특정 endpoint로 요청을 보낼 때, 어떻게 응답할지 정해두는 코드다.

app.METHOD(PATH, HANDLER)
  • app : express의 인스턴스
  • METHOD : HTTP 요청 메소드 (get, post, put, delete)
// GET method route
app.get('/', (req, res) => {
  res.send('GET request to the homepage')
})

// POST method route
app.post('/', (req, res) => {
  res.send('POST request to the homepage')
})
  • PATH : endpoint의 path
  • HANDLER : 루트가 일치하는 경우, 실행되는 함수
    • http://localhost:3000이라는 endpoint에 /home이라는 Path를 지정하는 경우, http://localhost:3000/home 로 요청시 Handler 동작하도록 설정한다.
    • Handler는 무조건 하나일 필요는 없다. next라는 argument를 제 3의 인자로 받을 수 있어, 다음 Handler가 실행되도록 할 수 있다.
const cb0 = function (req, res, next) {
  console.log('CB0')
  next()
}
const cb1 = function (req, res, next) {
  console.log('CB1')
  next()
}
const cb2 = function (req, res) {
  res.send('Hello from C!')
}
app.get('/example/c', [cb0, cb1, cb2])

응용 라우팅

app.all()

어떤 method든 상관없이 실행되는 method이다.

app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...')
  next() // pass control to the next handler
})

app.route()

같은 path를 가진 서로 다른 메소드들을 하나로 묶어서 표현할 수 있다.

app.route('/book')
  .get((req, res) => {
    res.send('Get a random book')
  })
  .post((req, res) => {
    res.send('Add a book')
  })
  .put((req, res) => {
    res.send('Update the book')
  })

path에 패턴 사용하기

path에는 문자열, 문자열패턴, 정규식을 사용할 수 있다. 그 중 ? + * ()는 와일드카드의 형태로 사용되며, -.은 문자 그대로 인식된다. 만약 달러 사인($)을 원하는 경우, ([\$]) 의 형식으로 사용 할 수 있다.
/book/$test => /book/([\$])test

path값 그대로 해석

app.get('/', (req, res) => {
  res.send('root')
})
// http://localhost:3000/

app.get('/about', (req, res) => {
  res.send('about')
})
// http://localhost:3000/about

app.get('/random.text', (req, res) => {
  res.send('random.text')
})
// http://localhost:3000/random.text

와일드카드 사용

? : 왼쪽 단어 0개 혹은 1개

app.get('/ab?cd', (req, res) => {
  res.send('ab?cd')
})
// http://localhost:3000/acd
// http://localhost:3000/abcd

+ : 왼쪽 단어 1개 이상

app.get('/ab+cd', (req, res) => {
  res.send('ab+cd')
})
// http://localhost:3000/abbcd
// http://localhost:3000/abbbbbbcd
// http://localhost:3000/abcd

* : 단어 0개 혹은 여러개 추가

app.get('/ab*cd', (req, res) => {
  res.send('ab*cd')
})
// http://localhost:3000/ab12345cd
// http://localhost:3000/abTESTcd
// http://localhost:3000/abcd

() : 괄호 안 문자에 대해 와일드카드 설정 가능

app.get('/ab(cd)?e', (req, res) => {
  res.send('ab(cd)?e')
})
// http://localhost:3000/abcde
// http://localhost:3000/abe

동적 path 생성하기

path의 값이 동적으로 바뀌는 경우, 해당 값을 req.param을 이용해 가져올 수 있다. req.param은 key와 value로 구성되어있는데, 해당 키 값을 path에 다음과 같이 설정해주면 endpoint와 함께 넘어온 value값을 받아 사용할 수 있다.

app.get('/users/:userId/books/:bookId', (req, res) => {
  const {userId, bookId} = req.param
  // http://localhost:3000/user/minju/book/dictionary
  // req.param == {userId : 'minju', bookId : 'dictionary'}

  res.send(userId + bookId) // minjudictionary
})

-.이 문자열로 취급되기 때문에 다음과 같이 사용도 가능하다.

Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }

정적 파일 제공하기

이미지나 css 파일 등 정적인 파일을 제공하기 위해서 express 내장 미들웨어를 이용할 수 있다.

express.static(root, [options])

만약 public 폴더에 다음과 같은 파일이 있는 상태에서, public 폴더에 접근 할 수 있도록 해주면, endpoint를 이용해 해당 정적 파일에 접근 할 수 있다.

app.use(express.static('public'))

app.use(express.static('public'))
app.use(express.static('files'))

해당 설정을 여러개 설정해 둘 수도 있다. 이런 경우 최적화 작업을 위해 역방향 프록시(reversed proxy)를 사용하는 것을 추천한다.

만약 해당 endpoint에 prefix를 추가하고 싶다면, 첫번째 인자로 path를 작성해 줄 수 있다.

app.use('/static', express.static('public'))
// http://localhost:3000/static/images/test.jpeg

express.static('public')에 들어가는 path는 상대 경로기 때문에 만약 다른 폴더에서 실행하게 되면 에러가 발생할 수 있다. 따라서 안전하게 사용하기 위해 path.join을 이용해 절대경로로 설정해주어야 한다.

const path = require('path')
app.use('/static', express.static(path.join(__dirname, 'public')))

express.Router

app을 쪼개서 사용할 수 있도록 도와주는 핸들러다. 미들웨어가 특정 라우터를 사용 할 수 있도록 해주고, path에 따라 라우터를 쪼개서 관리할 수 있게 해준다.

// color.js
import express from express
export const ColorRouter = express.Router()

ColorRouter.get('/red', HANDLER)
// http://localhost:3000/colors/red 로 접근 시 실행
...
// app.js
import {ColorRouter} from './color'

// ...

app.use('/colors', colors)

다음 게시글은 express-generator 사용시 기본값으로 생성되는 app.js에 작성된 코드를 뜯어보고자 한다. 🧐

app.js 기본 코드
profile
PRE-FE에서 PRO-FE로🚀🪐!

2개의 댓글

comment-user-thumbnail
2022년 10월 3일

Express까지 점령하는 천재 개발자...

1개의 답글