티스토리 뷰

백엔드

Node.js API server 학습하기

초딩영웅 2018. 9. 2. 16:32

Node.js

  • https://nodejs.org/ko/
  • 비동기(논 블럭킹 IO) 이벤트 기반, 이벤트 루프(드라이븐), 싱글쓰레드
  • 호출과 처리(실행)과 결과 프로세스
    : 호출스택(콜스택) > 이벤트 루프 > 태스크 큐 > 이벤트 루프 > 호출스택(콜스택)
  • 4. 태스크 큐에 들어가는 경우
    : setInterval, setTimeout, setImmediate, Promise resolve & reject, async & await, 이벤트리스너의 콜

module

  • 모듈이 될 파일은 module.exports = 값; 마지막에 붙여야 함.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const a = 'a';
    const b = 'b';
    // 모듈을 내보낼때
    module.exports = {
      a: a,
      b: b
    }
    // es6
    module.exports = {
      a,
      b
    }
    // another
    exports.a = a;
    exports.b = b;
    cs
  • 하나의 모듈안에 다른 모듈들을 의존해서 사용 가능.
  • 불러올때

    1
    2
    3
    4
    // import module
    const a = require('./var'// .js 는 생략가능
    // es6
    const {a, b} = require('./var'// 비구조화 활당
    cs

global (전역객체)

  • web 상에서 쓰는 window 라는 전역객체 처럼 node.js에서 쓰는 전역객체
  • global 이 가지는 함수들을 사용할때는 global 표기를 생략해서 사용할 수 있다.

http module

  • node.js 자체는 runtime 역할만 할뿐 서버가 아니다.
  • http module 을 사용하여 서버 역할을 하게 한다.
  • 사용방법
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const http = require('http')
     
    http.createServer((req, res) => {
      console.log('server start..')
    }).listen(3000, () => {
      console.log('server starting to port 3000')
    })
     
    // server에 대한 응답
    const server = http.createServer((req, res) => {
      console.log('server start..')
    }).listen(3000)
     
    server.on('listening', () => {
      console.log('server starting to port 3000')
    })
    server.on('error, (err) => {
      console.error(err)
    })
    cs

npm (node package manager)

  • node.js 에서 사용하는 module 들을 관리해 준다.
  • 사용방법
    1
    2
    3
    4
    5
    npm init # npm 에서 정의하는 패키지를 생성. 모듈을 만드는 기반이 된다. 명칭은 다른 사람의 패키지명과 겹치지 않게 한다.
    npm install [패키지명] # 다른 패키지를 현재 프로젝트에 모듈 기반으로 설치하게 한다.
    npm install [패키지명] --save [or --save-dev] # 설치할 패키지를 package.json 에 명시하며 dev는 개발상에서만 사용하도록 설치.
    npm i -D [패키지명] # = npm install --save-dev
    npm i --global [패키지명] # 명령어(서비스)로 쓸수 있게 패키지를 설치. -g
    cs

express framework

  • node.js 에서 server 를 구성하기 위한 최소한의 기능들을 제공하는 패키지
  • java 에서 spring 과 같은 개념이다.
  • 가장 많이 사용하는 framework
  • command
    1
    2
    3
    4
    5
    6
    npm i -g express-generator # express framework 를 쉽게 설치할 수 있는 명령어를 가능하게 하는 패키지
    npm express [프로젝트명] --view-pug # 자신만의 express framework을 만든다. view를 pug 로 정의함. 기본은 jade
    npm install # express 에서 의존되야할 패키지들을 설치한다. node_module 폴더가 생성되며 그 안에 패키지들이 들어감.
    npm start # 서버 실행. port 3000 of default
    npm run start # package.json 안에 scripts 에서 정의한 start 명령어를 실행하라는 의미. 하지만 start 명령어는 run을 제외해도됨.
    npm run dev # starts 안에 dev 명령어를 정의해야함.
    cs

app.js

  • node.js의 핵심부. 다른 개발자들은 index.js 로 정의 하기도 한다.
  • express 모듈을 사용하여 실행.
  • command
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const app = express()
     
    // 1. 외부 모듈 정의 (예, 디비설정 등)
     
    // 2. express 옵션 정의
     
    // 3. router의 기능
    app.get('/', (req, res) => {
      res.send('helloworld')
    }
     
    // 4. 에러 핸들
    cs

router

  • crud, rest api 를 서버에서 정의하는 모듈.
  • router 모듈을 이용해서 구조화 할 수 있음.
  • command
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // from app.js
    const usersRouter = require('./route/users')
     
    app.use('/users', usersRouter)
     
    // from users.js
    const express = require('express')
    const router = express.Router()
     
    router.get('/:id', (req, res, next) => {
      res.send('get api ' + req.params.id)
    })
    router.post('/', (req, res.next) => {
      res.send('post api ' + req.body.id)
    })
    router.put('/:id', (req, res.next) => {
      res.send('put api ' + req.params.id)
    })
    router.delete('/:id', (req, res.next) => {
      res.send('delete api ' + req.params.id)
    })
    router.patch('/:id', (req, res.next) => {
      res.send('patch api ' + req.params.id)
    })
     
    module.exports = router
    cs

error handling

  • next(err) 함수를 사용한다.
  • app.js 에 정의한 에러 함수로 빠지면서 결과를 반환한다.
  • source
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // catch 404 and forward to error handler
    app.use((req, res, next) => {
      const err = new Error('api not found')
      err.status = 404
      next(err)
    })
     
    // error handler
    app.use((err, req, res, next) => {
      // set locals, only providing error in development
      res.locals.message = err.message
      res.locals.error = req.app.get('env'=== 'development' ? err : {}
     
      // render the error page
      res.status(err.status || 500)
      err.success = false
      debug('error')(err)
     
      // bug fix : front error handling
      if (err.name === 'UnauthorizedError'delete err.code
     
      return res.json(err)
    })
    cs

dotenv

  • 환경설정 값을 관리 할 수 있는 패키지 유틸.
  • production or development 설정을 따로 분기하여 배포가능하다.
  • 오픈된 소스 저장소에는 해당 파일을 제외하고 올려야 한다.
  • 다수의 시크릿 설정값들이 들어감.
  • process.env.[컬럼명] 으로 값을 호출 가능.
  • source
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // from .env
    // 파일을 생성하고 설정값을 정의함.
    MONGODB_CONNECTION = mongo://...
     
    // from app.js
    // .env 파일 설정을 불러오는 부분
    require('dotenv').config()
    // 또한 production or development 단계를 분기할 때, 파일 분기 방법중에 하나
    require('dotenv').config({path: './config/env/' + process.env.NODE_ENV + '/.env'})
    cs

API Access Token

  • JWT (Json Web Token)
  • 토큰안에 정보를 담고 base64 인코딩하여 API 헤더에 넣고 서버에 호출 하는 방식
  • 중요한 정보는 제외하고 해당 회원의 아이디를 담아는게 일반적.
  • 다른 인증 방식과 다르게 API 서버 처음에 자체적으로 회원인증이 필요없음. I/O를 줄일 수 있다.
  • Node.js 에서는 jsonwebtoken 패키지를 사용한다.
  • API 호출하는 곳에서는 header 영역에 토큰을 담아 전송하면 된다.
  • source
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // from signup.js
    // 정상 가입 후에 accessToken를 서버에서 발급
     
    // from signin.js
    // 정상 로그인 후 accessToken를 서버에서 발급
     
    // create accessToken
    // SECRET: .env 파일에 jwt secret id 를 정의한 값 (노출되면 안됨)
    jwt.sign(
        { // playload
          mid: member._id, // 회원아이디
          rol: member.role // 회원권한
        },
        Buffer.from(process.env.JWT_SECRET, 'base64'), // secret
        { // option
          issuer: DOMAIN,
          expiresIn: '1d' // one day 기한이 설정됨.
        },
        (err, token) => { // callback with async
          if (err) return callback({code: 512, message: err})
          if (!token) return callback({status: 401, message: 'not create token..'})
     
          return token
        })
     
    // Authentication accessToken
    // from api.js
    // 정상 인증이 되면 req.user 객체에 토큰 내용이 담겨 진다.
    // 아래 처럼 req.auth 객체에 담도록 다르게 설정가능.
    // jsonwebtoken 패키지의 기능으로 인증할 수 있지만 express-jwt 패키지를 사용하여 쉽게 구현이 가능.
    // 인증 라우터 위치는 / 루트에 정의해야 한다.
    const jwt = require('express-jwt')
     
    router.use('/',
      jwt({
        requestProperty: 'auth',  // req.auth
        secret: Buffer.from(process.env.SECRET, 'base64')
        // audience: '123'
      }),
      (req, res, next) => {
        if (!req.auth) return res.status(401).json({success: false, code: 401, message: 'not set auth object in req'})
        // console.log(req.auth);
        next()
      })
    cs


'백엔드' 카테고리의 다른 글

JavaScript의 변화 (CMAScript 2015 ~)  (0) 2018.09.02
Authenticate a Node.js API with JSON Web Tokens  (0) 2015.10.29
[mysql] about with linux  (0) 2015.10.08
댓글