순간을 성실히, 화려함보단 꾸준함을

인텔리제이 .http 파일로 MultipartFile 전송해보기 본문

나의 개발 메모장

인텔리제이 .http 파일로 MultipartFile 전송해보기

폭발토끼 2023. 8. 19. 09:55

안녕하세요!

글또 활동을 마치고 처음 적는 글입니다

 

오늘은 아무리 구글링해도 알 수 없어서 제가 직접 하나하나 고생하면서 알아낸 Tip(?) 을 ㅋㅋㅋㅋㅋ 적어보려고 합니다.

제목 처럼 인텔리제이에서 .http 파일을 사용하여 http 요청을 보낼 수 있습니다.

 

IntelliJ의 .http를 사용해 Postman 대체하기 (tistory.com)

 

IntelliJ의 .http를 사용해 Postman 대체하기

안녕하세요! 이번 시간엔 IntelliJ의 .http 파일을 어떻게 사용하는지 소개드리겠습니다. 모든 코드는 Github에 있습니다! 소개 프로젝트를 계속 운영하다보면 로컬 환경외에 개발/운영 환경에서 API

jojoldu.tistory.com

유명한 블로그이시자 개발바닥 채널을 운영하고 계시는 향로님의 글인데 이 글을 읽기전에 참고하시면 좋을 것 같습니다.

 

배경

사이드 프로젝트를 진행 도중에 image 파일을 업로드하는 API 를 테스트 해야됐습니다.

postman 을 사용하여 테스트 했을땐 문제없이 원하는 바로 동작을 했습니다.

그 다음 .http 파일을 생성하여 인텔리제이에서 동일하게 해당 API 를 테스트 하려고 했지만,,,,,file 은 어떻게 요청을 보내야지???? 라는 의문점과 같이 열심히 구글링을 했지만 정확히 어떤식으로 정의해야 할지 모르겠더라고요...

 

과정

1. postman 으로 요청 정상 확인

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/user")
public class UserController {

    private final UserService userService;

	...

    /**
     * 유저 프로필 사진 업로드(U002)
     */
    @PostMapping("/profile/image")
    public CommonResponseEntity<UserProfileImageResponseDTO> uploadProfileImage(
    							   @Authentication LoginSession session,
                                   @ModelAttribute @Valid UserProfileImageRequestDTO imageDTO){
        return CommonResponseEntity.toResponseEntity(
        			ResponseType.U002,userService.saveProfileImage(session,imageDTO),1);
    }

}

유저의 프로필 사진을 업로드 하는 API 가 존재합니다.

(LoginSession 은 무시해주세요!!!)

@Setter
@Getter
@NoArgsConstructor
public class UserProfileImageRequestDTO {

    @ValidFile(message = "EXU005")
    private MultipartFile file;

    public UserProfileImageRequestDTO(MultipartFile file) {
        this.file = file;
    }

}

request dto 는 MultipartFile 객체 하나만 받고 있습니다.


※@ModelAttribute

@ModelAttribute 의 동작 방식을 재대로 이해하지 못하는 분들이 꽤 계시는데 @NoArgsConstructor 어노테이션을 사용한다면 반드시 @Getter 와 @Setter 가 필수적입니다.
HandlerMethodArgumentResolver 를 implements 하는 ModelAttributeProcessor 는 기본생성자를 통해 객체를 생성하고 setter 를 이용하여 데이터를 바인딩 해주기 때문입니다.

그럼 무조건 위와 같은 방식으로만 동작하는건가요?!!!
절대!! 아닙니다.

@NoArgsConstructor 가 아닌 @AllArgsConstructor 를 사용한다면 @Setter는 강제되지 않습니다.

더 많은 정보를 얻고 싶으신 분들은 [Spring] @ModelAttribute 처리 흐름 (tistory.com) 해당 블로그를 참고해주세요!


해당 프로젝트를 실행시키고 postman 으로 한번 요청을 보내봅시다 !

