[ react ] React에서의 Error 처리 & async await 비동기 함수->동기함수 / 비번암호화하기

Suji Kang·2023년 9월 27일
0

🐾 React에서의 Error 처리

📝 에러가 났는데 에러나는 이유는 여러가지인데 무슨에러인지 어떻게 알지 ❓

코드를 잘 작성하더라도 에러는 언제든 발생할 수 있다. 갑작스러운 서버 문제나 데이터 손실 (많은이유로)과 같은 예상치 못한 사건이 발생하면 에러를 피할 수 없다. 에러가 발생할 수 있으므로 항상 예방책을 갖추는 것이 중요❗️

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...

🐾 async await 문법 javascript (2:00) 9/27

비동기 함수를 동기 함수처럼 사용하고싶어

❗️ 비동기 함수 앞에 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: '알수없는 에러가 발생했습니다.' });
        }
    }
});

🐾 비번 암호화 하기 (3:23)

📝 암호화 라이브러리 사용

설치

npm install bcrypt

import

const bcrypt = require('bcrypt');

📝문서확인 :
https://www.npmjs.com/package/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에 들어간다

profile
나를위한 노트필기 📒🔎📝

0개의 댓글