Skip to content

dhshffnfn123/blog-backend

Repository files navigation

💻 Back-end

자바스크립트로 서버를 구현할 수 있는 Node.js와 MongoDB를 사용하여 블로그 백엔드 구현

스키마

필드 이름 데이터 타입 설명
title 문자열 제목
body 문자열 내용
tags 문자열 배열 태그 목록
publishedDate 날짜 작성 날짜

🛠 Install

Koa
eslint-config-prettier
nodemon
koa-router
koa-bodyparsera
mongoose
dotenv
esm
joi
bcrypt
jsonwebtoken
sanitize-html
koa-static


🧩 Node.js

웹 브라우저에서만 사용하던 자바스크립트를 서버에서도 사용할 수 있는 런타임을 개발한 것

Koa

  • 미들웨어 기능만 갖추고 있으며 나머지는 다른 라이브러리를 적용하여 사용한다. (가벼움)
  • async/await 문법을 정식으로 지원하기 때문에 비동기 작업을 더 편하게 관리할 수 있다.
  • app.use : 미들웨어 함수를 애플리케이션에 등록한다.
  • app use를 사용하여 등록되는 순서대로 처리된다.
  • Koa의 미들웨어 함수는 두개의 파라미터를 받는다. (ctx, next) => { ... }
    • ctx는 Context의 줄임말로 웹 요청과 응답에 관한 정보를 지니고 있다.
    • next는 현재 처리 중인 미들웨어의 다음 미들웨어를 호출하는 함수이다.
    • next를 호출하지 않으면, 그 다음 미들웨어를 처리하지 않는다.
    • next 함수를 호출하면 Promise를 반환한다.
  • 쿼리 파라미터는 문자열이다.

koa-router

  • router.get : 첫 번째 파라미터에는 경로를 넣고, 두 번째는 해당 라우트에 적용할 미들웨어 함수를 넣는다.
  • get 키워드는 해당 라우트에서 사용할 HTTP 메서드를 의미한다.
  • 라우터의 파라미터를 설정할 때는 /about/:name 형식으로 콜론을 사용하여 라우트 경로를 설정한다.
    • 파라미터가 있을수도 있고 없을수도 있다면 /about/:name? 와 같이 ?를 붙인다.
    • 설정한 파라미터는 함수의 ctx.params 객체에서 조회할 수 있다.
  • URL 쿼리의 경우, 해당 값을 ctx.query에서 조회할 수 있다. (ex: /posts/?id=10)
    • 쿼리 문자열을 자동으로 객체 형태로 파싱해 주므로 별도로 파싱 함수를 돌릴 필요가 없다.
    • 쿼리 문자열을 조회할 때는 ctx.querystring을 사용한다.

REST API

  • REST API는 요청 종류에 따라 다른 HTTP 메서드를 사용한다.
    • GET : 데이터 조회 시 사용
    • POST : 데이터를 등록할 때 사용
    • DELETE : 데이터를 지울 때 사용
    • PUT : 데이터를 새 정보로 통째로 교체할 때 사용
    • PATCH : 데이터의 특정 필드를 수정할 때 사용
  • REST API를 설정할 때는 API 주소와 메서드에 따라 어떤 역할을 하는지 쉽게 파악할 수 있도록 작성해야 한다.
  • ❗ 포스트 수정 API를 PUT으로 구현할 때는 모든 필드가 다 있는지 검증하는 작업이 필요하다.

koa-bodyparser

POST/PUT/PATCH 같은 메서드의 Request Body에 JSON 형식으로 데이터를 넣어주면, 이를 파싱하여 서버에서 사용할 수 있게 한다.

  • 컨트롤러는 exports.이름 = ... 형식으로 함수를 내보내주면 다음과 같은 형식으로 불러올 수 있다.
    const 모듈이름 = require('파일이름');
    모듈이름.이름();
    

🍃 MongoDB

문서 지향적 NoSQL 데이터베이스
이 데이터베이스에 등록하는 데이터들은 유동적인 스키마를 지닐 수 있다.
데이터의 구조가 자주 바뀐다면 MongDB가 더 유리하다.

mongoose

  • mongoose는 Node.js 환경에서 사용하는 MongoDB기반 ODM 라이브러리이다.
  • 이 라이브러리는 데이터베이스 문서들을 자바스크립트 객체처럼 사용할 수 있게 해준다.

detenv

  • 환경변수들을 파일에 넣고 사용할 수 있게 해주는 개발도구이다.

Schema

Schema 는 컬렉션에 들어가는 문서 내부의 각 필드가 어떤 형식으로 되어 있는지 정의하는 객체이다.

Schema에서 지원하는 타입

타입 설명
String 문자열
Number 숫자
Date 날짜
Buffer 파일을 담을 수 있는 버퍼
Boolean true & false 값
Mixed(Schema.Types.Mixed) 어떤 데이터도 넣을 수 있는 형식
ObjectId(Schema.Types.ObjectId) 객체 아이디, 주로 다른 객체를 참조할 때 넣음
Array 배열 형태의 값으로 []로 감싸서 사용

model() 함수

  • 기본적으로 두개의 파라미터가 필요하다. 하나는 스키마의 이름이고, 또 하나는 스키마 객체이다.
  • 데이터베이스는 스키마 이름을 정해주면 그 이름의 복수 형태로 컬렉션 이름을 만든다.
    • 예를 들어 Post로 이름을 설정하면 컬렉션 이름은 posts가 된다.
    • 이 컨벤션을 따르고 싶지 않다면, 세번째 파라미터에 원하는 이름을 입력하면 된다.

