Spring Boot에서 ClassPathResource나 ResourceUtil의 getFile() 메서드를 사용해 정적 파일을 읽어올 때, 로컬환경에서는 문제없이 불려 오던 파일이 배포환경의 jar나 war파일 내에서는 불려 오지 않고 FileNotFoundException이 발생했다.
◆ 원인
IDE(IntelliJ, Eclipse)에서 Spring Boot 애플리케이션을 실행하면 정적자원은 「file:// 」 경로를 통해 로드되고 File 객체를 사용해 파일을 읽어오는 게 가능하기 때문에 로컬환경에서는 문제없이 파일이 불려 왔지만
Spring Boot 애플리케이션을 war나 jar파일로 패키징 한 뒤에 실행하면 정적자원은 war, jar파일 내부에 포함되게 된다.
이 경우, 정적자원(HTML, CSS, JavaScript 파일 등) 은 더 이상 파일 시스템의 경로에 있지 않고 패키지 내부에 포함되어 있기 때문에 「file:// 」 경로로 접근하는 것이 불가능해 지면서 배포환경에서 File 객체를 사용하려고 하면 FileNotFoundException이 발생했던 것이다.
◆ war, jar내의 정적파일 경로
우선 war나 jar로 패키징 된 파일의 압축을 풀어 실제 정적자원의 경로를 확인한 뒤에 진행하길 권장한다.
확인해 보니 로컬환경에서는 /src/main/webapp/static/file/template.xlsx 경로였지만
war파일 내에서는 /static/file/template.xlsx 경로에 파일이 위치해 있어 로컬환경과 차이가 있었다.
아래는 패키징된 war나 jar파일 내에서 정적자원을 찾는 예시이다.
◆ InputStream을 이용하여 파일 읽어오기 (ClassPathResource)
로컬환경: X
배포환경: O
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
String resourcePath = "/static/file/template.xlsx";
ClassPathResource resource = new ClassPathResource(resourcePath);
InputStream fis = resource.getInputStream();
XSSFWorkbook workbook = new XSSFWorkbook(fis);
◆ InputStream을 이용하여 파일 읽어오기 (ResourceLoader)
로컬환경: O
배포환경: O
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ResourceLoader;
@Autowired
private ResourceLoader resourceLoader;
String resourcePath = "/static/file/template.xlsx";
Resource resource = resourceLoader.getResource(resourcePath);
InputStream fis =resource.getInputStream();
XSSFWorkbook workbook = new XSSFWorkbook(fis);
◆ ServletContext의 getResourceAsStream()을 이용하여 파일 읽어오기
로컬환경: O
배포환경: O
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.ServletContext;
@Autowired
private ServletContext servletContext;
String resourcePath = "/static/file/template.xlsx";
InputStream fis = servletContext.getResourceAsStream(resourcePath);
XSSFWorkbook workbook = new XSSFWorkbook(fis);
글 내용 중 잘못된 부분이 있거나, 첨부하실 내용이 있으시면 댓글로 남겨주세요. 공부하는데 많은 도움이 됩니다.
-- 기억의 유효기간은 생각보다 짧다. --
'▹ JAVA 기반 프레임워크 > 스프링부트 (Spring Boot)' 카테고리의 다른 글
스프링 부트(Spring Boot)의 세션 만료 시간 (session timeout) 설정 방법 (1) | 2025.01.10 |
---|---|
[Spring] MultipartFile 파일 업로드 최대크기 제한 조정 (0) | 2024.10.02 |
[Spring] MultipartFile 비어있는 파일 확인 - isEmpty() (0) | 2024.07.31 |
스프링 부트(Spring Boot)에서 JSP 사용하기 (1) | 2023.12.27 |
[Spring] ClassPathResource 경로 (0) | 2023.09.15 |