본문 바로가기
  • 삽질하는 자의 블로그
메인-프로젝트/Next.js - 오늘 뭐먹지? 프로젝트

5. DB 연결 with. MongoDB Atlas 그리고 API

by 이게뭐당가 2022. 12. 2.

회원가입 및 로그인 페이지를 만들었으니, DB 에 연결해주어야 합니다!

 

저는 MongoDB를 사용합니다.

 

MonoDB 에 연결하려면, 패키지를 설치해야합니다.

 

https://www.npmjs.com/package/mongodb

 

mongodb

The official MongoDB driver for Node.js. Latest version: 4.12.1, last published: 9 days ago. Start using mongodb in your project by running `npm i mongodb`. There are 11303 other projects in the npm registry using mongodb.

www.npmjs.com

 

 

요로코롬 해줍니다.

 

API 에 직접 하면, 코드가 더러워지니, "리팩토링" 지금 시작합니다.

 

Helper 폴더를 만들어, db-util 파일안에, db 에 접근하는(insert, find, delete, update) 코드들을 아웃소싱합니다.

import { MongoClient } from "mongodb";

const MongodbURI =
`mongodb+srv://유저이름:패스워드@클러스터이름.xpihqcv.mongodb.net/?retryWrites=true&w=majority`;
 
export function connectDb() {
  const client = new MongoClient(MongodbURI);

  return client;
}

          이렇게, client(DB를 연결해주는) 를 빼 놓고, 필요한 요청을 하면 됩니다.

 

 

회원가입 페이지 폼에 있는 정보들을 DB에 넣도록 요청해봅시다.

 

1. 회원가입 컴포넌트로 갑니다.

  async function createUser(e) {
    e.preventDefault();

    const email = emailRef.current.value;
    const password = passwordRef.current.value;
    const name = nameRef.current.value;

    const insertUserData = {
      email,
      password,
      name,
    };

    const response = await fetch("/api/createuser", {
      method: "POST",
      body: JSON.stringify(insertUserData),
      headers: {
        "Content-Type": "application/json",
      },
    });

    if (!response.ok) {
      setSendingState(() => "error");
      setMessage("연결 실패");
    }
    const responseData = await response.json();
    setMessage(responseData.message);
    if (responseData.data) {
      setSendingState("success");
    }
  }
 
  return (
    <div className={styles.maindiv}>
      <form className={styles.signupform}>
        <h1> 회원가입</h1>
        </div>
        <div>
          <label htmlFor="email">이메일을 입력하세요</label>
          <input
            type={"email"}
            id={"email"}
            ref={emailRef}
            required
            placeholder="@를 포함하는 email을 입력해주세요"
          />
        </div>
        <div>
          <label htmlFor="password">패스워드를 입력하세요</label>
          <input
            type={"password"}
            id={"password"}
            ref={passwordRef}
            required
            maxLength={10}
            placeholder="4자리 수 이상의 문자를 입력해주세요."
   
        </div>
        <div className={styles.buttons}>
          <Button onClick={createUser}> 제출</Button>
          <button type="reset"> 취소 </button>
        </div>
      </form>
    </div>
  ); 
                   .....

PreventDefault 를 하지 않으면, SPA 의 이점이 사라집니다.

FORM은 기본적으로 HTTP 요청을 보내고,  서버는 완전한 페이지를 돌려주며, 페이지는 "새 페이지가 로드됩니다."

 

하지만 FETCH 를 통해, AJAX 요청을 했으므로,

딱 필요한 데이터만 가져와, 페이지를 로드 할 수 있습니다.

 

비동기식 요청의 장점을 살리기 위해, PreventDefault() 를 통해, Form 의 기본 기능을 막습니다.

 

useRef 로 데이터롤 가져올 곳에 접근하고

ref.current.value 에 접근해, 필요한 값을 참조하여,

객체 형태로 만들고

서버 -클라이언트 데이터 이동에는 JSON 데이터로 보내주어야 하기 때문에,

fetch 를 할때, JSON.stringfy 를 통해, 변환하고 보내주었습니다

 

다시 db-util 로 돌아가, bcrypt 를 사용해, hash 한 비밀번호와 함께, DB 로 넣는 코드를 생성합니다

export async function createUser(client, data) {
  const hashedPassword = await bcrypt.hash(data.password, 10);
  data.password = hashedPassword;
  const insertResult = await client
    .db("eating")
    .collection("userInfo")
    .insertOne(data);

  return insertResult;
}

 

이제 실제 API 에, 필요한 아웃소싱한 코드를 넣어주기만 하면 됩니다.

 

/PAGES/API 폴더에 필요한 이름의 파일을 만듭니다.

 

import { createUser, connectDb, findUserInfo } from "../../helper/db-util";
import { signupValidation } from "../../helper/validation-util";

async function handler(req, res) {
  if (req.method === "POST") {
    let client;
    try {
      client = await connectDb();
    } catch (error) {
      res.status(500).json({ message: "데이터베이스 연결 오류" });
      throw new Error("연결 오류");
    }

    const { email, password, name } = req.body;

    if (signupValidation(email, password, name)) {
      res.status(400).json({ message: "정보를 다시 확인해주세요" });
      throw new Error("정보를 다시 확인해주세요");
    }
    const userData = {
      email,
      password,
      name,
    };

    const sameEmailUser = await findUserInfo(client, userData.email);

    if (sameEmailUser) {
      res.status(400).json({ message: "이미 존재하는 이메일 입니다." });
      throw new Error("이미 존재하는 이메일 입니다.");
    }

    try {
      const createResult = await createUser(client, userData);
      res.status(200).json({ message: "회원가입 성공!", data: userData });
    } catch (error) {
      res.status(400).json({ message: "회원가입 실패" });
      throw new Error("회원가입 실패");
    }
  }
}

export default handler;
validation 도 아웃소싱하여 집어넣어주고,  API 요청을 하면,  클라우드 기반의 DB 인 MongoDB Atlas 에 유저의 정보가 입력됩니다.

짜잔-

댓글