회원가입에 관해서 기능이 추가될 것이 없는지 계속 생각하다가 한 가지 중요한 기능을 빠뜨렸다는 것을 깨달았다.😓 현재 플젝으로 만들고 있는 사이트는 쇼핑몰 사이트라는 것을 감안해볼 때, 고객들이 등록된 상품을 구입할 때, 구입한 상품이 자택 혹은 원하는 배송지로 배송되기 위해서는 사용자의 주소를 알고 있는 것이 가장 중요하다.
물론 전에 회원가입 기능을 구현할 때, 아래와 같이 폼을 통해 주소 값을 입력받게 하였고, Controller
와 Entity
등의 로직들을 통해 실제로 입력된 주소값이 유저 정보로 Insert되는 것은 전혀 문제가 없도록 만들었다.
위 코드는 돌아가는데 전혀 문제가 없다. 그러나, 전혀 "user-friendly" 하지 않다.
세상에 어떤 사이트가 사용자에게 자신의 자택 주소나 우편번호을 직접 입력하게 하는가? 당장 내가 만약 회원가입을 해야하는데 직접 우편번호와 자택 주소를 검색해와서 입력해야한다면 깊은 짜증이 몰려올 것이다.🤬 물론 예전에는 그런 경우도 있었겠지만 사용자 친화적인 설계로 개발하는 요즘엔 이렇게 사이트를 구성한다면 수 많은 컴플레인이 접수되는 것은 불보듯 뻔한 상황이다.
어떤 사이트에 접속하여 회원가입을 할 때, 집주소만 입력하면 우편번호와 주소가 자동으로 입력되는 것을 경험해보았을 것이다. 이는 API를 활용한 것으로 이 기능을 통해 전체 주소를 입력하는 번거로움을 덜 수 있다. 여러가지 API가 있지만 나는 다음 주소 API를 사용하여 구현했다.
💡 다음 주소 API
-> 자세한 방법은 http://postcode.map.daum.net/guide 에 가이드가 나와있다.
일단 가장 먼저 당연히 Member
Entity를 손봐야했다. 기존에 address 하나로 뭉뚱그리던 속성을 좀 더 세분화시켰다.
Member.java
package com.shop.entity;
@Builder
@Entity
@Table(name="member")
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Member extends BaseEntity{
@Id
@Column(name="member_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@Column(unique = true)
private String email;
private String password;
private String picture;
private String address; // 우편 번호
// 새롭게 추가된 코드
private String streetaddress; // 지번 주소
// 새롭게 추가된 코드
private String detailaddress; // 상세 주소
@Enumerated(EnumType.STRING)
private Role role;
private String provider;
private String providerId;
public static Member createMember(MemberFormDto memberFormDto,
PasswordEncoder passwordEncoder) {
Member member = new Member();
member.setName(memberFormDto.getName());
member.setEmail(memberFormDto.getEmail());
// member에 각 속성을 set하기 위해 memberFormDto에 추가해야할 내용
member.setAddress(memberFormDto.getZipcode());
member.setDetailaddress(memberFormDto.getDetailadr());
member.setStreetaddress(memberFormDto.getStreetadr());
String password = passwordEncoder.encode(memberFormDto.getPassword());
member.setPassword(password);
member.setRole(Role.USER);
return member;
}
String address
: 기존 주소 값을 저장하던 속성에서 우편번호를 저장하는 속성값으로 변경했다.
String streetaddress
: 지번 주소를 저장하는 속성
String detailaddress
: 상세 주소를 저장하는 속성
또한, member 클래스에 속성을 받아오기 위해 memberFormDto
에도 같은 속성들을 구현해야한다.
MemberFormDto.java
package com.shop.dto;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
@Getter
@Setter
public class MemberFormDto { // 회원 가입 화면으로부터 넘어오는 가입정보를 담을 dto
@NotBlank(message = "이름은 필수 입력 값입니다.")
private String name;
@NotEmpty(message = "이메일은 필수 입력 값입니다.")
@Email(message = "이메일 형식으로 입력해주세요.")
private String email;
@NotEmpty(message = "비밀번호는 필수 입력 값입니다.")
@Length(min=8, max=16, message="비밀번호는 8자 이상, 16자 이하로 입력해주세요")
private String password;
// 새롭게 추가된 코드들
@NotEmpty(message = "우편번호는 필수 입력 값입니다.")
private String zipcode;
private String streetadr;
private String detailadr;
private String role;
}
이제 사용자로부터 zipcode(우편번호), streetadr(지번주소), detailadr(상세주소)을 받을 수 있게 되었다.
타임리프와 JS는 (https://kingchobocoding.tistory.com/9) 이 블로그를 많이 참조하여 구현했다.
언제나 느끼지만 타임리프는 정말 간편하다! th:field
문법하나로 html
(memberForm)과 Java class file
(MemberFormDto)를 매핑할 수 있다니...
쉬운 API였는데도 구현하는데 거의 다섯시간이 걸렸다..😂 타임리프에서 데이터를 매핑할 때, 조금 애를 먹었고 address
클래스를 어떻게 구현해야할지를 고민하느라 였던 것 같다. 다음은 동작화면이다.
그리고 여담이지만 전체적으로 프론트를 많이 수정했다! (이상하게 html과 css를 만질 때 더 재미있는 것 같은 느낌은 왜일까...ㅎㅎ)
여튼 메인화면은 다음과 같다.
로그인 화면이다.
회원가입 버튼을 누르면 아래와 같이 회원가입 폼과 구현해놓은 주소찾기 기능이 뜬다.
한번 주소찾기 API를 이용하여 실제 회원가입을 해보자. (움짤입니다...)
실제 사는 곳도 아니고 저런 아파트가 있지는 않다!😂 예시로만 참고해주시길...!
이제 회원가입이 되었으니 DB를 살펴보자. MySQL Workbench을 실행하고 저장된 회원을 select해보면 회원가입 폼에 입력한대로 잘 저장이 된 것을 볼 수 있다.