[새벽세시] 회원가입 기능 구현 - Controller, Service

Hoehenflug·2022년 2월 15일
1
post-thumbnail
post-custom-banner

👭 이어서 회원가입 기능을 위한 Controller, Service 단을 구현해본다.


🚙 Controller 생성 및 작성

회원가입 요청은 Post 방식으로 접속/요청이 들어오면 처리하게 된다.

@Controller
public class UserController {

    @Autowired
    private UserService userServiceImpl;
    
    // 회원 가입 요청
    @PostMapping("/auth/signUpProc")
    public ResponseEntity<?> signUp(@RequestBody User user) {
    	return ResponseEntity.ok(userServiceImpl.join(user));
    }
}

Controller에서는 HTTP에 맞는 응답을 클라이언트에게 제공해줘야 한다. 예전 프로젝트에서는 @ResponseBody 어노테이션을 사용해 응답을 전달했는데 이번에는 ResponseEntity를 사용해봤다. status code 200으로 userServiceImpl.join(user)을 response 본문에 담아서 보냈다.(@ResponseBody와 ResponseEntity의 사용 시 차이점도 좀 더 정확히 짚고 넘어가야지...)

🛺 Service 생성 및 로직 구현

Service의 경우 UserService와 같이 서비스 부분을 interface로 설계하고, UserServiceImpl이라는 구현체인 클래스를 별도로 생성해 사용하는 방식으로 설계했다. (구현체 클래스의 확장성과 독립성을 위한 것이라고 알고 있는데 습관적으로 사용하던 이 방식에 대해서 좀 더 자세히 알아보아야겠다.)

1. UserService interface 생성

public interface UserService {

    // 회원가입
    @Transactional
    public BaseResponseDTO join(User user);
}

2. UserServiceImpl 생성

UserServiceImpl은 UserService interface를 implements하고 각 메서드들은 override해서 사용한다.

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BCryptPasswordEncoder encoder;
    
    // 회원가입
    @Override
    @Transactional
    public BaseResponseDTO join(User requestUser) throws ApiException {

        String rawPassword = requestUser.getPassword
        String encPassword = encoder.encode(rawPassword);
        requestUser.setPassword(encPassword);

        if (userMapper.join(requestUser) != 1) {
            return BaseResponseDTO.builder()
                    .code("ER004")
                    .messageType(BaseResponseDTO.FAIL)
                    .message("회원가입에 실패했습니다.")
                    .build();
        }
        
        return BaseResponseDTO.success("회원가입에 성공했습니다.");
    };
}

체크할 점은 spring security에서 지원하는 BCryptPasswordEncoder를 이용해 회원가입 시 받은 password를 암호화시킨 부분이다. password의 암호화 부분은 다음의 순서로 이뤄진다.

String rawPassword = requestUser.getPassword(); // 입력받은 User 객체에서 원래의 password get
String encPassword = encoder.encode(rawPassword); // 원래의 password를 BCryptPasswordEncoder class에 내장되어 있는 encode 메서드를 이용해 암호화
requestUser.setPassword(encPassword); // 암호화 된 password를 User 객체의 password로 새로 set

참고로 join 메서드를 보면 throws ApiException을 하고 있다. ApiException에 대한 부분은 에러 처리와 관련해 따로 구현한 부분인데 추후 포스팅을 할 예정이다.

또, 참고로 회원가입과 관련해 필요한 유효성 검사들도 물론 해줬다. 따로 Utils class를 만들어 구현해줬는데 마찬가지로 추후 포스팅 할 예정이다.

userMapper.join(requestUser)은 이전 포스팅에서 작성한 회원가입과 관련한 insert문이다. 해당 SQL을 호출해 1을 반환하지 않으면 삽입된 행이 없다는 의미이므로 회원가입에 실패한 것으로 보고 회원가입에 실패했다는 메세지를 던져준다.

SQL 참고

  • insert : 삽입된 행의 개수 반환
  • update : 수정에 성공한 행의 개수 반환
  • delete : 삭제한 행의 개수 반환

마지막으로 보다시피 join 메서드의 return 타입은 BaseResponseDTO이다. 앞으로 모든 Service 단에서의 모든 메서드들의 return 타입은 BaseResponseDTO로 구현될 것이다. BaseResponseDTO에 대해서도 따로 포스팅 할 예정이다.
우선 회원가입에 성공하면 회원가입에 성공했다는 메세지를 던져준다는 점!


💪🏻 기록

@ResponseBody와 ResponseEntity 차이, ApiException, Utils, BaseResponseDTO... 따로 포스팅해야 할 부분이 참 많다..부지런해져야 한다!..
사실 프로젝트 처음에는 Controller는 @ResponseBody를 사용해 응답을 전달했고 따로 만들어 둔 ResponseDto(BaseResponseDTO와 다른 Dto)를 리턴했었다. Service에서도 Map을 사용해 메세지나 데이터를 담아 리턴했었는데 코드리뷰도 받고, 다른 분들의 코드를 살펴보며 지금처럼 구현하게 되었다.
Controller는 Controller의 역할에 충실하도록, 정말 요청을 받고 응답을 전달해주는 교통경찰(?) 역할을 해주도록 코드를 구현하고 싶었는데 서비스 로직이 포함되는 경우가 적지 않아 마음에 들지 않았는데, 이렇게 구현하게 되며 그나마 이 부분에 있어서는 조금 마음에 드는 코드가 나온 것 같다!

post-custom-banner

0개의 댓글