작은 도서관
article thumbnail
Published 2021. 10. 7. 17:52
[koa] mongoose 연결 / CRUD 코딩/백엔드

사용 라이브러리

    "@koa/router": "^10.1.0",
    "@types/dotenv": "^8.2.0",
    "@types/mongoose": "^5.11.97",
    "koa": "^2.13.1",

개요

  • mongoose를 koa 프로젝트에서 사용하기
  • mongoose를 사용하여 User 모델 제작
  • restfulAPI로 라우터 구축
  • UserCRUD 제작

1. mongoose를 koa 프로젝트에서 사용하기

import mongoose from 'mongoose';

// 주로 사용하는 mongoose 연결 템플릿.
mongoose.connect(
  process.env.DB_URI!,
  {
    user: process.env.DB_USER,
    pass: process.env.DB_PASSWORD,
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  },
  (err) => {
    if (err) {
      throw err;
    }
  },
);

dotenv를 사용하여 호스트와 유저네임/비밀번호를 지정하고 기타 설정을 해둔 템플릿이다.

JSON형식의 설정이 편해서 이 버전을 사용하고 있으나 최신버전에선 적용이 안되니 사용 전에 확인할 필요가 있다.

해당 템플릿을 app.ts파일에 추가한다.

 

2. User 모델 제작

Edrawmind 처음 써보는데, 워터마크가 있는줄 몰랐네요... 딴거 써야지

유저 형식에는 위와 같은 내용이 포함되어야한다.

import { createSchema, Type, typedModel } from 'ts-mongoose';

// 스키마 지정
const UserSchema = createSchema(
  {
    name: Type.string({ required: true }),
    email: Type.string({ required: true, unique: true }),
    password: Type.string({ required: true }),
    salt: Type.string({ required: true }),
  },
);

// 여기서부턴 내보내기
const User = typedModel('User', UserSchema);

export default User;

간단하게 타입과 옵션을 지정하여 스키마로 만들 수 있다.

스키마를 통해서 모델 인스턴스로 만들어 사용하면 된다.

 

3. 라우팅

auth는 다음에 설명

api 구조를 간략하게 도식화하면 이렇다.

delete와 patch는 params 매개변수로 유저의 고유 id를 받아야한다.

 

먼저 라우터를 만들어야한다.

src 하위에 router라는 폴더를 만들고 index.ts를 다음과 같이 작성한다.

import Router from '@koa/router';

import auth from './auth';
import user from './user';

const router = new Router();

router.use('/user', user.routes());
// 아직 구현하지 않았으니 이 줄은 추가하지 않아도 무관함
// 혹은 주석처리 해두세요.
router.use('/auth', auth.routes());

export default router;

이제 router 폴더 아래에 위 코드의 8번째줄을 받을 user.ts를 작성한다.

import Router from '@koa/router';

import {
  create, get, remove, update,
} from '../controllers/user';

const router = new Router();

router.post('/', create);
router.get('/', get);
router.delete('/:id', remove);
router.patch('/:id', update);

export default router;

위와같이 작성했다면 앱에서 사용할 수 있게 된다.

다음을 app.ts에 추가한다.

import router from './router';

// 중략. 미들웨어 다음에 넣을것을 권장함

app.use(router.routes());

라우터가 완성되었다!

 

4. UserCRUD 제작

유저 정보를 저장하기 앞서, 유저 모델 도표에 있는 비밀번호의 암호화 기능을 만들어야한다.

이러한 기능들은 보통 컨트롤러에서 처리하는게 아니라 모듈화해서 따로 서비스로 만든다.

src 하위에 services 폴더를 만들고, 그 안에 user.ts 파일을 만들고 다음을 작성한다.

import { pbkdf2Sync, randomBytes } from 'crypto';

export const passwordEncryption = (password: string) => {
  const salt = randomBytes(16).toString('base64');
  const result: Array<string> = [pbkdf2Sync(password, salt, 10000, 64, 'SHA512').toString('base64'), salt];
  return result;
};

단순하게 문자열을 입력받아 암호화한 문자열 / 암호화한 키를 배열로 리턴하는 함수이다.

그 아래 유저 정보를 저장하기 위해서 다음을 추가한다.

import User from '../models/User';

// 중략

export const userRegistration = async (
  name: string,
  email: string,
  password: string,
  salt: string,
) => {
  const user = new User({
    name,
    email,
    password,
    salt,
  });

  try {
    await user.save();
    return user;
  } catch (e) {
    return e;
  }
};

유저 정보를 저장할 준비가 끝났다.

src 하위에 controllers 폴더를 만들고 user.ts 파일에 다음을 작성한다.

import { Context } from 'koa';

import User from '../models/User';
import { passwordEncryption, userRegistration } from '../services/user';

export const create = async (ctx: Context) => {
  const { name, email, password } = ctx.request.body;

  const EncryptedPassword = passwordEncryption(password);
  userRegistration(name, email, EncryptedPassword[0], EncryptedPassword[1]);
  ctx.status = 200;
};

유저 데이터를 모두 가져오는 함수 get도 추가한다.

export const get = async (ctx: Context) => {
  const id = ctx.request.body;

  try {
    const user = await User.findById(id).exec();

    if (!user) {
      ctx.status = 404;
      ctx.body = { message: 'user not found' };
      return;
    }

    ctx.body = user;
  } catch (e) {
    ctx.throw(500, e);
  }
};

유저 데이터를 삭제하는 함수 remove도 추가한다.

export const remove = async (ctx: Context) => {
  const id = ctx.params; // 매개변수는 이런식으로 접근함

  try {
    await User.findByIdAndRemove(id).exec();
    ctx.status = 200;
  } catch (e) {
    ctx.throw(500, e);
  }
};

마지막으로 유저 정보를 업데이트하는 함수 update를 추가한다.

export const update = async (ctx: Context) => {
  const { name, email, password } = ctx.request.body;
  const id = ctx.params;

  try {
    const user = User.findByIdAndUpdate(id, name, email, password);
    ctx.body = user;
    ctx.status = 200;
  } catch (e) {
    ctx.throw(500, e);
  }
};

마치며

다른 프레임워크에서 CRUD를 만들어봤고, 만들 줄 안다! 하는 사람 기준으로 작성된 글입니다.

다음엔 jwt 토큰 인증 방식을 사용하여 로그인과 인증 기능을 올릴 예정입니다.

댓글 질문은 늘 받고있어요!

profile

작은 도서관

@Flrea

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!