Spring Boot를 이용한 RESTful Web Services 개발 #13 사용자 등록을 위한 API 구현 - POST HTTP Method

Jake Seo·2021년 9월 15일
0

Spring-boot-restful

목록 보기
13/17

addUser() 메소드 추가

    @PostMapping("")
    // @RequestBody: HTTP 요청 Body 영역에 User 객체가 올 것이다.
    public User addUser(@RequestBody User user) {
        return service.save(user);
    }

User 도메인 객체에 @NoArgsConstructor 추가

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private LocalDateTime joinDate;
}

@NoArgsConstructor를 추가해야 에러가 나지 않는다. 그 이유는 다른 포스팅에 상세히 정리하겠다.

내가 달았던 답변 기록

@NoArgsConstructor 애노테이션을 추가했을 때 작동이 정상적으로 되고 없었을 때는 안 됐던 이유는 요약하자면, Jackson2HttpMessageConverter 때문입니다.

처음에 스프링 부트를 로드하시면, 로깅 시에 Creating shared instance of singleton bean 'mappingJackson2HttpMessageConverter' 과 같은 것이 보일 것입니다. 요약하자면 해당 빈이 등록되었다는 이야기인데, 해당 빈은 스프링 부트 설정에 의해 자동으로 등록되어 쓰입니다.

해당 빈은 우리가 HTTP BODY에 JSON 문자열을 담았을 때, 그것을 자바 객체로 변환해주거나, 아니면 자바 객체로 만든 것을 컨트롤러에서 반환했을 때 JSON 문자열로 변환해주는 역할을 하고 있습니다.

또 'mappingJackson2HttpMessageConverter' 빈은 내부적으로 'ObjectMapper'라는 객체를 사용해서 JSON 문자열을 자바 객체로 바꾸거나, 자바 객체를 JSON 문자열로 바꾸는데, 'ObjectMapper' 객체는 바로 변환을 시작하는 게 아니라 처음에 일단 변경할 수 있는지 검증부터 합니다.

왜냐하면, 사용자가 잘못된 (제대로 시작되거나 끝나지 않은 혹은 쉼표가 부족한 경우 등) JSON 문자열을 넘기는 경우에 대해서도 대비를 해야하고, 자바 객체에 대해서도 올바른 Getter, Setter가 있는지, 어떤 생성자가 있는지 검증을 해야 변환 시 예측하지 못한 방향으로 로직이 흘러가지 않기 때문입니다. 이는 올바른 예외처리의 일환입니다.

ObjectMapper 내부에 BeanDeserializer가 존재하고, deserializeFromObject() 라는 메소드가 존재하는데, 이 메소드에서 기본 생성자가가 없으면 에러가 날 것입니다.

기본생성자가 없으면 에러가 나는 이유는 내부적으로 자바 리플렉션을 사용해서 입니다. 자바 리플렉션에 대해서 설명하기는 너무 장황하니 검색을 추천드립니다.

자바 리플렉션의 특성상 접근 제어자에 상관 없이 기본 생성자를 사용 가능하기 때문에 기본 생성자의 접근 제어자는 private이어도 무관합니다.

참고로 JPA에서도 같은 이유(리플렉션 사용)로 기본 생성자가 필수이니 참고하시면 나중에 도움이 되실 겁니다.

UserDaoService에서 save() 시에 joinDate 넣어주기

    public User save(User user) {
        if(user.getId() == null) {
            user.setId(++usersCount);
        }
        user.setJoinDate(LocalDateTime.now());

        users.add(user);
        return user;
    }
profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글