파일 업로드를 구현하다 보면 MultipartFile의 transferTo() 메서드가 파라미터로 File도 받고 Path도 받는 걸 볼 수 있다. "결국 저장하는 건 똑같은데 왜 굳이 두 개로 나눠놨지?"라는 궁금증이 생겨, 실무에서 주로 쓰이는 방식과 함께 정리해보았다.
결론부터 말하면, 자바의 구형 방식(IO)과 신형 방식(NIO)을 모두 지원하기 위한 스프링의 배려다.
File 방식가장 오래된 방식으로, 저장할 파일의 '실체'를 객체로 직접 만들어 전달한다.
file.transferTo(new File(fullPath));
경로 유효성 검사 등을 File 객체 생성 시점에 미리 처리할 수 있지만, 코드가 다소 투박하다.
Path 방식 (권장)Java 7부터 도입된 NIO(New IO)를 활용한다. 파일 객체 대신 '경로' 정보만 전달한다.
file.transferTo(Paths.get(fullPath));
new File()을 직접 할 필요가 없다. 내부적으로 최신 자바 API를 사용하여 더 안전하고 효율적으로 파일을 저장한다.
공부하다 보니 실무에서는 서버 로컬 디스크에 저장하는 위 방식들보다 AWS S3 같은 외부 스토리지를 훨씬 많이 쓴다는 걸 알게 되었다. 이때는 transferTo를 아예 쓰지 않는 '반전'이 있다.
서버 디스크에 임시 저장하지 않고, 입력 스트림(InputStream)을 열어 외부로 바로 쏴주는 방식이다.
public void uploadS3(MultipartFile file) throws IOException {
// transferTo 대신 getInputStream()을 사용
amazonS3.putObject("bucket-name", "filename", file.getInputStream(), metadata);
}
서버의 디스크 자원을 소모하지 않고 곧바로 클라우드에 저장할 수 있어 대규모 서비스에 유리하다.
결국 transferTo가 두 가지인 이유는 "그릇을 직접 빚어서 줄래(File), 아니면 놓을 자리만 알려줄래(Path)?"의 차이였다. 최근에는 Path 방식이 표준이지만, 인프라 환경에 따라 아예 스트림을 직접 다루는 방식이 더 중요할 수 있다는 점이 흥미로웠다.