![[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