2022. 9. 25. 16:16ㆍJAVA/Spring
- 소개
- Resource 인터페이스
- 기존 제공하는 Resource 구현
1. 소개
자바의 표준 java.net.URL 클래스와 다양한 URL 접두어에 대한 표준 핸들러는 불행하게도 모든 로우 레벨 자원들에 대한 접근을 제공하지 않습니다. 예를 들어 클래스패스에서 가져오거나 ServletContext에서 상대적인 경로로 자원에 접근하는데 사용할 수 있는 표준화된 URL 구현이 없습니다. 특수한 url 접두사(http:와 같은 접두사에 대한 기존 핸들러와 유사함)를 위해 새로운 핸들러를 등록하는 것은 가능하지만, 이 방법은 일반적으로 복잡하며 URL 인터페이스는 여전히 접근해야하는 자원의 존재를 확인하는 방법과 같은 기능이 부족합니다.
2. Resource 인터페이스
"org.springframework.core.io." 패키지에 위치한 스프링의 Resource 인터페이스는 로우 레벨 자원들에 접근을 추상화하기 위한 인터페이스입니다. Resource 인터페이스를 통하여 자원들의 종류 상관없이 동일한 방식으로 접근이 가능합니다. 다음은 Resource 인터페이스의 제공하는 메서드입니다.
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
boolean isFile();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
ReadableByteChannel readableChannel() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
위 Resource 인터페이스 정의와 같이 Resource 인터페이스는 InputStreamSource 인터페이스를 상속받고 있습니다. 다음은 InputStreamSource 인터페이스의 정의입니다.
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
Resource 인터페이스에서 중요한 메서드들은 대표적으로 다음과 같습니다.
- getInputStream() : 자원을 탐색하여 열고 자원을 읽기 위해서 InputStream 타입으로 반환합니다.
- exists() : 접근하고자 하는 자원이 존재하는지 확인합니다.
- isOpen() : 해당 자원에 접근하고 있는 스트림이 있는지 여부를 확인합니다. true라면 입력 스트림을 여러번 읽을 수 없으며, 자원 누수를 방지하기 위해 한번만 읽은 다음 닫아야 합니다. InputStreamResource를 제외한 모든 일반적인 자원 구현에 대해 false를 반환합니다.
- getDescription() : 자원을 사용할때 오류 출력에 사용되는 설명을 반환합니다. 이것은 종종 자원의 정규화된 파일 이름 또는 실제 URL이됩니다.
Resource 인터페이스의 몇몇 구현체들은 자원에 작성하기 위해서 WritableResource 인터페이스를 상속받아 구현합니다.
스프링은 자체적으로 자원이 필요할때 많은 메서드 시그니처안에 인수 타입으로 자원 추상화를 광범위하게 사용합니다. 일부 Spring API의 다른 방법들(예를들어 다양한 ApplicationContext 인터페이스 구현의 생성자)은 Context 구현에 적합한 Resource를 만들기 위해 그대로 사용하거나 간단한 형태로 사용되거나 문자열 경로의 특수한 접두사를 통해 호출자가 특정한 Resource 구현을 생성해야 함을 지정하도록 하는 문자열을 사용합니다.
반면에 Resource 인터페이스는 Spring과 함께 많이 사용되지만, 실제로는 코드가 Spring의 다른 부분을 몰라도 자원에 대한 접근을 위해 자체 코드에서 일반 유틸리티 클래스로서 사용하는 것이 매우 편리합니다. 코드를 스프링에 연결하지만 실제로는 URL을 더 잘 대체하는 유틸리티 클래스들의 작은 집합에만 연결하며, 이 목적으로 사용하는 다른 라이브러리와 동등하다고 간주할 수 있습니다.
리소스 추상화는 기능을 대체하지 않고 가능한 포장해줍니다. 예를 들어 UrlResource는 URL을 감싸고 감싼 URL을 사용하여 작업을 수행합니다.
3. 기본 제공하는 Resource 구현물들
스프링은 기본적으로 여러개의 Resource 구현물들을 포함합니다.
- UrlResource
- ClassPathResource
- FileSystemResource
- PathResource
- ServletContextResource
- InputStreamResource
- ByteArrayResource
Resource 인터페이스 공식문서에 모든 구현 클래스들을 확인할 수 있습니다.
3.1 UrlResource
UrlResource 클래스는 java.net.URL 클래스를 래핑한 클래스입니다. UrlResource 클래스는 파일, HTTPS, FTP 등을 대상으로 접근하는데 사용됩니다. 모든 URL들은 표준화된 문자열 접두어를 가지고 있습니다. 파일 시스템 경로에 접근하기 위해서는 "file:"로 시작하고, HTTP 프로토콜을 통해 자원에 접근하기 위해서는 "https:"로 시작합니다. FTP를 통해서 접근하기 위해서는 "ftp:"로 시작합니다.
UrlResource 인스턴스는 UrlResource 생성자를 사용하여 생성되지만 종종 URL 경로와 같이 API 메서드를 호출할때 묵시적으로 생성될 수 있습니다. 후자의 경우에 JavaBeans PropertyEditor 같은 경우 궁극적으로 Resource의 타입에 따라서 생성하는 것을 결정합니다. 만약 경로 문자열이 "classpath:"와 같은 잘 알려진 접두어가 포함된다면, 접두어에 따른 Resource 인스턴스가 생성됩니다. 예를 들어 접두어가 "file:"이라면 FileSystemResource 인스턴스로 생성될 것입니다. 만약 접두어를 인식하지 못하면 표준 URL 문자열이라고 추측하여 UrlResource 인스턴스가 생성됩니다.
- UrlResource 클래스는 java.net.URL 클래스의 래퍼 클래스
- UrlResource 클래스를 이용하는 접두어는 FILE, HTTPS, FTP 등이 존재함
- URL 경로와 같이 API 메서드 호출시 묵시적으로 UrlResource 인스턴스 생성됨
3.2 ClassPathResource
ClassPathResource 클래스는 클래스패스로부터 얻어와야하는 자원을 나타내는 클래스입니다. ClassPathResource는 쓰레드 컨텍스트 클래스 로더를 사용하거나 자원들을 불러오기 위하여 주어진 클래스를 사용합니다.
만약 클래스 경로 자원이 파일 시스템에는 상주하지만 jar 파일안에 있는 자원이 아닌 경우, Resource 구현은 "java.io.File" 클래스로 해결을 지원합니다. 이를 해결하기 위해 다양한 Resource 구현은 항상 java.net.URL로 해결을 지원합니다.
ClassPathResource 클래스는 ClassPathResource 생성자를 사용하여 명시적으로 생성될 수 있지만 경로를 의미하는 문자열 과 같이 API 메서드를 호출하는 경우 묵시적으로 생성되는 경우가 있습니다. 후자의 경우 JavaBeans PropertyEditor는 "classpath:" 접두어를 인식하여 ClassPathResource 인스턴스를 생성합니다.
3.3 FileSystemResource
FileSystemResource 클래스는 "java.io.File" 클래스를 다루기 위한 클래스입니다. 또한 이 클래스는 "java.nio.file.Files" API를 통하여 모든 연산들을 수행하는 스프링의 표준 문자열 기반 경로 변환을 적용하는 "java.nio.file.Path" 인터페이스를 다룹니다. PathResource를 지원하는 대신에 순수한 "java.nio.path.Path"를 지원합니다.
3.4 PathResource
PathResource 클래스는 Path API를 통해 모든 연산들과 변환들을 수행하는 "java.nio.file.Path"를 다루는 것을 구현한 클래스입니다. PathResource 클래스는 파일 및 URL을 지원하고 WritableResource 인터페이스를 구현하기 때문에 자원에 작성도 가능합니다. PathResource 클래스는 상대 경로로 생성하는 FileSystemResource 크랠스를 대체하는 순수한 java.nio.path.Path 기반의 클래스입니다.
3.5 ServletContextResource
ServletContextResource 클래스는 웹 애플리케이션의 루트 디렉토리 내부에서 상대적인 경로를 해석하는 ServletContext 자원들을 위해서 구현된 클래스입니다. ServletContextResource는 스트림 접근과 URL 접근을 지원하지만 파일 시스템에 물리적으로 위치한 자원과 웹 애플리케이션 아카이브가 확장될때의 접근은 java.io.File 접근을 허용합니다. ServletContext가 파일 시스템에서 확장되었는지 아니면 JAR에서 직접 접근되는지, 데이터베이스와 같은 다른 곳에서 접근되는지의 여부는 실제로 서블릿 컨테이너에 달려 있습니다.
3.6 InputStreamResource
InputStreamResource는 InputStream 클래스의 래퍼 클래스입니다. InputStreamResource는 특정 리소스 구현이 적용되지 않는 경우에만 사용해야 합니다. 특히 ByteArrayResource나 파일 기반의 Resource 구현체가 해당됩니다.
다른 Resource 구현체와는 다르게 InputStreamResource는 이미 열려있는 자원에 대한 설명자(descriptor)입니다. 따라서 isOpen()을 호출하면 true를 반환합니다.
3.7 ByteArrayResource
ByteArrayResource 클래스는 바이트 배열을 래핑하는 클래스입니다. 주어진 바이트 배열에서 ByteArrayInputStream을 생성합니다.
단일 사용 InputStreamResource에 의존할 필요 없이 주어진 바이트 배열에서 컨텐츠를 불러오는데 유용합니다.
References
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources
'JAVA > Spring' 카테고리의 다른 글
[Spring] ResourcePatternResolver 인터페이스 (0) | 2022.10.03 |
---|---|
[Spring] ResourceLoader 인터페이스 (0) | 2022.09.30 |
[Spring][IoC] ApplicationEventPublisher (0) | 2022.09.23 |
[Springboot] 내장 웹 서버(Embedded Web Servers) #1 (0) | 2022.09.23 |
[Spring][IoC] MessageSource (0) | 2022.09.13 |