관리 메뉴

피터의 개발이야기

[Spring] War 배포와 Jar 배포 시 resource 참조 문제 본문

Programming/Spring

[Spring] War 배포와 Jar 배포 시 resource 참조 문제

기록하는 백앤드개발자 2020. 12. 14. 15:29
반응형

엑셀다운로드을 하고 있었다. JXLS로 만들면서 템플릿 Excel파일의 경로를 지정하였다.

하지만 로컬에서 실행시키자 에러가 발생하였다.
얼마전 SpringBoot 배포를 War에서 Jar로 변경 하였기 때문이었다.

 

결론적으로 Jar와 War가 Resource를 참조하는 방식이 달랐다.

Jar로 배포된 개발계와 운영계에는 문제가 없었고,

local에서는 classpath경로로는 리소스를 참조할 수 없었다.

 

우선 알아야할 개념은 Path와 Classpath의 차이다.

path는 javac와 연관이 있다. 자바환경에서 컴파일 할 때 필요한 것이다.

javac가 컴파일하기 위한 모든 라이브러리를 참조하기 위해

윈도우에서는 환경변수로 java홈의 라이브러리 경로를 지정해 준다.

javac는 라이브러리 경로에 따라 lib파일에 직접 접근하여 컴파일을 수행한다.

 

classpath는 JVM과 관련이 있다.

JVM은 class 파일을 바이트로 읽어 들여서 메모리에 로딩을 해야한다.

resource안의 파일도 컴파일 단계를 거쳐 파일시스템이 아닌 메모리 안에 존재하게 된다.

classpath는 자바에서 컴파일 하기 위해, *.class가 모여있는 곳을 가리키는 곳
다시말해 라이브러리(class 파일)을 자바에게 알려주는 역할이다.

 

jar와 web의 파일들의 시스템 상태 차이

jar는 JVM에 의해 class파일과 resource들이 바이트로 읽어들여 메모리에 로딩된 상태이다.

war는 tomcat이 가동되면서 압축이 해제되어 resouce는 WEB-INF 폴더에 저장이 되어 있다.

 

테스트 차원에서 같은 SpringBoot Application을 bootJar와 war로 빌드 한 후 압축을 해제 하였다.

 

boorJar로 빌드

jar 파일 압축해제

 

War로 빌드

 

war파일 압축해제

 

결론적으로

jar는 classpath에 존재하는 메모리상의 리소스를 참조하는 것이고,

war는 파일 시스템 상에서 존재하기 때문에, 파일수정 시에 운영에도 반영이 되는 것이다.

 

war로 배포시 엑셀 참조 방법

// tempPath는 템플릿 엑셀파일이 들어가는 경로를 넣어 준다.
String tempPath = request.getSession().getServletContext().getRealPath("/WEB-INF/excel");

Workbook workbook;
InputStream is = new BufferedInputStream(new FileInputStream(tempPath + "/" + templateFile));

 

 

jar로 배포 시 수정된 참조 방법

local인 경우 'classpath:'를 제거한다. 

@Value("${spring.profiles.active}")
private String activeProfile;

// ~~ 중간 생략 ~~

  StringBuilder stringBuilder = new StringBuilder();
  stringBuilder.append("local".equals(activeProfile)?"static":"classpath:static");
  stringBuilder.append(File.separator);
  stringBuilder.append("excel");
  stringBuilder.append(File.separator);
  stringBuilder.append(templateFile);
  String filePath = stringBuilder.toString();
  
  ClassPathResource classPathResource = new ClassPathResource(filePath);
  if (classPathResource.exists() == false) {
  	log.error("Invalid filePath : {}", filePath);
  	throw new IllegalArgumentException();
  }
  log.info("file path exists = {}", classPathResource.exists());
  
  InputStream is = new BufferedInputStream(classPathResource.getInputStream());

 

블러그를 정리하면서 공부가 많이 되어서 좋다.

근데 지금 새벽4시가 되었다.

궁금해서 자꾸 찾아보면서 이해가 되어야지 잠이 올 것 같아서다.

 

내일을 위해 잠을 자야겠다.
다음에는 Spring에서 클래스 경로의 resource를 참조하는 방법에 대해서 알아봐야겠다.

반응형

'Programming > Spring' 카테고리의 다른 글

[Spring] PDF을 이미지 파일로 변환하기  (0) 2020.12.23
[TDD] assertThat 사용법  (0) 2020.12.19
Spring Profiles  (0) 2020.12.12
[Spring] Jackson Annotations  (0) 2020.12.10
[SPRING BOOT] Retrofit vs Feign for Server Side  (0) 2020.12.08
Comments