위와 같이 요청을 보낸 후 controller 에서 breaking point 를 걸어서 확인해보면

정상적으로 잘 요청이 온 걸 확인할 수 있습니다

 

2. .http 파일을 사용해보기

이제 문제의 .http 파일을 이용하여 MultipartFile 을 요청보내보도록 해봅시다.

Exploring the HTTP request syntax | IntelliJ IDEA Documentation (jetbrains.com)

 

Exploring the HTTP request syntax | IntelliJ IDEA

 

www.jetbrains.com

jetbrain 공식홈페이지에 나와있는 공식문서를 참고하였습니다.

 

To send a file as part of the multipart/form-data message, include the filename parameter in the Content-Disposition header.

 

파일을 포함한 multipart/form-data 를 요청할때는 Content-Disposition header 에 filename 파라미터를 정의하라고 하네요!

그리고 각 파라미터는 boundary 로 구분이 되어져야 합니다!

(주의할 점은 마지막 boundary 는 끝에 -- 문자를 추가해주어서 끝이라는걸 알려주어야 합니다)

 

이렇게 정의하고 요청을 보내면?

마찬가지로 정상적으로 들어오는걸 확인할 수 있었습니다.

 

지금은 file 하나만 요청받고 있는데 만약 다른 변수들과 같이 전송할때는 어떻게 해야 될까요????

위에 기술했듯이 boundary 로 구분해 준 후 Content-Disposition header 에 파라미터명을 정의해주면 됩니다.

 

예시로 하나의 게시글에는 이미지를 포함한 게시글 제목, 게시글 내용 등등 많은 컨텐츠들이 들어갈 수 있겠죠?

위와 같이 정의해주면 됩니다!

 

3. postman 요청은 되는데 .http 요청은 안돼요!!!!

이번 게시글의 핵심인데요, 사실 저는 공식문서를 참고하지 않고 문제를 해결했었습니다.

postman 으로는 잘 들어가는데 .http 파일에서는 어떻게 정의해서 요청을 보내야 될지 잘 몰랐거든요.....

 

그래서 제가 선택한 방법은 Content-Type 이 multipart/form-data 일때 http request message 을 확인해보자!!!!였습니다.

 

바로 Http11InputBuffer 를 사용해서 말이죠.

Http11InputBuffer 가 뭔데요?????


Http11InputBuffer 란?

- tomcat 웹 서버 컨테이너에서 사용되는 클래스로 Http 요청의 본문 데이터를 읽어오는 역할을 수행합니다.

 

기능

1. 클라이언트로부터 Http request message 를 파싱하여 요청 라인, 헤더 및 본문 데이터로 분리합니다.

2. 요청 본문을 처리합니다. Post , Put 과 같은 요청이 해당되겠네요

3. 클라이언트가 멀티파트 형식으로 파일을 업로드 하면 해당 파일 데이터를 처리하고 저장합니다.


즉, Http11InputBuffer 를 통해서 요청받는 http message 가 어떤형식으로 들어오는지 확인할 수 있다는 걸 뜻합니다.

Http11InputBuffer 라는 존재를 알았으니 이를 활용하여 우리가 직접 http request message 를 확인해봐야겠죠?

 

loggin level 에서 debug 모드로 설정한다면 console 창에 확인할 수 있습니다.

application.yml 에서 설정해주면 됩니다

자, 그러면 요청을 보내볼까요?

console 창에 잘 나오는걸 확인할 수 있었습니다.

그래서 전 인텔리제이 .http 에서 위와 같은 message 를 확인하여 동일하게 적용해주어서 해결할 수 있었습니다.

 

결과

배울 수 있었던 점이 많았던 귀한 경험이었습니다.

 

1. @ModelAttribute 동작방식

2. 인텔리제이 .http 를 이용하여 multipart/form-data 를 요청보내는 방법

3. Http11InputBuffer

 

혹시 다른분들도 저와 비슷한 문제를 마주하셨다면 위 글이 도움이 되셨으면 좋겠네요

감사합니다!