일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 리액트
- vue 이벤트 수신
- KDT 프로그래머스 데브코스 프론트엔드
- vue mixin
- react next
- KDT 프로그래머스
- Spacer
- netlify redirect
- 프로그래머스 K_Digital Training
- nextjs사용법
- flex
- intersection opserver
- 리스트 렌더링
- Vue
- postcss
- 프로그래머스 프론트엔드 데브코스
- 프로그래머스 데브코스 프론트엔드
- SCSS use
- 이벤트 수식어
- 쌓임맥락
- SCSS forward
- vue 지역 컴포넌트
- SCSS import
- SCSS extend
- git 같은계정 다른 컴퓨터
- 다른컴퓨터에서 git사용
- 폼 입력 바인딩
- 프로그래머스 데브코스
- 고양이 사진 검색기
- vuex map
- Today
- Total
혼자 적어보는 노트
회원가입 구현하기 /NextJS, Express, MySQL 본문
프론트서버(Next.js), 백엔드서버(Express), 데이터베이스(MySQL)를 연결하여
회원가입을 하는 기능을 구현해보자
📄 준비된 것
- 프론트에서 회원가입 submit시 데이터 전달을 하는 코드 작성
- Node Express를 이용한 서버 세팅
- Sequalize를 사용하여 모델 세팅
- MySQL으로 연결하여 데이터를 넣을 테이블 세팅
현재 Sequalize에서 만든 모델들을 MySQL에 연결해 놓은 상태이기 때문에
그 이후 과정을 진행해보겠다.
😇 연결 전 기억해야 할 것
1. 브라우저와 프론트서버의 포트는 동일하다.
프론트의 포트를 변경할 경우 front의 package.json에서 변경을 해준다.
"scripts": {
"dev": "next -p 3060"
},
2. 백엔드 서버의 포트번호는 Node.js를 통해 설정한 app.js의 포트번호다.
3. MySQL의 포트번호는 워크벤치에서 확인할 수 있다.
총 3가지의 포트번호를 사용하고 있는 셈이다.
🚚 실제 회원가입 데이터 DB에 보내기
1. 임시 데이터 처리를 실제 데이터 요청으로 변경
회원가입 form에 submit후 dispatch 하는 부분에
임시로 데이터 요청을 해놓았던 부분을 실제 데이터 요청으로 변경
function signUpAPI(data) {
return axios.post("http://localhost:8080/user", data); // api 요청
}
function* signUp(action) {
try {
const result = yield call(signUpAPI, action.data);
// call의 인자로 API요청 함수와 API요청 함수에 보낼 매개변수를 적는다.
console.log(result); //일단 데이터 요청 전 결과가 제대로 나오는지 console확인
yield put({
type: SIGN_UP_SUCCESS,
});
} catch (error) {
yield put({
type: SIGN_UP_FAILURE,
error: error.response.data,
});
}
}
saga를 사용했고 임시로 작성해놓은 yield delay(1000); 코드를 지우고 call요청으로 변경했다.
* call은 비동기
2. 백엔드(express)의 app.js에 아래의 코드를 추가
//.. 생략
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use("/user", userRouter);
//.. 생략
app.use(express.json()) : 프론트 서버에서보낸 json형식의 데이터를 req.body에 넣어준다.
app.use(express.urlencoded()) : form submit의 방식의 경우 urlencoded형식으로 넘어오는데 그 데이터를 처리해줌.
express.json()과 express.urlencoded()을 설정해야 서버에 데이터 전달 시
데이터를 req.body로 받아올 수 있다.
❗ (중요) express.json()과 express.urlencoded()가 route를 설정하는 코드 위에 있어야한다.
3. route 생성
[routes/user.js]
const express = require("express");
const router = express.Router();
const { User } = require("../models");
// models/index.js에서 내보낸 db안의 User을 가져온다 == User의 모델(table)을 가져오는 것
router.post("/", async (req, res) => {
await User.create({
// table안에 데이터 삽입 / 비동기함수기 때문에 await 사용
email: req.body.email,
nickname: req.body.nickname,
password: req.body.password,
});
res.status(201).send("ok"); // 상태코드 전달
});
module.exports = router;
기존에 만들었던 models/user.js에서 db안의 User을 가져오고
Post요청을 작성한다. 비동기로 이루어지기 때문에 async를 사용한다.
2번에서 json형식으로 받은 데이터를 req.body에 넣어주었기 때문에
req.body에는 action.data가 들어있다.
4. 이메일 중복 검사
회원가입을 이메일로 진행을 했는데 해당 이메일이 DB에 있는지 확인을하고
이미 등록된 이메일이 있다면 회원가입을 막아주어야한다.
router.post("/", async (req, res, next) => {
try {
const exUser = await User.findOne({
// 기존의 유저 중 해당 email을 사용하는 유저가 있는지 확인
where: {
email: req.body.email,
},
});
if (exUser) {
return res.status(403).send("이미 사용중인 이메일입니다.");
// 이 부분이 saga의 error.response.data가 됨
}
await User.create({
email: req.body.email,
nickname: req.body.nickname,
password: req.body.password,
});
res.status(201).send("ok");
} catch (error) {
console.log(error);
next(error); // status(500)
}
});
module.exports = router;
데이터를 찾을 땐 비동기로 조회해야 하기 때문에 async await을 사용해주어야 한다.
사용중인 이메일일 경우 return을 사용하여 에러 전달 후 끊어주어야 한다.
5. cors에러 처리
3번까지만 하고 서버를 실행해서 회원가입을 하면 cors에러가 발생하는데
브라우저에서 백엔드 서버에 요청을 보내면 port가 다르기 때문에 cors에러가 생긴다. (동일출처정책)
✅ 해결방법 1.
응답할 때(route) setHeader()사용
[routes/user.js]
const express = require("express");
const router = express.Router();
const { User } = require("../models");
router.post("/", async (req, res) => {
await User.create({
email: req.body.email,
nickname: req.body.nickname,
password: req.body.password,
});
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3060"); // *
res.status(201).send("ok");
});
module.exports = router;
서버에서 setHeader를 사용하여 브라우저의 도메인을 허용시켜준다.
두 번째 인자에 '*'을 넣을 경우 모든 요청을 허용해주게된다.
✅ 해결방법 2.
서버에서 미들웨어로 처리
[app.js]
const cors = require("cors");
app.use(
cors({
origin: "*",
})
);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// .. route 코드들
use와 cors를 이용하여 미들웨어로 처리하면 각각의 route에서 처리하지 않고 한번에 처리를 할 수 있다.
origin에는 나중에 도메인이 생긴다면 허용하는 도메인을 넣으면 된다.
❗❗ (중요) cors는 route코드들 위에 적어주어야 한다.
5. 회원가입 완료
next와 node모두 서버를 실행한 상태에서 회원가입을 하면
상태코드 201과 함께 회원가입처리가 완료된 것을 확인할 수 있다.
✅ 데이터의 전달 순서
데이터가 전달이 꽤 많이 되는데 순서를 잘 파악을 해야 한다.
데이터가 전달되는 순서를 정리해보면,
1. 사용자에게서 이벤트 발생
2. 회원가입의 데이터를 action data로 dispatch
dispatch(signupRequestAction({ email, nickname, password }));
// dispatch(type: SIGN_UP_REQUEST, data : { email, nickname, password })); 이렇게도 전달 가능
3. watch하고 있던 saga로 전달하고 takeLatest의 두 번째 인자인 함수 실행
function* watchSignUp() {
yield takeLatest(SIGN_UP_REQUEST, signUp);
}
4. 해당 함수에는 action이 들어있고 action.data를 api요청함수에 전달
function* signUp(action) {
try {
const result = yield call(signUpAPI, action.data);
console.log(result);
yield put({
type: SIGN_UP_SUCCESS,
data: action.data,
});
} // ...생략
5. api를 요청하는 함수의 인자에는 data가 들어있고
post요청으로 만들어놓은 route에 데이터를 함께 전송
function signUpAPI(data) {
return axios.post("http://localhost:8080/user", data);
}
6. 위의 data는 route에서 req.body에 전달되게된다.
router.post("/", async (req, res) => {
await User.create({ // req.body == action.data
email: req.body.email,
nickname: req.body.nickname,
password: req.body.password,
});
});
회원가입 부분을 구현하면서 파일 이름들이 같고
어디서 하더라? 하면서 헷갈리던 부분들이 많았지만 조금은 이해가 된 것 같다.
몇번 더 해봐야 될 것 같다.
'기타' 카테고리의 다른 글
git 원격 저장소 여러 개 연결하기 (0) | 2022.05.08 |
---|---|
private repository clone 안될 때 / remote: Repository not found. (0) | 2022.03.26 |
[MySQL] sequelize mysql column 이름, 속성 변경 및 생성 (0) | 2022.03.18 |
[Redux] Redux-saga 사용 해보기 (0) | 2022.03.08 |
[VSCode] prettier 설정 변경 / 줄바꿈 / 따옴표 변경 (0) | 2022.03.06 |