프로필

프로필 사진
Popomon
Frontend Developer
(2020/12 ~)

    카테고리

    포스트

    [Node/Rest API] API 리소스를 정의하는 3가지 요소

    2020. 11. 12. 15:30

    꿈가게: To Do List - iOS

    꿈가게: To Do List - Android

    모델

    데이터베이스의 스키마를 정의합니다. 각각의 테이블에 대한 스키마 및 모델 자체의 데이터를 가공하거나 비교하는 과정에서의 로직을 함수로 정의합니다. 상단에는 현재 사용하고 있는 데이터베이스 관련 모듈을 불러와서 스키마를 정의하고, 생성합니다. 그 이후에 추가할 함수 및 전처리 후처리 함수를 등록합니다. 데이터베이스 관련 라이브러리가 제공하는 설정 중에서 추가적으로 변경해야할 내용이 있다면 변경하고, 그것이 아니라면 모델을 생성해줍니다.

     

    여기서 주의해야할 점은, User 라는 모델 객체는 데이터베이스와 데이터를 주고받기 위한 객체임과 동시에, userSchema가 데이터를 담기 위한 객체에 대한 정의입니다. 따라서, User 객체를 이용하여 데이터베이스에 있는 데이터를 조회하면 그 조회된 데이터와 userSchema에 정의한 함수를 동시에 사용할 수 있습니다.

     

    // 모듈 불러오기
    const mongoose = require("mongoose");
    const Schema = mongoose.Schema;
    
    // 스키마 정의
    export const schema = {
      id: {
        sparse: true,
        type: String,
        unique: true
      },
      email: {
        required: [true, "Email is required."],
        type: String,
        unique: true
      },
      password: {
        required: [true, "Password is required."],
        type: String
      },
    };
    
    // 스키마 생성
    const userSchema = new Schema(schema, { timestamps: true });
    
    // save 함수 처리 전에 로직 정의
    userSchema.pre("save", function(next) { ... });
    
    // 함수 정의
    userSchema.methods.function1 = function( ... ) { ... };
    userSchema.methods.function2 = function( ... ) { ... };
    userSchema.methods.function3 = function( ... ) { ... };
    
    // 옵션 설정
    mongoose.set("useCreateIndex", true);
    mongoose.set("useFindAndModify", false);
    
    // 모델 정의
    export const User = mongoose.model("User", userSchema, "user");
    

     

    모델을 사용하는 방법은 아래와 같습니다. 아래의 샘플 코드를 참고하여 데이터의 조회/추가/수정/삭제에 관한 처리를 할 수 있습니다.

     

    // 데이터 조회
    const data = await User.findOne({ id: 'horong' });
    const dataList = await User.findAll();
    
    // 데이터 추가
    await User.create(
      { id: '', email: '', password: '' },
      function(err, data){ ... }
    );
    await User.insertMany(
      [
        { id: '', email: '', password: '' },
        { id: '', email: '', password: '' },
        { id: '', email: '', password: '' }
      ],
      function(err) { ... }
    );
    
    // 데이터 수정
    await User.update(
      { email:'horong@gmail.com' },
      { password: 1234 }
    );
    
    // 데이터 삭제
    await User.remove(
      { email:'horong@gmail.com' }
    );

     


    컨트롤러

    request와 response 객체를 통해서  요청을 처리하는 핸들러 함수를 정의합니다. 요청에 대한 핸들러 이외에도 공통적으로 사용되는 핸들러 함수들. 예를들면, 인증에 대한 검증, JWT 토큰으로부터 사용자 정보 추출 등의 함수는 module 폴더를 생성하여 별도로 정의해 둡니다.

     

    다음 예제코드는 인증이 된 상태를 체크하는 모듈 함수를 실행한 다음에 통과되면 요청 핸들러 함수를 실행합니다. 즉, 배열의 순서에 따라서 함수가 실행될 예정이라고 생각하시면 될 것 같습니다.

     

    const { isAuthenticated } require("../../modules/auth");
    
    const handlerFunction = [
      isAuthenticated,
      function(req, res) { ... },
    ]
    
    module.exports = {
      handlerFunction
    }

     


    라우터

    다음과 같이 해당하는 요청에 따라, 컨트롤러에서 정의한 핸들러 묶음 함수를 마지막 인자로 집어넣습니다. 첫번째와 두번째 인자는 각각 밸리데이션을 체크하는 배열과 밸리데이션에 위반될 시에 어떻게 처리할지를 정의하는 밸리데이션 핸들러 함수를 정의합니다.

     

    // 모듈
    const express = require("express");
    const { validationBody, validationResult } = require("express-validator");
    
    // 컨트롤러
    const userController = require("./user.controller");
    
    // 라우터
    const userRouter = express.Router();
    
    // URL 매핑
    userRouter.route("/hello").get(
      // 밸리데이션 조건
      [
        validationBody("id")
          .exists()
          .withMessage("Id is Empty"),
        validationBody("email")
          .exists()
          .withMessage("Email is Empty"),
      ],
      // 밸리데이션 핸들러
      (req, res) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
          return res.status(400).json({ errors: errors.array() });
        }
      },
      // 요청 핸들러
      userController.handlerFunction
    );
    
    module.exports = {
      userRouter
    }

     

    원하는 요청에 대한 처리를 다 작성하면 이 라우터 파일을 익스포트할 index.js 파일을 하나 만들어 주고 아래와 같이 입력합니다. 

     

    module.exports = require("./user.router");

     

    이렇게 하면 이제 하나의 리소스에 index.js, xxx.controller.js, xxx.model.js, xxx.router.js 총 4개의 파일이 완성됩니다.