[Go!Street] MERN STACK으로 혼자 구현해보는 커뮤니티 사이트 3️⃣

Beanxx·2022년 11월 1일
0

Go!Street Project 🚚 

목록 보기
3/3
post-thumbnail

💡 로그인 & 회원가입

npm install firebase
npm install @reduxjs/toolkit react-redux
  1. firebase - 프로젝트 생성 - authentication - email/password 선택
  2. client 폴더 내에 firebase.js 파일 생성
    (내용은 firebase 플젝 생성시 제공하는 코드 사용)
    import "firebase/compat/auth";
     import firebase from "firebase/compat/app";
     
     const firebaseConfig = {
       apiKey: "~",
       authDomain: "~",
       projectId: "~",
       storageBucket: "~",
       messagingSenderId: "~",
       appId: "~",
     };
     
     firebase.initializeApp(firebaseConfig);
     
     export default firebase;

💫 회원가입

🔗 [firebase 공식문서] Get Started with Firebase Authentication on Websites

[Client]

// firebase 회원가입 기능
const RegisterFunc = async (e) => {
  e.preventDefault();

  let createdUser = await firebase
    .auth()
    .createUserWithEmailAndPassword(email, pw);

  await createdUser.user.updateProfile({
    displayName: name,
  });

  let body = {
    email: createdUser.user.multiFactor.user.email,
    displayName: createdUser.user.multiFactor.user.displayName,
    uid: createdUser.user.multiFactor.user.uid,
  };

  axios.post("/api/user/register", body).then((response) => {
    setFlag(false); // 회원가입이 완료되면 회원가입 버튼 다시 활성화해주기
    if (response.data.success) {
      navigate("/login");
    } else {
      return alert("회원가입에 실패하였습니다.");
    }
  });
};

[Server]

  • 먼저 UserSchema 생성해주기

    const mongoose = require("mongoose");
    
    const userSchema = new mongoose.Schema(
      {
        userNum: Number,
        email: String,
        displayName: String,
        uid: String,
      },
      { collection: "users" }
    );
    
    const User = mongoose.model("User", userSchema);
    
    module.exports = { User };
// 회원가입
router.post("/register", (req, res) => {
  let temp = req.body;
  Counter.findOne({ name: "counter" })
    .then((doc) => {
      temp.userNum = doc.userNum;
      const userData = new User(req.body);
      userData.save().then(() => {
        Counter.updateOne({ name: "counter" }, { $inc: { userNum: 1 } }).then(
          () => {
            res.status(200).json({ success: true });
          }
        );
      });
    })
    .catch((err) => {
      res.status(400).json({ success: false });
    });
});

💫 회원가입 - 닉네임 중복검사

[Client]

const NameCheckFunc = (e) => {
  e.preventDefault();

  if (!name) {
    return alert("닉네임을 입력해주세요.");
  }

  let body = { displayName: name };

  axios.post("/api/user/namecheck", body).then((response) => {
    if (response.data.success) {
      if (response.data.check) {
        setNameCheck(true);
        setNameInfo("사용가능한 닉네임입니다.");
      } else {
        setNameInfo("사용불가능한 닉네임입니다.");
      }
    }
  });
};

[Server]

router.post("/namecheck", (req, res) => {
  User.findOne({ displayName: req.body.displayName })
    .exec()
		.then((doc) => {
      let check = true;
      if (doc) check = false;
      res.status(200).json({ success: true, check });
    })
    .catch((err) => {
      res.status(400).json({ success: false });
    });
});

💫 로그인

// firebase 로그인 인증
const SignInFunc = async (e) => {
  e.preventDefault();

  try {
    await firebase.auth().signInWithEmailAndPassword(email, pw);
    navigate("/");
  } catch (err) {
    console.log(err.code);
    if (err.code === "auth/user-not-found") {
      setErrorMsg("존재하지 않는 이메일입니다.");
    } else if (err.code === "auth/wrong-password") {
      setErrorMsg("비밀번호가 일치하지 않습니다.");
    } else {
      setErrorMsg("로그인에 실패하였습니다.");
    }
  }

💫 로그인 회원정보 redux-toolkit으로 관리

🔗 [redux-toolkit 공식문서] Quick Start | Redux Toolkit

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  displayName: "",
  uid: "",
  accessToken: "",
};

