상세 컨텐츠

본문 제목

회원가입 관련 Front-end와 Back-end 정리

CODING/React.js

by 뚜뚜 DDUDDU 2022. 6. 1. 02:22

본문

 

회원가입 관련 Front-end와 Back-end 정리

Node.js, React.js, redux.js,

express, sequelize 기반

회원가입 프론트앤드 dispatch({
      type: SIGN_UP_REQUEST,
      data: { email, password, nickname },
    });
  리덕스         draft.signUpLoading = false;
        draft.signUpDone = true;
  사가 function signUpAPI(data) {
  return axios.post('/user', data);
}
function* signUp(action) {
  try {
    const result = yield call(signUpAPI, action.data);
    console.log(result);
    yield put({
      type: SIGN_UP_SUCCESS,
    });
  } catch (err) {
    console.error(err);
    yield put({
      type: SIGN_UP_FAILURE,
      error: err.response.data,
    });}}
  백앤드 // 라우터명과 합쳐져서 Post /user/ (saga에서의 user 일치하게끔-localhost:3054/user)
router.post('/', isNotLoggedIn, async (req, res, next) => {
  try {
    // 이메일 중복확인을 위한 작업 
    // front에서 보낸 메일주소(req.body.email) 같은 data(email) 확인
    const exUser = await User.findOne({
      where: {
        email: req.body.email,
      }})
    if (exUser) {
      // return 필수(없을시 아래명령 계속수행)
      // status: 헤더일부로 200: 성공, 300: 리다이렉트, 400: client 에러(보내는쪽에서 잘못보냄), 500: server에러
      return res.status(403).send('이미 사용중인 아이디입니다.')
    }
 
    const hashedPassword = await bcrypt.hash(req.body.password, 12);
    // 테이블 내에 데이터 삽입
    // async, await: res.json 선실행 방지를 위함(비동기) - 비동기 판별유무공식문서
    await User.create({
      email: req.body.email,
      nickname: req.body.nickname,
      password: hashedPassword,
    })
    res.status(201).send('ok'); //200: 성공, 201: 데이터 성공적인 전송
  } catch (error) {
    console.error(error);
    next(error); // next 통해 error전송(status 500)
  }
})
 
로그인 프론트앤드 dispatch(loginRequestAction({ email, password, }));
  리덕스 export const loginRequestAction = data => {
  return {
    type: LOG_IN_REQUEST,
    data,};};
         draft.logInLoading = false;
        draft.me = action.data;
        draft.logInDone = true; // 임시방편으로 일단 고정시킴
  사가 function logInAPI(data) {
  return axios.post("/user/login", data);
}
function* logIn(action) {
  try {
    const result = yield call(logInAPI, action.data);
    yield put({ type: LOG_IN_SUCCESS, data: result.data });
  } catch (err) {
    // 7. 요청이 실패할 경우를 위해
    yield put({
      type: LOG_IN_FAILURE,
      error: err.response.data,
    });}}
  백앤드 // passport/local에서 done: callback역할, local, 매개변수 ex. err(서버에러)/user/info 넘겨받음
router.post('/login', isNotLoggedIn, (req, res, next) => {
  passport.authenticate('local', (err, user, info) => {
    if (err) {
      console.error(err);
      // 서버에러는 next(err); 보내야하지만(아래 참조매개변수로 받지 않았음(사용방법 차이때문에)
      // 방법미들웨어의 확장 - 위의 req, res, next부분과 아래 같은부문을 붙인 다음에 넣음(passport.authen-- ~)
      return next(err);
    }
    // 클라이언트 에러 발생시 passport/local에서 작성한 명령을 client 응답을 보내줌
    // 401 : http 상태코드(한번 조회!) '비인증'
    if (info) {
      return res.status(401).send(info.reason);
    }
    // 에러 없을시 로그인(loginerr: 서버로그인 이후 passport로그인(2단계관련)
    return req.login(user, async (loginErr) => {
      if (loginErr) {
        console.error(loginErr)
        return next(loginErr)
      }
      const fullUserWithoutPassword = await User.findOne({
        where: { id: user.id },
        // attributes: ['id', 'nickname', 'email'], --> 이속성들만 받음
        attribute: {
          exclude: ['password'] // password속성 받지 않음(보안문제때문에)
        },
        // 다른테이블 정보 합치기
        include: [{  // hasMany model:Post 복수형이 되어 me.Posts 
          model: Post,
          attribute: ['id'],
        }, {
          model: User,
          as: 'Followings',
          attribute: ['id'],
        }, {
          model: User,
          as: 'Followers',
          attribute: ['id'],
        }]
      })
      // res.setHeader('Cookie','cxlhy...') 포함되어 들어감
      // cookie: 서버쪽에선 (ex.password) 통째로 들고있고, front에선 복잡한 문자열로 변형되어 들어감
      // session: 서버쪽에 통째로 들고있는 
      return res.status(200).json(fullUserWithoutPassword); //login 정보 front 넘겨줌
    })
  })(req, res, next)
}) // post /user /login
정보 불러오기 프론트앤드 dispatch({
      type: LOAD_MY_INFO_REQUEST,
    })
  리덕스         draft.loadMyInfoLoading = false;
        draft.me = action.data; // 로그인했으면 내정보가 들어가게  
        draft.loadMyInfoDone = true;
  사가 function loadMyInfoAPI() {
  return axios.get("/user");
}
 
function* loadMyInfo() {
  try {
    const result = yield call(loadMyInfoAPI, action.data);
    yield put({
      type: LOAD_MY_INFO_SUCCESS,
      data: result.data,
    });
  } catch (err) {
    yield put({
      type: LOAD_MY_INFO_FAILURE,
      error: err.response.data,
    });
  }
}
 
  백앤드 router.get('/', async (req, res, next) => { // GET /user
  try {
    if (req.user) {
      const fullUserWithoutPassword = await User.findOne({
        where: { id: req.user.id },
        // attributes: ['id', 'nickname', 'email'], --> 이속성들만 받음
        attribute: {
          exclude: ['password'] // password속성 받지 않음(보안문제때문에)
        },
        // 다른테이블 정보 합치기
        include: [{  // hasMany model:Post 복수형이 되어 me.Posts 
          model: Post,
          attribute: ['id'], // 어차피 length(follower ) 가져올것이라 id 가져오게끔(데이터효율을 위한)
        }, {
          model: User,
          as: 'Followings',
          attribute: ['id'],
        }, {
          model: User,
          as: 'Followers',
          attribute: ['id'],
        }]
      })
      res.status(200).json(fullUserWithoutPassword);
    } else {
      res.status(200).json(null);
    }
  } catch (error) {
    console.error(error);
    next(error);
  }
})
 
     

 

 

 

관련글 더보기

댓글 영역