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); } }) |
|
텍스트 중 하이퍼링크 필터링 체크하여 a태그로 변환(react.js) (0) | 2022.12.22 |
---|---|
비동기처리 이벤트 없이 처음 실행되는 방법 - React.js (0) | 2022.12.21 |
react-quill 사용(이미지 포함)방법 (0) | 2022.05.29 |
boiler-plate (0) | 2020.08.25 |
노마드코더님 _ React #3 (0) | 2020.06.16 |
댓글 영역