공부(TIL)

개발일지 16-19일차

하루지오 2024. 7. 11. 07:38

issue: 비밀번호 찾기 구현 중 memberApi 호출 오류 
 
1. 비밀번호 찾기를 위한 임시 비밀번호 이메일 전송을 위해 api를 작성했으나, 이메일 발송 확인 불가

// 1안
export const sendEmail = async (email) => {
  try {
    const response = await axios.post(
      `${host}/member/sendEmail?email=${email}`
    );
    console.log(response.data.message);
    return response.data;
  } catch (error) {
    console.error(
  
// 2안
export const sendEmail = async (updateData) => {
  const header = { headers: { "Content-Type": "application/json" } };
  const data = {
    email: updateData.email,
  };
  try {
    const response = await axios.post(`${host}/member/sendEmail`, data, header);
    return response.data;
  } catch (error) {
    console.error(
      "Error fetching data:",
      error.response ? error.response.data : error.message
    );
    throw error.response.data;
  }
};

 
아래는 이메일 전송 함수이다.

const handleSendEmail = async () => {
    if (!updateData.email) {
      setEmailError("필수 입력 사항입니다.");
      return;
    } else if (!isValidEmail(updateData.email)) {
      setEmailError("이메일 형식이 올바르지 않습니다.");
      return;
    }

    try {
      const emailResponse = await sendEmail(updateData.email);
      console.log("emailResponse");

      if (emailResponse === true) {
        setEmailError("작성해주신 이메일로 재발급된 비밀번호를 전송했습니다.");
        setEmailAvailable(true);
      } else {
        setEmailError("가입되어 있지 않은 이메일입니다.");
      }
    } catch (error) {
      console.log(error);
      Swal.fire("이메일 전송 실패", `다시 시도해주세요.`, "error");
      setEmailError("");
      setEmailAvailable(false);
    }
  };

1안으로 먼저 시도해보니, 백엔드에서는 메일 전송 완료로 console창에서 확인 가능했다. 그런데, 이메일은 도착하지 않았고, 3~5초가 지난 후에 백엔드에서 500 에러가 발생하며, 프론트엔드에서는 이메일 전송 실패라는 alert 창을 띄웠다.
 

 
로그인을 구현했던 것처럼 header와 data를 보내는 방식으로 2안을 작성했고, 2안에 맞게 백엔드 코드도 수정해서 다시 시도했다. 하지만 이번에도 같은 결과를 맞이했다.
이후에도 api와 이메일 호출 함수를 계속해서 수정하는 과정을 3일 동안 반복했다.
 
그러던 중 같이 이 문제의 원인을 찾고 있었던 팀장님께서 host만 local로 변경해서 api는 1안으로, 이메일 호출 함수도 그대로 이메일 전송을 갑자기 코드가 제대로 작동되기 시작했다는 연락을 주셨다. 확인해보니 정말 며칠 전만 해도 오류만 생기던 코드가 정상적으로 작동되고 있었다. 다만 "가입되어 있지 않은 이메일입니다."라는 에러 메세지가 떠서 예외 처리를 다시 진행했다.
 
2. 새로 발급 받은 임시 비밀번호와 입력한 임시 비밀번호의 불일치

 
분명 이메일로 전송된 임시 비밀번호를 입력했는데, 일치하지 않다고 백엔드에서 에러 메세지를 보내고 있었다.
그래서 비밀번호 변경 함수의 오류인 줄 알고 다시 검토했으나, 문제는 없었다.

const handleUpdatePW = async (e) => {
    e.preventDefault();

    let valid = true;

    if (!updateData.email) {
      setEmailError("필수 입력 사항입니다.");
      valid = false;
    } else if (!isValidEmail(updateData.email)) {
      setEmailError("이메일 형식이 올바르지 않습니다.");
      valid = false;
    }

    if (!updateData.password) {
      setPasswordError("필수 입력 사항입니다.");
      valid = false;
    }

    if (!updateData.newPassword) {
      setNewPasswordError("필수 입력 사항입니다.");
      valid = false;
    } else if (!isValidPassword(updateData.newPassword)) {
      setNewPasswordError("비밀번호 형식이 올바르지 않습니다.");
      valid = false;
    }

    if (!pwCheck) {
      setPwCheckError("필수 입력 사항입니다.");
      valid = false;
    } else if (updateData.newPassword !== pwCheck) {
      setPwCheckError("비밀번호가 일치하지 않습니다.");
      valid = false;
    }

    if (valid) {
      try {
        const updateResponse = await updatePassword(updateData);
        console.log("비밀번호 변경 완료:", updateResponse);
        setUpdatePW(true);

        Swal.fire(
          "비밀번호 변경 완료",
          `로그인 창으로 전환됩니다.`,
          "success"
        ).then(() => {
          onClose();
        });
      } catch (error) {
        console.error(
          "비밀번호 변경 실패:",
          error.response ? error.response.data : error.message
        );
        Swal.fire("비밀번호 변경 실패", `다시 시도해주세요.`, "error");
        setEmailError("");
        setPasswordError("");
        setNewPasswordError("");
        setPwCheckError("");
      }
    }
  };

 
그러던 지난 번 로그인을 구현할 때, BCrpt를 거치지 않은 비밀번호는 로그인 안됬던 상황이 생각났다. 회원가입 시 모든 비밀번호는 BCrpt를 거쳐 DB에 저장되기 때문에 BCrpt를 거치지 않은 비밀번호는 로그인이 안되는 것이다. 이처럼 입력받은 임시 비밀번호가 BCrpt를 거치도록 해야 DB에 저장된 임시 비밀번호와 일치한 것으로 인식할 것이라는 생각이 들었다.
 
백엔드 코드를 확인해보니, 입력받은 임시 비밀번호가 BCrpt를 거치는 과정이 생략되어 있었다. 그래서 아래와 같이 수정하니, 드디어 입력받은 임시 비밀번호가 DB에 저장된 임시 비밀번호와 일치해서 비밀번호 수정이 가능했다.

// 기존 코드
else if(!member.getPassword().equals(password)) {
    throw new MemberException(ErrorCode.PW_NOT_FOUND);
}

// 변경한 코드
else if(!bCryptPasswordEncoder.matches(password, member.getPassword())) {
    throw new MemberException(ErrorCode.PW_NOT_FOUND);
}