코드를 잘 작성하더라도 에러는 언제든 발생할 수 있다. 갑작스러운 서버 문제나 데이터 손실
(많은이유로)
과 같은 예상치 못한 사건이 발생하면 에러를 피할 수 없다. 에러가 발생할 수 있으므로항상
예방책을 갖추는 것이 중요❗️
app.js
if (err !== null) {
// 아이디가 컬럼의 최대 허용 용량을 벗어났다 1406
if (err.errno === 1406) {
res.status(400).json('아이디가 너무 길어요');
return;
}
// 중복된 아이디가 존재한다 1062
else if (err.errno === 1062) {
res.status(400).json('이미 중복된 아이디가 존재합니다.');
return;
}
// 그외에 에러는 400
else {
res.status(400).json('서버쪽에서 에러가 발생했습니다.');
return;
}
join.js
.catch((err) => {
console.log(err);
//회원가입 실패 했다하면 실행시킬 코드
if (err.response.data === '아이디가 너무 길어요') {
// alert('아이디가 너무 길어요'); // -->깔끔하게 하기 위해 alert대신 state변수를 만들어서 에러메세지를 출력
setEmailErrMsg('아이디가 너무 길어요');
} else if (err.response.data === '이미 중복된 아이디가 존재합니다.') {
// alert('이미 중복된 아이디가 존재합니다.');
setEmailErrMsg('이미 중복된 아이디가 존재합니다.');
} else {
// alert('서버쪽에서 에러가 발생했습니다.');
setEmailErrMsg('서버쪽에서 에러가 발생했습니다.');
}
}
📌 예를들어,
if (err.response.data === '아이디가 너무 길어요')
인데,if (err.response.data === '아이디가 너무 길어요 ')
이렇게 뛰어쓰기가 있으면error 에서 아이디가 너무길어요
가 아니라서 그냥서버쪽에서 에러가 발생했습니다.
error로 들어갈수있다.
이것을 방지하기위해 !
코드(숫자)로 만들었다. - 회사마다 오류코드가 있다.
app.js
if (err !== null) {
// 아이디가 컬럼의 최대 허용 용량을 벗어났다 1406
if (err.errno === 1406) {
// res.status(400).json('아이디가 너무 길어요');
res.status(400).json({ errCode: 1, errMsg: '아이디가 너무 길어요' }); //객체에 담어서 보내줌
}
// 중복된 아이디가 존재한다 1062
else if (err.errno === 1062) {
res.status(400).json({ errCode: 2, errMsg: '중복된 아이디가 존재합니다.' });
}
// 그외에 에러는 400
else {
res.status(400).json({ errCode: 3, errMsg: '알수없는 에러가 발생했습니다.' });
}
} else {
console.log('result:', result);
console.log('fields:', fields);
res.json('성공이야~!!');
}
}
);
join.js
axios.post('/api/users', {
email,
password,
question,
answer
}).then((res) => {
console.log(res)
//회원가입 성공 했다하면 실행시킬 코드
// alert('회원가입이 완료되었습니다.');
setIsOpen(true);
}).catch((err) => {
console.log(err);
//회원가입 실패 했다하면 실행시킬 코드
if (err.response.data.errCode === 1) {
// alert('아이디가 너무 길어요'); // 🌟🌟깔끔하게 하기 위해 alert대신 state변수를 만들어서 에러메세지를 출력 🌟v
setEmailErrMsg('아이디가 너무 길어요');
} else if (err.response.data.errCode === 2) {
// alert('이미 중복된 아이디가 존재합니다.');
setEmailErrMsg('이미 중복된 아이디가 존재합니다.');
} else {
// alert('서버쪽에서 에러가 발생했습니다.');
setEmailErrMsg('서버쪽에서 에러가 발생했습니다.');
}
});
📌
navigate 함수
사용navigate('/login', { 옵션 }); //뒤로가게하기 true 나 false 설정가능 navigate('/login', { replace: true }); // replace -> 뒤로가게 못함
📌
state변수
사용const [isOpen, setIsOpen] = useState(false);
join.js
const JoinPage = () => {
import { useNavigate } from "react-router-dom";
//모달창이 열려있는지 닫혀있는지를 판단하는 state변수
const [isOpen, setIsOpen] = useState(false);
const navigate = useNavigate();
//모달창 확인 버튼 클릭되었을때
const onModalClick = () => {
//로그인 페이지로 이동,
navigate('/login', { replace: true }); // replace -> 뒤로가게 못함
}
const submitHandler = (e) => {
.then((res) => {
console.log(res)
setIsOpen(true); //button submit 했을때 true로 바뀌어서 성공시 모달창 보임
}
};
return (
<ModalWrap isOpen={isOpen}>
<Modal>
<h1>회원가입이 완료되었습니다.</h1>
<p>확인을 누르시면 로그인 페이지로 이동합니다</p>
<button onClick={onModalClick}>확인</button>
</Modal>
</ModalWrap>
);
}
const ModalWrap = styled.div`
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,0.8);
display: ${(props) => { return props.isOpen ? 'flex' : 'none' }};
//props는 어디서 전달받는거지?? - <ModalWrap isOpen={false}/>
justify-content: center;
align-items: center;
`;
const Modal = styled.div`
width: 450px;
background-color: white;
border-radius: 16px;
display: flex;
flex-direction: column;
align-items: center;
padding: 30px ;
`;
확인누르면, 회원가입페이지이동
fetch
axios.get
axios.post
axios...
비동기 함수를 동기 함수처럼 사용하고싶어
❗️ 비동기 함수 앞에
await
를 사용하면 동기함수로 해석한다
await
를 썼으면await를 감싸고있는
함수를async함수
라고 알려줘야 한다!!
📝 문법
:
일반적인 함수 async function 함수이름(){ await } 익명함수 async function (){ } 화살표 함수 async ()=>{ }
axios.get('/users').then((res)=>{
// get함수가 정상적으로 끝났을때 실행되는 공간(동기적으로)
// res 에는 객체(status, statusCode, statustext, data, ...)
}).catch((err)=>{
// get함수가 오류가 발생하면서 끝났을때 실행되는 공간(동기적으로)
//err에는 에러 객체(에러정보, 에러이름, response, ... )
})
pool.query('SELECT * FROM tmp, (err, result, fields)=>{
// 이공간은 sql이 끝나고 동기적으로 실행되는 곳
//err 에는 오류발생하면 err객체 안발생하면 null
//result에는 ? 정상적으로끝나면 결과(배열, 객체) 오류발생시 undefined
//fields 에는 ? 정상적으로 끝나면 각 컬럼에대한 정보 오류발생 혹은 SELECT 아닌경우 undefined
});
취향차이지만, 주로 간단한것은
.then
사용하고, 복잡할때는await
을 사용한다.
예를 들어, 함수 중에 ceil이라는 함수
가 있다고 가정 해보자.
let res = await ceil(3.5); // 다른거 먼저 하지말고 결과 나올때까지 기다리겠다.
console.log(res + 7);
//ex)
ceil(3.5).then((res)=>{ // 똑같이 동작함
console.log(res + 7);
})
//ex) .then 사용
axios.get('/users').then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err)
});
//ex) await으로 바꾸기
try {
let res = await axios.get('/users');
console.log(res);
}catch(err){
console.log(err);
}
//ex) 두개의 값을 한꺼번에 넣어주려면 - 배열이나 객체사용// 정하는건 하는사람 마음
doubleMath(3.5).then((a, b)=>{
console.log(a); //4
console.log(b); //3
})
//구조분해할당
let [a, b] = await doubleMath(3.5); //--> 올림한값[4, 3]내림한값
console.log(a); //4
console.log(b); //3
//ex) 기존 함수
pool.query('SELECT * FROM tmp', (err, result, fields)=>{
if(err !== null){
console.log(err);
}else{
console.log(result);
console.log(fields);
}
})
//ex) await 함수
try{
let [ result, fields ] = await pool.query('SELECT * FROM tmp');
// [ , ]배열 첫번째는 result, 두번째는 fields
console.log(result);
console.log(fiedls);
}catch(err){
console.log(err);
}
//ex) .then 함수 -> 해석은 가능하지만, 어떤 오류에 .catch인지 헷갈릴수있다.
doubleMath(3.5).then((a,b)=>{
doubleMath( a + 7.2).then((a, b)=>{
console.log(a);
doubleMath(b + 3.2).then((a, b)=>{
}).catch((err)=>{
});
}).catch((err)=>{
})
}).catch((err)=>{
console.log(err);
})
//ex) await 함수
try{
let [res1, res2] = await doubleMath(3.5);
let [res3, res4] = await doubleMath( res1 + 7.2); //결과가 나올때까지 기달려
console.log(res3);
let [res5, res6] = await doubleMath(res4 + 3.2); //결과가 나올때까지 기달려
}catch(err){
console.log(err); //어디서든 실행하다가 오류가생기면 오류 출력해줘
}
join.js
const submitHandler = async (e) => {
e.preventDefault();
let check = true;
try {
let res = await axios.post('/api/users', { email, password, question, answer });
console.log(res);
setIsOpen(true);
} catch (err) {
console.log(err);
if (err.response.data.errCode === 1) {
alert('아이디가 너무 길어요');
} else if (err.response.data.errCode === 2) {
setEmailErrMsg('이미 중복된 아이디가 존재합니다.');
} else {
setEmailErrMsg('서버쪽에서 에러가 발생했습니다.');
}
}
🌟 await
사용하고싶으면 서버쪽 app.js
에서
이걸 import 해야한다.
const mysql = require('mysql2/promise');
const mysql = require('mysql2/promise');
//회원 한명 추가
app.post('/api/users', async (req, res) => {
console.log('req.body', req.body);
const sql = `INSERT INTO tbl_users
(email, pw, question, answer)
VALUES (?, ?, ?, ?)
`;
let { email, password, question, answer } = req.body;
try {
let [result, fields] = await pool.query(sql, [email, password, question, answer]);
console.log('result', result);
console.log('fields', fields);
res.json("성공이야~!!");
} catch (err) {
if (err.errno === 1406) {
res.status(400).json({ errCode: 1, errMsg: '아이디가 너무 길어요' }); //객체에 담어서 보내줌
}
// 중복된 아이디가 존재한다 1062
else if (err.errno === 1062) {
res.status(400).json({ errCode: 2, errMsg: '중복된 아이디가 존재합니다.' });
}
// 그외에 에러는 400
else {
console.log(err)
res.status(400).json({ errCode: 3, errMsg: '알수없는 에러가 발생했습니다.' });
}
}
});
📝 암호화 라이브러리 사용
설치
npm install bcrypt
import
const bcrypt = require('bcrypt');
const bcrypt = require('bcrypt');
// 비밀번호 암호화
let enpw = bcrypt.hashSync(password, 10); //10번에 거쳐서 암호화한다. 10보다 더 많이 할수있지만 그러면 느려질수있고 10도 충분하다
try {
let [result, fields] = await pool.query(sql, [email, enpw, question, answer]); // password 를 enpw로 바꿔주는거 잊지말고 !
console.log('result', result);
console.log('fields', fields);
res.json("성공이야~!!");
이렇게 암호화가 되어서 mysql에 들어간다