File과 Map을 동시에 Controller에서 동시에 받아야 할 경우

2025. 1. 3. 15:06·현업에 종사하면서 발견한 문제점

회사에서 일하면서 Map과 File을 동시에 Request받아야 할 일이 생겼습니다.

 

Content-Type - Application/json

Map 객체는 JSON 형태로 보내야 합니다.

예를 들어, 클라이언트에서 JavaScript 객체 형태로 Map 데이터를 JSON으로 변환하여 서버에 전송할 수 있습니다.

{
  "key1": "value1",
  "key2": "value2"
}

이 데이터는 HTTP 요청의 Content-Type이 application/json이어야 하며,

Spring의 @RequestBody 어노테이션을 사용하여 매핑할 수 있습니다.

@PostMapping("/api/data")
public String handleData(@RequestBody Map<String, Object> map) {
    // map 데이터 처리
    return "Data received";
}

 

 

Content-Type: multipart/formed-data

반면, 파일 데이터를 전송하려면 Content-Type이 multipart/form-data이어야 합니다.

이때는 파일 외에도 다른 폼 데이터(예: 텍스트 데이터)도 함께 전송할 수 있습니다.

클라이언트는 파일을 FormData 객체로 만들어 전송합니다.

const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("key1", "value1");
formData.append("key2", "value2");

fetch('/api/upload', {
    method: 'POST',
    body: formData
});

서버에서는 @RequestParam을 사용하여 파일을 받아올 수 있습니다.

예를 들어, 파일을 MultipartFile 객체로 받을 수 있습니다.

@PostMapping("/api/upload")
public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
    // 파일과 추가 파라미터 처리
    return ResponseEntity.ok("File uploaded successfully");
}

 

 

문제점:

Map 데이터와 File 데이터를 동시에 처리할 때의 주요 문제는 Content-Type 헤더가 서로 다르다는 점입니다.

  • **application/json**은 JSON 형태의 데이터를 서버에서 처리하기 위한 것이고,
  • **multipart/form-data**는 파일 업로드와 같은 다중 폼 데이터 전송을 위한 것입니다.

이때 문제가 발생하는 이유는 Spring이 Content-Type을 기준으로 요청을 처리하는 방식에 있습니다.

만약 하나의 요청에 두 가지 Content-Type이 혼합되어 있으면

Spring은 이를 구분할 수 없어서 오류가 발생할 수 있습니다.

 

문제 발생 시:

클라이언트에서 파일과 JSON 데이터를 함께 전송하려 할 때, Spring은 이를 처리하기 위한 별도의 로직이 필요합니다.

만약 파일과 JSON 데이터를 함께 보내면, Spring은 기본적으로 하나의 Content-Type만 인식할 수 있기 때문에,

파일을 받을 때는 multipart/form-data로 인식하고,

JSON 데이터는 application/json으로 처리하려고 시도하면서 충돌이 발생할 수 있습니다.

 

오류 메시지 예시:

org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present

이 오류는 @RequestBody로 JSON 데이터를 처리하려고 시도하면서

@RequestParam으로 처리해야 할 파일이 누락된 것처럼 처리되는 경우 발생할 수 있습니다.

 

 

해결 방법:

Map형태는 무조건 Json형태로만 보내어야 할까?

우리는 정해진 틀에만 의존하지 않고, 유연한 방식으로 파일과 데이터를 처리할 수 있어야합니다.

Map형태도 동일하게 form-data형태로 추가를 해주어 실제 file로 받을 수 있게 해준 후

백엔드에서 클라이언트에서 JSON 형태로 보내는 Map 데이터를 String으로 받아서,

이를 다시 Map 객체로 변환하여 사용할 수 있습니다.

@PostMapping("/api/upload")
public String handleFileAndData(
        @RequestPart("file") MultipartFile file,
        @RequestPart("mapData") String mapData) {
    
    // Map 데이터는 JSON 형태로 받아서 Map으로 변환
    ObjectMapper objectMapper = new ObjectMapper();
    Map<String, Object> map = null;
    try {
        map = objectMapper.readValue(mapData, new TypeReference<Map<String, Object>>(){});
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        return ResponseEntity.badRequest().body("Invalid map data");
    }

    // 파일과 map 데이터 처리
    return "File and data received successfully";
}

이렇게 File 형태로 데이터를 받은 후 file객체의 문자열을 객체화 시켜주는 Object Mapper를 활용하여

다시 객체화 시켜줌으로써 백엔드에서 Map데이터를 사용 할 수 있게 되었습니다~!

 

'현업에 종사하면서 발견한 문제점' 카테고리의 다른 글

@Controller, @RestController 차이점  (0) 2024.02.25
DTO 와 VO의 차이에 대하여  (0) 2024.02.25
'현업에 종사하면서 발견한 문제점' 카테고리의 다른 글
  • @Controller, @RestController 차이점
  • DTO 와 VO의 차이에 대하여
Developer Covy
Developer Covy
🚀Let's become a growing developer again today!👊
  • Developer Covy
    Developer Covy
    Developer Covy
  • 전체
    오늘
    어제
    • 분류 전체보기 (19)
      • Kafka (3)
      • 트랜잭션 (1)
      • 현업에 종사하면서 발견한 문제점 (3)
      • SpringBatch (1)
      • Redis (2)
      • 운영체제 (1)
      • MSA (1)
      • DevOps (4)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    redis
    Java
    SpringBoot
    트랜잭션
    vo
    spring
    SrpingBoot
    Controller
    Cache
    dto
    운영체제
    RestController
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Developer Covy
File과 Map을 동시에 Controller에서 동시에 받아야 할 경우
상단으로

티스토리툴바