청소 플랫폼 만들기 (27)

김민준·2023년 9월 15일
0

청소 플랫폼 만들기 (27)

공부하며 느낀 점
참조한 페이지

청소 플랫폼 만들기 (27)

정규식 모듈화

const ApiError = require('../utils/apierror');

// 이메일 검증
exports.verificationEmail = (email) => {
  const emailReg = /^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/;
  if (!emailReg.test(email)) {
    throw new ApiError(412, '이메일 형식을 확인해주세요');
  }
};

// 비밀번호 검증
exports.verificationPassword = (pass, confirm) => {
  const passwordReg = /^(?!.*(.)\1\1)[a-zA-Z0-9!@#$%^&*]{4,}$/;
  if (!passwordReg.test(pass)) {
    throw new ApiError(
      412,
      '비밀번호는 네자리 이상, 영어 소문자(a~z), 영어 대문자(A~Z), 일부 특수문자(! @ # $ % ^  & *) 만 사용가능합니다.'
    );
  }

  if (pass !== confirm) {
    throw new ApiError(412, '패스워드가 일치하지 않습니다.');
  }
};

// 전화번호 검증
exports.verificationPhoneNumber = (number) => {
  const phoneNumberReg = /^\d{2,}-\d{3,}-\d{4,}$/;
  if (!phoneNumberReg.test(number)) {
    throw new ApiError(412, '전화번호 형식을 확인해주세요');
  }
};

정규식을 활용한 검증을 사용하는 경우가 많아서 아예 모듈화하였다.
정말 우연치않게도 그 직후에 정규식을 고칠 일이 있어서 이득을 봤다.
(0-9d로 바꿈)

오류 내보내기 통일

우리 프로젝트에서는 아래와 같은 방법으로 오류를 처리하고 있다.

class ApiError extends Error {
  constructor(status, message) {
    super(message);
    this.status = status;
    Error.captureStackTrace(this, this.constructor);
  }
}

module.exports = ApiError;

하지만 api를 각각 나누어서 작성하다보니 에러를 처리하는 캐치문이 다 다르게 작성되어 있어서 통일 하였다.

} catch (error) {
  console.error(error);
  return res.status(500).json({ message: 'Internal Server Error' });
}

//////////////////////

} catch (err) {
  if (err instanceof ApiError) {
    console.error(err.message);

    return res.status(err.status).json({ message: err.message });
  }
  console.error(err);

  return res.status(500).json({ message: 'Internal Server Error' });
}

또한, 이제는 컨트롤러 단에서 에러를 내뱉기 때문에 서비스단의 try-catch 문을 모두 삭제하였다.

위와같이 뜨던것이 아래와같이 바뀌었다.

코드 가독성 상승

showModal(
  'signUp',
  '회원가입',
  `
<form>
<div class="modal-body">
<div class="form-group">
<label for="permission" class="col-form-label">사업자/개인:</label>
<select id="signup-permission" name="선택">
<option value='guest'>일반 회원</option>
<option value='owner'>사업자 회원</option>
</select>
</div>
<div class="input-group">
<label for="signup-name">이름 </label>
<input id="signup-name" type="text" placeholder="홍길동" />
</div>
<div class="input-group">
<label for="signup-email">이메일 </label>
<input id="signup-email" type="email" placeholder="email@gmail.com" />
</div>
<div class="input-group">
<label for="signup-password">비밀번호 </label>
<input id="signup-password" type="password" placeholder="password" />
</div>
<div class="input-group">
<label for="signup-confirm-password">비밀번호 확인 </label>
<input id="signup-confirm-password" type="password" placeholder="confirm-password" />
</div>
<div class="input-group">
<label for="signup-nickname">닉네임 </label>
<input id="signup-nickname" type="text" placeholder="nickname" />
</div>
<div class="input-group">
<label for="signup-address">주소 </label>
<input id="signup-address" type="text" placeholder="XX시 XX로 XXXXX" />
</div>
<div class="input-group">
<label for="signup-phone-number">연락처 </label>
<input id="signup-phone-number" type="text" placeholder="010-XXXX-XXXX" />
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="signup-btn" type="submit" class="btn">Close</button>
<button type="button" class="btn btn-primary">회원 가입</button>
</div>
`
);

위와 같은 형태로 쓰던것을 아래와 같이 고쳐서 가독성을 올렸다.