export const userSlice = createSlice({
  name: "user",
  initialState,
  reducers: {
    loginUser: (state, action) => {
      state.displayName = action.payload.displayName;
      state.uid = action.payload.uid;
      state.accessToken = action.payload.accessToken;
    },
    clearUser: (state) => {
      state.displayName = "";
      state.uid = "";
      state.accessToken = "";
    },
  },
});

export const { loginUser, clearUser } = userSlice.actions;

export default userSlice.reducer;


💡 Modal

modal 외부 클릭시 닫히도록 hooks 사용

🔗 [usehooks 공식문서] useOnClickOutside

const [modalFlag, setModalFlag] = useState(false);
useOnClickOutside(ref, () => setModalFlag(false));

function useOnClickOutside(ref, handler) {
  useEffect(() => {
    const listener = (event) => {
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }
      handler(event);
    };
    document.addEventListener("mousedown", listener);
    document.addEventListener("touchstart", listener);
    return () => {
      document.removeEventListener("mousedown", listener);
      document.removeEventListener("touchstart", listener);
    };
  }, [ref, handler]);
}
const ref = useRef();

// 모달 사용시 모달 태그쪽에 ref 추가해주기
{modalFlag && (<div ref={ref}>...</div>)}


💡 HEROKU 배포

  1. Create new app

  2. 컴터에 Heroku CLI 설치
    🔗 [사용가이드] The Heroku CLI

    # macOS는 아래 명령어를 통해 heroku를 설치해준다.
    brew tap heroku/brew && brew install heroku
  3. config 폴더 → key 관리

    // production.js 파일을 생성해서 key들을 아래와 같이 설정해준다 
    module.exports = {
      mongoURI: process.env.MONGO_URI,
      access_key: process.env.S3_KEY,
      secret_key: process.env.S3_SECRET,
    };
  4. heroku app dashboard로 가서 Settings 탭 - Config Vars에서 key들 입력해주기

    • process.env.~ 뒤에 작성했던 KEY와 해당하는 VALUE 입력
    스크린샷 2022-10-30 오후 10 38 29
  1. server/index.js 파일의 port 재설정

    // HEROKU로 배포시 포트가 무조건적으로 설정한 4000이 아닐 수 있기 때문에 아래와 같이 설정
    const port = process.env.PORT || 4000;
  2. 폴더 구조 변경

    # 변경 전
     ㄴclient
     ㄴserver
    
     본래 client 폴더를 server 폴더로 이동시키고, 본래 server 폴더 이름을 App으로 변경한다.
     이후, App 폴더 내에 새로운 server 폴더를 생성해서 원래 server 폴더에 만들었던
     config, Router, Model, Util 폴더를 새로 생성한 server 폴더에 넣어준다.
    
     # 변경 후
     App
     ㄴclient
     ㄴserver
  3. server/index.js 파일 내에 import 경로 변경 & gitignore 내 파일 경로 변경

  4. App 폴더 내에 Profile 파일 생성

    web: node index.js
  5. server/package.json - script - start 명령어 변경해주고, 커밋까지 해주기!

    // 변경 전 
    "start": "nodemon index.js"
    
    // 변경 후
    "start": "node index.js"
    
    // 편의를 위해 nodemon으로 명령어를 변경했던 것을 다시 node로 변경하기
  6. heroku app dashboard로 가서 Deploy 탭으로 이동해서 명령어 확인 후, 실행

    $ heroku login
    # 터미널에서 아무키나 누른 후, heroku 사이트에서 로그인 버튼 한번 클릭해주면 로그인 완료 
    $ heroku git:remote -a go-street
    $ git subtree push --prefix App heroku main

이렇게하면 배포 성공 🎃
이제 부가기능 추가하고, 디자인 틈틈히 수정하자~!

profile
FE developer

0개의 댓글