이번 포스팅은 회원가입을 포스팅해보겠다
먼저 이번 포스팅에 필요한 의존성이다
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'
인증 인가의 경우
상대적으로 간단하고 순서상 회원가입이 되어야하기때문에 회원가입을 먼저 개발해보자
비즈니스에 맞게 회원가입 dto를 작성해보자
내 비즈니스에서는 받아야할 정보가 username(아이디로 쓸 컬럼), email, password, role, department, full_name 이다.
부서 비즈니스는 아직 미개발이므로 그 쪽은 임시코드로 개발하도록 하겠다
@Getter
@NoArgsConstructor
@Builder
@AllArgsConstructor
public class SignUp {
private String username;
private String email;
private String password;
private String confirmPassword;
private String role;
private Integer department;
private String phone;
private String fullName;
}
이렇게 만든 SignUp Request를 우리는 User와 UserProfile로 변경해주어야한다
@Builder
public static User SignUpToUser(SignUp signUp, String passwordEnc) {
return User.builder()
.username(signUp.getUsername())
.email(signUp.getEmail())
.password(passwordEnc)
.role(signUp.getRole())
.createdAt(LocalDateTime.now())
.isDeleted(false)
.build();
}
@Builder
public static UserProfile SignUpToUserProfile(Long userId, SignUp signUp) {
return UserProfile.builder()
.userId(userId)
.departmentId(signUp.getDepartment())
.fullName(signUp.getFullName())
.phone(signUp.getPhone())
.build();
}
각 엔티티에 빌더 메서드를 하나 생성해 만들어주는 코드를 작성한다.
그 다음은 드디어 서비스 코드다.
먼저 서비스단에 비즈니스 코드를 적기전에 코드를 구상해본다
회원가입에 들어가는 기능이라면
1. 아이디 중복체크
2. 비밀번호와 비밀번호 확인 체크
3. 비밀번호 암호화
간단하게 이정도 기능을 가지고 있다.
그럼 아이디 중복체크와 비밀번호 체크는 자바 코드상으로 해결하면 되고
비밀번호 암호화는 어떻게할까?
암호화의 종류는 정말 많고 복잡하다. 다만 우리가 쓰는 Spring Security 의존성에는 편리하게 사용할 수 있는 인터페이스가 미리 정의되어있어
설정파일을 통해 bean에 미리 등록해주면 의존성 주입을 받아 사용할 수 있게된다.
PasswordEncConfig.class
@Configuration
public class PasswordEncConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserService
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final UserProfileRepository userProfileRepository;
private final PasswordEncoder passwordEncoder;
@Transactional
public Void createUser(SignUp signUp) {
checkUserExist(signUp.getUsername());
checkPasswordConfirm(signUp.getPassword(), signUp.getConfirmPassword());
User user = userRepository.save(User.SignUpToUser(signUp, passwordEncoder.encode(signUp.getPassword())));
userProfileRepository.save(UserProfile.SignUpToUserProfile(user.getId(), signUp));
return null;
}
private void checkUserExist(String username) {
if (!userRepository.isUsernameAvailable(username)) {
throw new CustomException(UserException.ALREADY_EXISTS);
}
}
private void checkPasswordConfirm(String password, String confirmPassword) {
if (!password.equals(confirmPassword)) {
throw new CustomException(UserException.MISS_MATCH_PASSWORD);
}
}
}
완성된 간단한 회원가입 로직이다.
음.. 특이한점은 userProfileRepository을 저장할 때 user.getId()를 바로 가져오는 형태인데
save로 먼저 저장을 하고 저장한 객체에 접근하여 데이터를 변경하여도 DB에 적용이 된다.
이는 JPA의 영속성과 관련된 부분으로 save를 통해 user를 영속성 컨테이너에 저장하여 저장된 영속 엔티티들은 DB와 동일성을 보장해주기때문에 가능한 방법이다.
또 createUser가 Void 타입을 반환하도록 되어있는데 이는 나중에 토큰을 반환하는 형식으로 변경하기 위한 임시코드이다.
이제 마지막으로 컨트롤러를 작성하러 가자
UserController.class
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/user")
public class UserController {
private final UserService userService;
@PostMapping("/sign-up")
public Response<Void> signUp(@RequestBody SignUp signUp) {
return Api.success(200, "success", userService.createUser(signUp));
}
}
컨트롤러 코드이다.
이제 서버를 실행하고 해당 api를 호출해보자
유효성 검사도 체크 해주고
이제 가입을 해보자
의도한대로 user 테이블과 userProfile 테이블에 잘 들어감을 확인했다!
이제 대망의 로그인기능을 다음에 포스팅 해보겠다