티스토리 뷰

services 폴더에는 controller에서 필요한 기능(함수)들을 보관했다.


starbucks_controller.js

import { Starbucks } from "../models/starbucks.model.js";

export class StarbucksController {
  getStarbucks = async  (req, res) => {
    const result = await Starbucks.find();
    res.send(result);
    return;
  };
}

스타벅스컨트롤러다. 겟 함수가 있는데, 모델을 통해서 디비에 있는 데이터를 모두 가져오란 뜻이다.


getStarbucks가 어디서 쓰이는지 알아보자.

index.js는 MVC 패턴에 영향을 받지 않는다. 

 

index.js

import express from "express";
import swaggerUi from "swagger-ui-express";
import swaggerJsdoc from "swagger-jsdoc";
import dotenv from "dotenv";
import mongoose from "mongoose";
import cors from "cors";
import { options } from "./swagger/config.js";

import { TokenController } from "./controllers/token_controller.js";
import { UsersController } from "./controllers/users_controller.js";
import { StarbucksController } from "./controllers/starbucks_controller.js";

const app = express();
app.use(express.json());
app.use(cors());
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerJsdoc(options)));
dotenv.config();

const tokenController = new TokenController();
app.get("/tokens/phone", tokenController.getToken);
app.post("/tokens/phone", tokenController.postToken);
app.patch("/tokens/phone", tokenController.patchToken); 

const usersController = new UsersController();
app.get("/users", usersController.getUsers);
app.post("/users", usersController.postUsers); 

const starbucksController = new StarbucksController();
app.get("/starbucks", starbucksController.getStarbucks); // 여기에서 쓰인다

mongoose.connect("mongodb://my_database:27017/codecamp");

app.listen(3000);

StarbucksController 객체를 만들어서 getStarbucks함수를 쓴다. 하지만 (), 소괄호는 쓰지 않는다. 함수를 바로 실행하고 싶지 않기 때문이다. 여담으로 js에선 함수또한 한 객체이다. 따라서 이렇게 쓰기가 가능하다.

 

TokenController 마찬가지로 자신의 함수를 썼다. TokenController를 써보자.

 


 

token_controller.js

import { Token } from "../models/token.model.js";
import {
  checkValidationPhone,
  getToken,
  sendToken2SMS,
} from "./sevices/token_services/phone.js";

export class TokenController {
  getToken = async (req, res) => {
    console.log(res);
    const result = await Token.find();
    res.send(result);
    return;
  };

  postToken = async (req, res) => {
    console.log(req.body);
    const phone = req.body.phone;
    // 1. 휴대폰 번호 자리수 확인
    if (!checkValidationPhone(phone)) {
      res.send(false);
      return;
    }
    const myToken = getToken(6);
    // 3. 휴대폰 번호에 토큰 전송, 위치 다시 생각해보자
    // sendToken2SMS(phone, myToken); // 정말로 보내지니 쓸 때만 주석 해제

    // 입력받은 폰번호랑 같은 객체 찾는다.
    const prevTokenPhone = await Token.findOne({ phone: phone });

    // 이미 있다면 최신 토큰으로 덮어씌우기
    if (prevTokenPhone) {
      prevTokenPhone.token = myToken; 
      await Token.updateOne({ phone: phone }, { token: myToken });
      res.send(true);
      return;
    }

    const token = new Token({
      token: myToken,
      phone: phone,
      isAuth: false, // 자동으로 주자.
    });
    await token.save(); // 몽고디비로 저장된다. 좀 기다려줘
    res.send(true);
    return;
  };

  patchToken = async (req, res) => {
    const phone = req.body.phone;
    const token = req.body.token;
    //! 핸드폰 번호 이미 저장됐는지 확인
    const tokenPhone = await Token.findOne({ phone: phone });

    // 토큰자체가 디비에 없다면
    if (!tokenPhone) {
      res.status(422).send("휴대폰 인증하세요.");
      return;
    }

    //! 발급한 토큰과 일치하는지 확인
    if (tokenPhone.token !== token) {
      console.log(tokenPhone);
      res.status(422).send("토큰 인증이 올바르지 않습니다.");
      return;
    } else {
      console.log(tokenPhone);

      await Token.updateOne({ phone: phone }, { isAuth: true });
      res.send(true);
      return;
    }
  };
}

getToken, postToken, patchToken으로 나눴다. 기능은 기존과 마찬가지다. 하지만 이렇게 나눠놓으면 보기도 편하며 나중에 관리할 때 수월해진다.

 

service폴더에서 controller에 쓰이는 기능들을 담아놨다. 알아보자


token_services에는 phone.js를 담고 있다. 

phone.js

import axios from "axios";
 

export const checkValidationPhone = (myphone) => {
  if (myphone.length !== 10 && myphone.length !== 11) {
    console.log("에러 발생! 핸드폰 번호를 제대로 입력해 주세요!!!");
    return false;
  } else {
    return true;
  }
}

export const getToken = (num) => {
  //   const num = 6;
  if (num === undefined) {
    console.log("error occured num === undefined, type the right number");
    return;
  } else if (num <= 0) {
    console.log("error occured num <= 0 , type the right number");
    return;
  } else if (num > 10) {
    console.log("error occured num > 10, type the right number");
    return;
  }
  const result = String(Math.floor(Math.random() * Math.pow(10, num))).padStart(
    num,
    "0"
  );
  return result;
}

export  const sendToken2SMS = async (phoneNumber, tokenNumber) => { // phoneNumber 받는 번호, tokenNumber 인증번호

  const appKey =  process.env.SMS_APP_KEY;
  const senderPhoneNum = process.env.SMS_SENDER;
  const XSecretKey = process.env.SMS_X_SECRET_KEY;

  await axios.post(
    // ------------ app key, secret key 같은 중요한 건 환경변수로 깃에 올리지 않는다 .env에 간다
    `https://api-sms.cloud.toast.com/sms/v3.0/appKeys/${appKey}/sender/sms`, // <-------- 내걸로 바꿀 부분 appkey
    //data, 필수요소 3인방!
    {
      body: "인증번호 : [ " + tokenNumber + " ]",
      sendNo: senderPhoneNum, // 보내는 휴대폰번호
      recipientList: [
        // 받을 사람
        {
          internationalRecipientNo: phoneNumber, // 이 한 줄만 써도 된다
        },
      ],
    },
    //header, config
    {
      headers: {
        "X-Secret-Key": XSecretKey, // <-------- 내걸로 바꿀 부분
        //-----------------------blog 쓸 것-----------------------------------------
        // 키를 큰 따옴표로 한 이유: - 는 큰 따옴표로 감싸야 정상 작동되기 때문
        "Content-Type": "application/json;charset=UTF-8",
        //----------------------------------------------------------------
      },
    }
  );
  console.log("전송 완료");
  console.log(tokenNumber + "보내는 사람, " + phoneNumber + "받는사람");
}

전에는 서술 안했지만 SMS전송은 NHN Cloud를 이용했다. 

token에서 쓰인 함수들을 모아뒀다.


유저도 마찬가지로 get post로 나눴다. 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
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
글 보관함