![[Tistory] 비밀번호 변경](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255BTistory%255D%2520%25EB%25B9%2584%25EB%25B0%2580%25EB%25B2%2588%25ED%2598%25B8%2520%25EB%25B3%2580%25EA%25B2%25BD%2520%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3DCoding_study&w=2048&q=75)

1. 유저 네임, 이메일은 값뿌리고, 유저네임, 이메일은 (프런트에서) 변경 막기 2. 수정하려는 비밀번호가 기존 비밀번호랑 같으면 동일한 비밀번호는 안 된다고 막기 3. 기존 비밀번호가 DB값이랑 다르면 막기
1. updateForm 값 뿌리기 용
[ userResponse ]
@Data public static class UpdateDTO { private String username; private String email; public UpdateDTO(String username, String email) { this.username = username; this.email = email; } }
[ userService ]
public UserResponse.UpdateDTO UpdateForm(Integer sessionUserId) { User user = userRepo.findById(sessionUserId) .orElseThrow(() -> new RuntimeException("회원 정보가 존재하지 않습니다.")); return new UserResponse.UpdateDTO(user.getUsername(), user.getEmail()); }
[ userController ]
@GetMapping("/user/update-form") public String updateForm(HttpServletRequest request) { User sessionUser = (User) session.getAttribute("sessionUser"); UserResponse.UpdateDTO updateDTO = userService.UpdateForm(sessionUser.getId()); // System.out.println("updateDTO = " + updateDTO); request.setAttribute("user", updateDTO); return "user/updateForm"; }
[ updateForm ] 머스태치 뿌리기

2. 진짜 update
[ userRequest ]
@Data public static class UpdateDTO { private String password; private String newPassword; }
[ userService ]
@Transactional public void userUpdate(Integer sessionUserId, UserRequest.UpdateDTO requestDTO) { //먼저 조회 User user = userRepo.findById(sessionUserId) .orElseThrow(() -> new RuntimeException()); if (requestDTO.getNewPassword().equals(user.getPassword())) { // throw new RuntimeException("동일한 비밀번호로는 변경할 수 없습니다."); } if (!requestDTO.getPassword().equals(user.getPassword())) { throw new RuntimeException("기존 비밀번호가 일치하지 않습니다."); } user.setPassword(requestDTO.getNewPassword()); }
[ userController ]
@PutMapping("/user/update") public ResponseEntity<?> update(@RequestBody UserRequest.UpdateDTO reqDTO) { // System.out.println("비번 확인용 = " + reqDTO); User sessionUser = (User) session.getAttribute("sessionUser"); userService.userUpdate(sessionUser.getId(), reqDTO); return ResponseEntity.ok(new ApiUtil<>(true)); }
@RequestBody 붙이는거 까먹지 말자 ㅠㅠ
→ 요청 본문을 JSON으로 받고, 자바 객체로 변환해준다.
AJAX를 사용하니까, 이제 POST말고 PUT으로 해주자!
[ updateForm ] - SweetAlert2 script 사용
<script> $("#updateUserForm").on("submit", function (e) { e.preventDefault(); let password = $("#password").val(); // console.log("password " + password); let newPassword = $("#same-password").val(); // console.log("newPassword " + newPassword); //한번에 넘기장 let passwords = { password: password, newPassword: newPassword }; $.ajax({ url: '/user/update', data: JSON.stringify(passwords), contentType: 'application/json; charset=utf-8', type: 'PUT' }).done((res)=>{ //swal - 비동기적으로 작동. 그래서 자꾸 alert창 안뜨고 바로 /로 넘어간다 swal({ text: "회원정보 변경이 완료되었습니다.", icon: "success", button: "확인" // then - 비동기 작업이 완료된 후에 실행할 코드를 지정할 때 사용 (promise) }).then(() => { window.location.href = "/"; }); }).fail((res)=>{ swal({ // text: "동일한 비밀번호로는 변경할 수 없습니다.", // res에서 msg 빼오고, apiException 만들어야하는데 exception 아직 하지 말라고 하셔서 패스 text: "비밀번호를 확인해주세요", icon: "warning", button: "확인" }); }); }); </script>
swal → 비동기적으로 작동. 그래서 자꾸 alert창 안뜨고 바로 /로 넘어간다.
그래서 then → 비동기 작업이 완료된 후에 실행할 코드를 지정할 때 사용 (promise)
swal 작동 안동 —> swal.fire 사용해야함


그러면 이렇게 Request에 ajax로 보낸 값이 잘 들어온다
slim → XXX

jQuery slim은 AJAX 지원 X
3. 완성 - 기존 비번 1234






4. 비밀번호 숨기기 보이기 (눈 이모지하고 싶옹…)


$(".togglePassword").on("click", function () { // 현재 클릭된 아이콘의 비밀번호 입력 필드 찾기 let input = $(password).siblings("input"); let type = input.attr("type"); if (type === "password") { input.attr("type", "text"); $(this).removeClass("fa-eye-slash").addClass("fa-eye"); } else { input.attr("type", "password"); $(this).removeClass("fa-eye").addClass("fa-eye-slash"); } });
toggleClass 로 하고 싶어서 이리저리 해봄 - 전체 input 다 먹힘 XXXX
$(".togglePassword").on("click", function () { // 현재 클릭된 아이콘의 이전 형제 요소인 입력 필드 찾기 let input = $(this).siblings("input"); // 입력 필드의 type 속성을 토글 input.attr("type", input.attr("type") === "password" ? "text" : "password"); // 아이콘의 클래스를 토글하여 시각적으로 상태 반영 $(this).toggleClass("fa-eye fa-eye-slash"); });
toggleClass 코드 수정
$('.togglePassword').on('click', function () { $(this).toggleClass('active'); if ($(this).hasClass('active')) { $(this).find("fa-eye").attr('class', "fa-eye-slash") .parents('.pw-box').find('#password').attr('type', "text"); } else { $(this).find("fa-eye-slash").attr('class', "fa-eye") .parents('.pw-box').find('#password').attr('type', "text"); } });
코드 가독성 좋게 수정
$('.togglePassword').on('click', function () { let input = $(this).siblings('input'); // 바로 옆의 비밀번호 필드 input.attr('type', input.attr('type') === 'password' ? 'text' : 'password'); // type 속성 토글 // 아이콘을 변경 $(this).toggleClass('fa-eye fa-eye-slash'); });
최종 재사용 코드(함수를 따로 뺌) - UI 한번에 퉁치는 건 없으니 수정전, 수정 후 따로 이모지 넣어주기~
비번 부분 말고 써야하는 토쿨이나 복잡한 로직이 없어서 굳이 따로 함수로 뺄 필요 없다고 생각하는데
눈 감는 것도 function 따로 빼기 → 한 번만 쓸 지, 여러번 쓸 지 모르기 때문에 이런건 일단 만들고 봐라 라고 해서 이부분은 굳이 따로 눈감는 것도빼야 하나 싶기는 해서 따로 빼지 않음
유지보수 때문에 한번 시도해보라고 한 것 같음


// 비밀번호 입력 필드 타입을 토글하는 함수 function togglePasswordVisibility($icon, $input) { // 입력 필드의 type 속성을 토글 $input.attr('type', $input.attr('type') === 'password' ? 'text' : 'password'); // 아이콘을 토글 $icon.toggleClass('fa-eye fa-eye-slash'); } // 토글 이벤트 핸들러 $('.togglePassword').on('click', function () { let $icon = $(this); // 클릭된 아이콘 let $input = $icon.siblings('input'); // 아이콘 옆의 입력 필드 // 비밀번호 보이기/숨기기 함수 호출 togglePasswordVisibility($icon, $input); });
Share article