문제의 원인
새로 만드는 개인 프로젝트에서 클라이언트에서 이미지를 생성해서 백엔드에 보내서 저장하기 위해 프로젝트 내 Resources 폴더를 이용하려고 했다.
Resources에 파일을 저장하게 되어버리면 당연히 프로젝트 빌드, 배포 시에 저장된 파일이 유실된다는 단점이 있었지만 구현하려던 기능이 이미지가 저장된 후에 전송 후 바로 삭제되는 작업이었기 때문에 Resources 폴더에 저장해도 상관없다 생각했다.
서버 경로에 파일 저장하기
정적 파일을 프로젝트에 업로드 하는 과정은 보통 아래와 같은 코드를 많이 쓴다.
String folder = request.getServletContext().getRealPath("/");
근데 무슨 일인지 위의 코드를 이용해 파일을 저장하고 나면
resources 폴더에 저장되지 않고 AppData\Local\Temp\tomcat-docbase~라는 임시 폴더에 저장되었다.
getRealPath()의 문제점
Spring Boot를 이용한다면 정적 파일들은 기본적으로 resources 밑에 static 폴더 내에 파일이 저장된다.(css 또는 js 파일 등)
하지만 getRealPath는 프로젝트 폴더 구조에서 resources가 아닌 webapp 폴더를 우선으로 찾고 해당 폴더가 존재하지 않으면 위와 같이 임시 폴더를 찾아간다.
그래서 resources를 찾지 않는 getRealPath 메소드는 Spring Boot에 권장되지 않는다.
하지만 getRealPath를 이용하기 위해 resources 폴더를 지우고 webapp 폴더를 기본 폴더로 이용하는 방법도 존재하기는 한다.
설정 방법은 아래와 같다.
하지만 이렇게 해버리면 문제점이 꽤 많이 생긴다.
- SSR을 이용하는 경우에 기존 html 파일에 import 시켰던 js, css 등의 경로에 webapp/을 모조리 붙여줘야한다.
- Spring Boot는 jar로 배포되는데 webapp 폴더로 인해 정상 배포 되지 않는다.(제일 큰 문제)
- 재배포 될 때마다 프로젝트 내 FileOutputStream의 모든 변경 사항(새 파일 또는 편집된 파일)이 손실된다.
- 상대 경로가 매번 달라 프로젝트의 이식이 쉽지 않다.
- getRealPath 자체가 순기능으로 활용되는 케이스가 거의 없다.
자세한 것은 아래 글 참조하면 된다.
그럼 getRealPath 대신에 상대 경로를 어떻게 구할까?
상대 경로 자체를 쓰지말라고 한다.
File uploads = new File("C:\");
최대한 절대 경로를 선호하라고 한다.
이것도 자세한 내용이 알고싶다면 아래 링크를 확인하자.
윈도우라면 최대한 C나 D처럼 드라이브 구조 안에 넣는 것이 좋고 리눅스라면 루트 경로를 잡는 것이 좋다.
이유는 보안이 좋고 재배포시 파일 유실이 안되기 때문이다.
Spring Boot 라서 생기는 문제
위의 제일 큰 문제라고 강조해놓은 부분이 사실 제일 문제다.
이유는 Spring Boot는 embedded tomcat을 이용해 jar 파일로 배포할 때 항상 정적 파일 폴더를 resources를 바라보기 때문에 webapp을 만들어서 작업하더라도 의미가 없다.
결론
뭐가 됐든 상대 경로를 쓰지 않는 것이 정답이다.
'🍃 Spring' 카테고리의 다른 글
@PostConstruct와 bean 생명주기 (0) | 2022.09.19 |
---|---|
Redirect와 Forward 차이점, 특징 및 실무 사용법 (0) | 2022.09.15 |
Spring과 Spring Boot의 예외 처리와 에러 페이지 처리 방식 (1) | 2022.07.30 |
Spring Boot application Property와 yml 작성 방법 (0) | 2021.04.30 |
@RequestParam, @RequestBody, @ModelAttribute, HttpServletRequest 사용법 (0) | 2021.03.24 |