const content = `
<form>
<div class="modal-body">
<div class="form-group">
<label for="permission" class="col-form-label">사업자/개인:</label>
<select id="signup-permission" name="선택">
<option value='guest'>일반 회원</option>
<option value='owner'>사업자 회원</option>
</select>
</div>
<div class="input-group">
<label for="signup-name">이름 </label>
<input id="signup-name" type="text" placeholder="홍길동" />
</div>
<div class="input-group">
<label for="signup-email">이메일 </label>
<input id="signup-email" type="email" placeholder="email@gmail.com" />
</div>
<div class="input-group">
<label for="signup-password">비밀번호 </label>
<input id="signup-password" type="password" placeholder="password" />
</div>
<div class="input-group">
<label for="signup-confirm-password">비밀번호 확인 </label>
<input id="signup-confirm-password" type="password" placeholder="confirm-password" />
</div>
<div class="input-group">
<label for="signup-nickname">닉네임 </label>
<input id="signup-nickname" type="text" placeholder="nickname" />
</div>
<div class="input-group">
<label for="signup-address">주소 </label>
<input id="signup-address" type="text" placeholder="XX시 XX로 XXXXX" />
</div>
<div class="input-group">
<label for="signup-phone-number">연락처 </label>
<input id="signup-phone-number" type="text" placeholder="010-XXXX-XXXX" />
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button id="signup-btn" type="submit" class="btn">Close</button>
<button type="button" class="btn btn-primary">회원 가입</button>
</div>
`

showModal('signUp','회원가입', content);

회원정보 수정

const user = await this.userRepository.findUserOne(userId);
if (!user) {
  throw new ApiError('존재하지 않는 로그인 이메일입니다.', 401);
}
console.log(password, 'aaaaaa', passwordConfirm);

if (!password) {
  password = user.password;
  passwordConfirm = user.password;
}

const passwordMatch = await bcrypt.compare(password, user.password);
if (passwordMatch) {
  throw new ApiError('기존 비밀번호와 다른 비밀번호를 입력해주세요.', 412);
}

console.log(password, 'bbbbb', passwordConfirm);

// 비밀번호 검증
verificationPassword(password, passwordConfirm);

let hashPassword;
if (password) {
  hashPassword = await bcrypt.hash(password, );
} else {
  hashPassword = user.password;
}

위와같이 새 비밀번호를 입력하지 않고 회원정보 수정시 기존 비밀번호로 업데이트 하도록 만들었다.

하지만 자꾸 비밀번호를 검증 오류가 발생했다. 이유는 이미 bcrypt 로 암호화한 것을 또 암호화해서 정규식에 맞지 않았기 때문이다...

실패시 새로고침 방지

const response = await fetch(`/api/user/me`, {
  method: 'put',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    userId,
    password,
    passwordConfirm,
    name,
    nickname,
    address,
    phoneNumber,
  }),
});
const result = await response.json();
window.location.reload();
return alert(result.message);
}

위와같이 API 응답을 받으면 새로고침을 하던것을 아래와 같이 정상적으로 요청이 완료 되었을 경우(201)에만 새로고침 하도록하여 이용자가 수정을 할 때 더 편하도록 바꾸었다.

const response = await fetch(`/api/user/me`, {
  method: 'put',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    userId,
    password,
    passwordConfirm,
    name,
    nickname,
    address,
    phoneNumber,
  }),
});
const result = await response.json();
if (response.status === 201) {
  window.location.reload();
}

로그아웃은 get 말고 post로

로그아웃쪽에서 예상지 못한 에러가 계속 일어나서 get 요청이 아니라 post 요청으로 해보니 해결되었다.

내부적으로 상태가 변하기 때문에 post가 맞다고 한다

공부하며 느낀 점

  • 이미 구현했으니 비슷하게 복붙만하면 된다고 생각했는데 하나하나 다 달랐다.
  • 같은 권한을 요구해도 다른 요청들을 보내야했고,
    마찬가지로 다른 권한을 요구하면 또 다른 요청을 보내야했다.

참조한 페이지

(인프런 get post 질문)[https://www.inflearn.com/questions/258343/%EA%B0%95%EC%9D%98-%EA%B4%80%EB%A0%A8-%EC%A7%88%EB%AC%B8%EC%9D%B4-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4]

profile
node 개발자

0개의 댓글

관련 채용 정보