leelee.log

[Spring] Resource를 가져오는 방법 본문

개발/Backend

[Spring] Resource를 가져오는 방법

leeleelee3264 2020. 5. 24. 17:13

spring framework

 

 웹 페이지를 만들다보면 Resource 를 사용할 일이 정말 많아진다. 여기서 주로 사용하는 Resource는 HTML, Javascript, Css, png 등이 있다. 이 Resource를 또 동적인 리소스 (dynamic resource)와 정적인 리소스 (static Resource)로 구분을 할 수 있는데 내가 이해한 바로는 동적인 리소스는 runtime에 변화가 있는 리소스이고, 정적인 리소스는 변화가 없는 리소스이다.

 예를 들어 이미지와 javascript, css와 같은 파일들은 서버에 저장되어 있을 때도, 클라이언트에게 줄 때도 변화가 없다. 그래서 변화가 없는 정적인 리소스가 된다. 이제 HTML을 한 번 생각해보자. HTML은 틀이고, HTML을 채우는 알맹이는 db에서 가져온 정보이다. '고양이'와 '강아지'의 회원 정보 조회 페이지가 있다고 해보면 회원정보 페이지의 디자인이나 서식 등은 동일한데 (틀의 역할을 하는 HTML은 동일함) 회원인 '강아지' 와 '고양이'는 다른 정보를 가지고 있을 수 밖에 없기 때문에 동일한 디자인의 페이지에 내용의 차이가 생긴다. 이렇게 서버에 저장되어 있는 형태와 클라이언트가 받았을 때 형태가 달라지는 리소스를 동적 리소스라고 한다.

 참고로 변화가 없는 정적 리소스의 경우 웹서버에 많이 저장을 해둔다. 트래픽 분배를 해줄 뿐 실질적으로 역할이 많이 없는 웹서버에 저장을 해두면 성능향상에 도움이 된다고 한다. 그리고 동적인 리소스는 웹서버 위에 떠있는 앱서버에 저장이 된다. 서버에서 프로세싱을 해서 클라이언트에게 줘야하니까.

 


 오늘의 주제는 spring에서 어떻게  위에서 설명한 리소스를 가져오는가 이다. 처음에 spring 프로젝트를 만들면 하나의 디렉터리 트리가 만들어진다. 최상위 디렉터리인 프로젝트 디렉터리 안에 많은 디렉터리 파일들이 만들어지는데 자바 파일이 저장되는 디렉터리로 알고 있는 src 디렉터리를 열면 java 디렉터리와 함께 resoources 디렉터리가 하나 더 생겼다. spring  에서 사용되는 html, css, 이미지 등의 리소스들은 resources 디렉터리 안에 저장이 된다.

디렉터리 트리

 gradle, build.gradle, gradlew, gradlew.bat, settign.gradle 등 gradle을 사용해 프로젝트를 구성하니 gradle 파일이 많이 생겼는데 이들이 어떤 역할을 하는 파일들인지 설명을 잘 해둔 포스트의 링크를 걸어두겠다.

medium.com/@goinhacker/%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94-1-%EB%B9%8C%EB%93%9C-%EC%9E%90%EB%8F%99%ED%99%94-by-gradle-7630c0993d09

 

운영 자동화#1 — 빌드 자동화 by Gradle

개발자가 비지니스 로직 구현에 집중하기 위한 운영 자동화의 첫번째 단계로 Gradle을 활용한 빌드 자동화에 대해서 설명한다. 개발에 대한 아주 기본적인 내용과 직접 Gradle 플러그인을 만드는 ��

medium.com

 

 java 파일들이 저장되는 디렉터리로 알고 있는 src 디렉터리를 열어보면 java 디렉터리와 resources 디렉터리가 생겼다! 신기한 점은 자바 코드에서 리소스를 불러올 때 경로대로 하면 '../resources/하위디렉터리/해당파일' 같은 상대경로나 't-story/src/main/resources/하위디렉터리/해당파일' 같은 절대 경로가 나와야하는데 실제로는 그냥 '하위디렉터리/해당파일' 만 쓰면 해당 리소스를 불러올 수 있다. 이처럼 리소스와 연관된 동작은 spring의 org.springframework.core.io.Resource 패키지를 통해서 이루어진다. 이 패키지는 java에서 제공하는 java.net.URL 을 이용해서 만들었다고 한다. 이게 있기 때문에 우리는 방금 말한 것 처럼 리소스를 가져오기 위해 복잡한 경로를 쓰지 않아도 된다. 

 

 Controller에서 리턴할 html 템플릿 경로를 쓸 때 말고도 코드 상에서 프로젝트 안의 resource 파일을 불러와야하는 일이 있는데 spring에서 resource를 읽는 방법은

1. URLResource : URL을 기준으로

2. ClasspathResource : classpath를 기준으로

3. FileSystemResource : file system을 기준으로

3. ServletContextResource : 웹 어플리케이션 루트를 기준으로

가 있다. ApplicationContext에 따라서 리소스 읽는 방법이 정해지는데 스프링으로 웹서비스를 만들때는 webapplicationcontext 를 사용하기 때문에 ServletContextResource를 사용한다. 가장 대표적인 예로 @Autowired로 DI를 할 때 ServletContextResource는 AnnotaionServletWebServerApplicationContext를 사용해서 빈을 주입한다. 그런데 강의를 들어보니 ApplicationContext와 상관없이 getResource로 리소스를 읽어올 때는 접두어를 꼭 사용자는걸 권장한다. 접두어를 사용하면 ApplicationContext가 어떻게 되어도 접두어를 사용한 방식으로 리소스를 읽어들여야 한다.

 예를 들어 'classpath:' 라는 접두어를 사용하면 classpathResource 방식으로 읽어오고 'file:///' 라는 접두어를 사용하면 filesystemresource 방식으로 읽어온다. 이렇게 해둬야 그냥 getResource 를 쓸때 보다 더 명시적이라 이해가 잘 간다고 한다.

 *참고로  ServletContextResource는 contextpath 접두사를 사용하는데 contextpath 루트가 따로 정해져있지 않아서 어플리케이션의 root 부터 읽는다고 한다. classpath의 경우 루트가  resources 디렉터리로 설정이 되어있다. (그럼 controller에서 html 리턴해줄 때 쓰는 경로도 classpath로 되어있나보다. resources 를 쓰지 않고도 리소스를 찾아오니까.) spring의  템플릿 엔진인 타임리프로 classpath로 읽어온다고 한다. 그래서 리소스 파일 가져올려면 classpath 방식으로 가져오는걸 적극 권하고 있다.*

 


 오늘의 핵심 내용은 리소스를 가져오는 방법이었다! HTML, css, js 등의 리소스 파일을 가져오는 방식이지 JAVA 파일과는 상관이 없다는 걸 헷갈리지 말자.