회원정보 수정 구현 -2-

jihan kong·2023년 8월 22일
0
post-thumbnail

회원정보 변경 기능 구현 ing...

저번 포스팅에서 보다시피 비밀번호를 입력했을 때, 회원 정보를 수정할 수 있는 폼을 띄우는 것까지 구현을 마쳤다.

이제 실제로 View를 통해 회원 관련 정보들을 수정하고 이를 DB에 업데이트하는 기능을 마무리해볼 것이다.

1. MemberUpdateDto

회원 정보를 수정하기 위해 회원 업데이트 정보만을 받는 Dto를 설계했다. 단순히 데이터를 전달할 목적이기 때문에 회원가입 기능 구현 당시 MemberForm을 통해 정보를 받았던 MemberFormDto 와 크게 다르지 않다. 여러 유효성 검증을 통해 회원정보를 업데이트할 때, 조건을 주기로 했다.

MemberUpdateDto.java

// ..import 생략

@Data
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class MemberUpdateDto {

    @NotBlank(message = "이메일을 입력해주세요.")
    @Email(message = "올바른 이메일 주소를 입력해주세요.")
    private String email;

    @NotBlank(message = "이름을 입력해주세요.")
    private String name;

    @NotEmpty(message = "비밀번호는 필수 입력 값입니다.")
    @Length(min=8, max=16, message="비밀번호는 8자 이상, 16자 이하로 입력해주세요")
    private String password;

    @NotEmpty(message = "우편번호는 필수 입력 값입니다.")
    private String zipcode;

    private String streetadr;

    private String detailadr;
}

2. MemberController

다음은 Controller이다.

MemberController.java

// import 생략

@RequestMapping("/members")
@Controller
@RequiredArgsConstructor
public class MemberController {

	// 회원 정보 변경 폼 (GET)
	@GetMapping(value = "/updateForm")
    public String updateMemberForm(Principal principal, Model model) {
        String loginId = principal.getName();
        Member memberId = memberRepository.findByEmail(loginId);
        model.addAttribute("member", memberId);

        return "/settings/memberUpdateForm";
    }
}    

비밀번호를 입력하고 회원 정보 수정 폼을 띄울 수 있게 해준다. 이 때, principal 객체를 통해 현재 로그인한 회원 정보를 memberRepository 에 전달해서 회원에 알맞은 정보를 model을 통해 View를 구성하게 한다.


뷰의 경우, 기존의 member 패키지에 파일들이 많기도했고 앞으로 회원 관련 수정 기능들이 더 추가될수도 있을 것 같아서 settings 라는 새로운 패키지를 만들기로 했다.

resources > templates > settings > memberUpdateForm
회원정보를 업데이트하는 Form을 생성했다.

(전체적으로 마이페이지와 비슷하지만 readonly를 해제하여 회원정보를 수정할 수 있게끔 했다.)


GET 으로 회원정보 수정 폼을 조회했다면 이제 POST 방식으로 데이터를 넘겨줘야할 차례이다.

MemberController.java

// ..import 생략

@RequestMapping("/members")
@Controller
@RequiredArgsConstructor
public class MemberController {
	
    // 회원 정보 변경 폼 (GET)
    
    // 회원 정보 변경 (POST)
    @PostMapping(value = "/updateForm")
    public String updateMember(@Valid MemberUpdateDto memberUpdateDto, Model model) {
        model.addAttribute("member", memberUpdateDto);
        memberService.updateMember(memberUpdateDto);
        return "redirect:/members/myInfo";
    }
  • 파라미터로 유효성검사 Valid 를 거친 MemberUpdateDto 와 Model을 받는다.
  • 추후 구현할 memberService의 updateMember 메서드에 Dto의 내용을 전달한다.
  • POST 되었으면 다시 마이페이지로 리다이렉트한다.

3. Member

Member Entity에 직접 수정할 수 있는 메서드를 구현한다. 사실 Entity에 이런식으로 구현하면 다른 구현체가 이것을 참조-변경할 가능성이 높아진다. 따라서 Best practice는 아니지만... 일단은 Entity의 멤버변수를 직접 변경하는 방식을 사용했다.

Member.java

// import 생략

@Builder
@Entity
@Table(name="member")
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Member extends BaseEntity implements UserDetails { 

	/**
     * 회원수정 메소드
     */
    public void updateUsername(String name) { 
    	this.name = name; 
    }

    public void updatePassword(String password) {
        this.password = password;
      }

    public void updateOriginalPassword(String originalpassword) {
        this.originalpassword = originalpassword;
    }

    public void updateAddress(String address) { 
    	this.address = address; 
    }

    public void updateStreetAddress(String streetaddress) { 
    	this.streetaddress = streetaddress; 
    }

    public void updateDetailAddress(String detailaddress) {
    	this.detailaddress = detailaddress; 
    }
}    

4. MemberService

Service단을 만질 차례이다.
Member Entity에서 만들어놓은 회원정보 변경 메서드에 UpdateDto 의 내용을 넣는 방식으로 간단하게 구현했다.

MemberService.java

// ..import 생략

@Service
@Transactional                                            
@RequiredArgsConstructor                                    
public class MemberService implements UserDetailsService {	
    
    /** 회원정보 수정 **/
    public Long updateMember(MemberUpdateDto memberUpdateDto) {
        Member member = memberRepository.findByEmail(memberUpdateDto.getEmail());
        member.updateUsername(memberUpdateDto.getName());
        member.updateAddress(memberUpdateDto.getZipcode());
        member.updateStreetAddress(memberUpdateDto.getStreetadr());
        member.updateDetailAddress(memberUpdateDto.getDetailadr());
        member.updateOriginalPassword(memberUpdateDto.getPassword());

        // 회원 비밀번호 수정을 위한 패스워드 암호화
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodePw = encoder.encode(memberUpdateDto.getPassword());
        member.updatePassword(encodePw);

        memberRepository.save(member);

        return member.getId();
    }

한 가지 주의점은 클라이언트가 Form에서 입력한 패스워드를 그대로 member Entity에 업데이트시키면 오류가 발생한다.
(Encoded password does not look like BCrypt 와 같은 오류 메세지를 받게 될 것이다.)

암호화하지 않은 상태에서 날것의 패스워드를 저장하려고 하면 Security에서 캐치해 오류를 뿜는 것이다. 이를 방지하기 위해 BCryptPasswordEncoder 를 통해 비밀번호를 암호화하는 작업을 진행하자.


5. 동작 화면 🕹️

이번 구현은 에러가 나지 않고 스무스하게 동작했다! 아니, 정확히는 에러가 났었지만 비교적 쉽게 해결할 수 있었다.🥰 여튼 회원정보 수정은 다음과 같이 동작한다.

마이페이지에서 회원정보 변경 버튼을 클릭하면...

위와 같이 비밀번호를 확인하는 창이 뜨게되고, 이 때 가입했던 회원 비밀번호를 입력한다면...

위와 같이 PK인 회원 이메일을 제외한 다른 정보들을 수정할 수 있는 폼이 뜨게 된다. 비밀번호의 경우, JS를 이용해 비밀번호 변경 버튼을 누르면 Readonly가 해제되고 원하는 비밀번호를 입력할 수 있게끔 만들었다.

원하는 비밀번호와 회원 정보들로 바꿔보자. 아래와 같이 바꾸어보았다.

수정을 누르니 마이페이지로 이동했고, 원하는대로 회원정보들이 변경된 것이 보인다.


(SQL로도 확인해보았는데 잘 변경된 모습이다.)

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글