1. 프론트엔드 - 파일 및 메타데이터 업로드
프론트엔드에서 파일과 추가 정보(메타데이터)를 함께 업로드하려면 FormData를 활용해야 한다.
HTML + JavaScript 코드 (Vanilla JS + Axios)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>파일 및 데이터 업로드</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<h2>파일 및 메타데이터 업로드 테스트</h2>
<input type="file" id="fileInput" /><br><br>
<input type="text" id="fileName" placeholder="파일 이름 입력" /><br><br>
<input type="text" id="fileDescription" placeholder="파일 설명 입력" /><br><br>
<button onclick="uploadFile()">파일 업로드</button>
<p id="result"></p>
<script>
function uploadFile() {
const fileInput = document.getElementById("fileInput");
const file = fileInput.files[0];
if (!file) {
alert("파일을 선택하세요.");
return;
}
const fileName = document.getElementById("fileName").value;
const fileDescription = document.getElementById("fileDescription").value;
const formData = new FormData();
formData.append("file", file);
formData.append("fileName", fileName);
formData.append("fileDescription", fileDescription);
axios.post("http://localhost:8080/rest/v1/file/upload", formData, {
headers: { "Content-Type": "multipart/form-data" }
})
.then(response => {
document.getElementById("result").innerText = "업로드 성공: " + response.data;
})
.catch(error => {
document.getElementById("result").innerText = "업로드 실패: " + error.response.data;
});
}
</script>
</body>
</html>
2. Spring Boot 파일 업로드 컨트롤러
Spring Boot에서 파일과 추가 데이터를 받는 방법은 크게 두 가지가 있다.
3. @ModelAttribute를 사용한 DTO 방식
이 방법은 DTO를 활용해 한 번에 데이터를 받을 수 있는 방식이다.
FileDto.java (DTO 객체)
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
@Data
public class FileDto {
private MultipartFile file;
private String fileName;
private String fileDescription;
}
FileController.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.IOException;
@Slf4j
@RestController
@RequestMapping("/rest/v1/file")
public class FileController {
private static final String UPLOAD_DIR = "C:/uploads/";
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@ModelAttribute FileDto fileDto) {
if (fileDto.getFile().isEmpty()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("파일이 없습니다.");
}
try {
String filePath = UPLOAD_DIR + fileDto.getFile().getOriginalFilename();
fileDto.getFile().transferTo(new File(filePath));
log.info("파일 업로드 성공: {}", filePath);
log.info("파일 이름: {}", fileDto.getFileName());
log.info("파일 설명: {}", fileDto.getFileDescription());
return ResponseEntity.ok("파일 업로드 성공: " + fileDto.getFile().getOriginalFilename());
} catch (IOException e) {
log.error("파일 저장 실패", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("파일 업로드 실패");
}
}
}
4. @RequestParam을 사용한 방식
이 방법은 파일과 데이터를 개별적으로 받는 방식이다.
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam("fileName") String fileName,
@RequestParam("fileDescription") String fileDescription) {
if (file.isEmpty()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("파일이 없습니다.");
}
try {
String filePath = "C:/uploads/" + file.getOriginalFilename();
file.transferTo(new File(filePath));
log.info("파일 업로드 성공: {}", filePath);
log.info("파일 이름: {}", fileName);
log.info("파일 설명: {}", fileDescription);
return ResponseEntity.ok("파일 업로드 성공: " + file.getOriginalFilename());
} catch (IOException e) {
log.error("파일 저장 실패", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("파일 업로드 실패");
}
}
5. @ModelAttribute vs @RequestParam 비교
방식 | 장점 | 단점 |
@RequestParam | 간단한 구현이 가능 | 필드가 많아지면 관리가 어려움 |
@ModelAttribute | DTO를 활용해 깔끔한 코드 유지 가능 | multipart/form-data 형식이 아닐 경우 오류 발생 |
6. 정리
- Vue에서 FormData를 사용해 파일과 추가 정보를 함께 전송
- Spring Boot에서는 @RequestParam 또는 @ModelAttribute를 사용해 처리 가능
- DTO를 활용하면 코드 유지보수가 쉬워짐
반응형