CRUD

✔ 모든 함수를 호출한 후에는 exec()를 붙여 주어야 서버에 쿼리를 요청한다.

데이터 조회

  1. find() : 데이터 조회
  2. findById : 특정 id를 가진 데이터 조회

데이터 삭제

  1. remove() : 특정 조건을 만족하는 데이터를 모두 지운다.
  2. findByIdAndRemove() : id를 찾아서 지운다.
  3. findOneAndRemove() : 특정 조건을 만족하는 데이터 하나를 찾아서 제거한다.

데이터 수정

  • findByIdAndUpdate() : 데이터를 업데이트 한다.
    • 이 함수는 세 가지 파라미터를 넣어주어야 한다.
      1. id
      2. 업데이트 내용
      3. 업데이트의 옵션

🔍 요청 검증

ObjectId 검증

id가 올바른 형식인지 검증하는 방법

import mongoose from 'mongoose';
const { ObjectId } = mongoose.Types;
ObjectId.isValid(id);

Request Body 검증

모든 값을 전달 받았는지 검증하는 방법
> ✔ src/api/posts/posts.ctrl.js 참고

📖 페이지네이션 구현

로딩 지연과 트래픽 낭비를 방지하기 위한 페이지네이션(pagination) 기능 구현

sort()

  • 내림차 및 오름차로 정렬한다.
  • exec()를 하기 전에 sort() 구문을 넣는다.
  • sort함수의 파라미터는 { key : 1 } 형식으로 넣는다.
    • key는 정렬할 필드를 설정하는 부분이다.
    • 오른쪽 값을 1로 설정하면 오름차순으로, -1로 설정하면 내림차 순으로 정렬한다.

limit()

  • 한번에 보이는 갯수를 제한
  • exec()를 하기 전에 limit() 구문을 넣는다.
  • 파라미터에는 제한할 숫자를 넣는다. ex : limit(10)

skip()

  • 데이터를 특정 갯수를 넘기며 보여준다.
  • 함수의 파라미터에는 (page - 1) * 10을 넣어주면 10개씩 불러오게 된다.

lean()

  • 데이터를 처음부터 JSON 형태롤 조회할 수 있다. (toJSON 생략가능)
  • ✔ src/api/posts/posts.ctrl.js의 list 참고


🌟 JWT

JSON Web Token의 약자로, 데이터가 JSON으로 이루어져 있는 토큰을 의미한다.

세션 기반 인증 시스템

세션 기반 인증 시스템에서 사용자가 로그인을 하면, 서버는 세션 저장소에 사용자의 정보를 조회하고
세션 id를 발급한다. 발급된 id는 주로 브라우저의 쿠키에 저장한다.


  • 세션 저장소는 주로 메모리, 디스크, 데이터베이스 등을 사용한다.
  • 세션 기반 인증의 단점은 서버를 확장하기가 번거로워질 수 있다는 점이다.

토큰 기반 인증 시스템

  • 토큰은 로그인 이후 서버가 만들어 주는 문자열이다.
    • 해당 문자열 안에는 사용자의 로그인 정보와 해당 정보가 서버에서 발급 되었음을 증명하는 서명이 들어있다.(무결성)
  • 서명 데이터는 해싱 알고리즘을 통해 만들어 지는데, 주로 HMAC SHA256알고리즘이 사용된다.
  • 서버에서 사용자 로그인 정보를 기억하기 위해 사용하는 리소스가 적다.
  • 사용자 쪽에서 로그인 상태를 지닌 토큰을 가지고 있으므로 서버의 확장성이 매우 높다.

모델 메서드

모델 메서드는 모델에서 사용할 수 있는 함수를 의미하며, 두 가지 종류가 있다.

인스턴스 메서드

모델을 통해 만든 문서 인스턴스에서 사용할 수 있는 함수를 의미한다.

const user = new User({ username: 'velopert' });
user.setPassword('mypass123');

스태틱 메서드

모델에서 바로 사용할 수 있는 함수를 의미한다.

const user = User.findByUsername('velopert');

Token

사용자가 브라우저에서 토큰을 사용할 때는 주로 두 가지 방법을 사용한다.
> 첫 번째 는 브라우저의 localStorage 혹은 SessionStorage에 담아서 사용하는 방법이다.
> 두 번째 는 브라우저의 쿠키에 담아서 사용하는 방법이다.


  • 브라우저의 localStorage 혹은 SessionStorage에 토큰을 담으면 사용하기가 매우 편리하고 구현이 쉽다.
    • 악성 스크립트를 삽입해 토큰을 탈취하는 XSS(Cross Site Scripting) 에 취약하다.
  • 쿠키에 담으면 httpOnly라는 속성을 활성화하면 자바스크립트를 통해 쿠키를 조회할 수 없으므로 악성 스크립트로부터 안전하다.
    • 사용자가 모르는 API를 요청하게 하는 CSRF(Cross Site Request Forgery) 라는 공격에 취약해질 수 있다.
  • iat 값은 토큰이 언제 만들어졌는지 알려주고, exp 값은 언제 만료되는지 알려주는 값이다.

sanitize-html

  • HTML을 작성하고 보여 주어야 하는 서비스에서 매우 유용하다.
  • 단순히 HTML을 제거하는 기능뿐 아니라 특정 HTML만 허용하는 기능도 있기 때문에 손쉽게 악성 스크립트 삽입을 막을 수 있다.

About

Node.js를 이용한 Back-end 공부 겸 Blog 프로젝트의 기능을 구현하는 Repo

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published