2022.11.20 TIL

SUADI·2022년 11월 21일
0

아.. 어제는 그제의 밀린 TIL을 작성하고 너무나도 귀찮아서 어제 TIL을 작성하지 않았었는데 친절하신 매니저님께서 슬랙에 친히 내 이름을 박제시켜주셔서 귀찮음을 무릅쓰고 어제의 TIL을 오늘 작성해보려고 한다. 오늘의 주제는 11월 17일 TIL에 ModelAttribute 관련된 이슈에서 해결 원인을 찾지 못했었는데 이 이슈에 대해 이야기해보려고 한다. TIL 시작.

[1] @ModelAttribute

프로젝트 VONGOLE에서 이미지를 업로드할 때, dto에 @ModelAttribute라는 어노테이션을 붙여서 요청을 들여온다. 이미지 업로드 부분은 성민님이 구현을 해주셨는데 나는 지금까지 RequestPart나 RequestParam을 이용해서 이미지를 받아왔는데 성민님 덕분에 ModelAttribute를 알게 되었고 나름 구글링을 하면서 공부를 해보았다.

{1} RequestParam

@RestController
@RequiredArgsConstructor
public class BoardController {
	
    private final BoardService boardService;
    
    public ResponseDto<BoardResponse> createBoard(@AuthenticationPrincipal UserDetailsImpl userDetails,
    											  @RequestParam String title,                                                  						
                                                  @RequestParam String content,
                                                  @RequestParam String author,
                                                  @RequestPart MultipartFile multipartFile) {
    	return boardService.createBoard(userDetailImpl.getMember(), title, content, author, multipartFile)                                               
	}                                         
}

예를 들어서 RequestParam을 사용해서 이미지를 받을 경우, 일일히 사용자의 요청을 받아오게 된다. 이 방법의 단점이라 하면 매개변수가 많아지면 많아질수록 코드가 복잡해지고 순서가 바뀌는 개발자 실수가 일어날 수 있다.

{2} ModelAttribute

반면 ModelAttribute의 경우에는 1대1 매핑을 해주는 RequestParam과는 달리 객체 매핑을 해주기 때문에 코드가 한결 깔끔해지고 순서가 바뀔 위험도 없다.

@RestController
@RequiredArgsConstructor
@RequestMapping("/boards")
public class BoardController {

    private final BoardService boardService;

    @PostMapping()
    public ResponseDto<BoardCreateResponse> createBoard(@AuthenticationPrincipal UserDetailsImpl userDetails,
                                                   @ModelAttribute @Valid BoardRequest boardRequest) throws IOException {
        return boardService.createBoard(userDetails.getMember(), boardRequest);
    }

하지만 ModelAttribute를 사용 시 유의해야 할 점이 있다.

{3} ModelAttribute 사용시 주의할 사항

ModelAttribute를 사용할 때 객체 매핑이 저절로 되는 것이 아니라 어떤 설정을 해줘야만 한다. 코드를 보며 예를 들어 설명해 보면,

@Getter
@AllArgsConstructor
public class BoardRequest {

    @NotEmpty(message = "빈 칸을 채워 주세요.")
    private String title;

    @NotEmpty(message = "빈 칸을 채워 주세요.")
    private String content;

    private MultipartFile boardImage;

   ...
}

@ModelAttribute 설정을 해준 dto를 객체로 바인딩해주기 위해서는 두가지 방법이 있다.

  1. @AllArgsConstructor를 이용해서 각 필드를 초기화한 객체를 생성한다.

  2. @NoargsConstructor과 @Setter로 각각의 필드 초기화
    이 방법은 기본 생성자로 객체를 생성한 후, 각 필드들을 setter로 초기화하는 방법으로 객체를 바인딩하게 된다.

@Getter
@NoArgsConstructor
@AllArgsConstructor
public BoardRequest {
	...
}

나는 지금까지 그냥 습관적으로 위의 코드처럼 NoArgsConstructor와 AllArgsConstructor를 같이 붙여왔던 것 같다. 이렇게 코드를 짰더니 NullpointerException이 뜨게 되었다. 그 당시에는 도저히 뭐가 문제인지 모르겠어서 진구 님께 도움을 요청했었는데 생성자 중에 NoArgsConstructor를 이용해서 객체를 생성하게 된 것 같아서 초기화가 안되어 있어 NullpointerException이 뜬 것 같다고 알려 주셨다.

NoArgsConstructor 어노테이션을 제거함으로써 에러를 잡을 수 있었다.
생각이 담기지 않은 코드가 이렇게 무섭다. 새삼 다시 한 번 코드 한 줄 한 줄을 생각하면서 작성해야겠다고 생각했던 이슈였다.

0개의 댓글

관련 채용 정보