[Spring Framework - Core] 2. Resource

mrcocoball·2023년 8월 25일

Spring Framework

목록 보기
3/20
post-thumbnail

해당 포스트는 Spring.io의 공식 문서를 포함한 레퍼런스와 코드를 통해 Spring Framework의 구조 / 기술에 대해 확인해보고자 하는 포스트입니다.

1. Resource

개요

스프링 프레임워크의 핵심 기술 중 하나인 Resource 인터페이스는 하위 수준 리소스에 대한 액세스를 추상화하기 위한 인터페이스입니다.

공식 문서에 따르면 자바의 표준 URL 클래스 및 표준 핸들러는 하위 수준 리소스에 대한 모든 액세스를 다루기에 충분하지 않다고 하는데요. 이러한 문제점을 보완하기 위해 만들어진 인터페이스라고 합니다.

Resource 인터페이스의 장점

스프링 프레임워크는 Resource 인터페이스를 활용한 추상화를 광범위하게 사용하는데, 리소스가 필요한 수많은 메서드들의 인자로 많이 사용합니다. 또한 스프링 프레임워크가 아니더라도 일반 유틸리티 클래스로 사용하기에도 매우 편리하다고 합니다.

2. 내장 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 인터페이스의 구조는 위와 같으며 공식 문서에서 언급하는 가장 중요한 메서드 중 일부는 다음과 같습니다.

  • getInputStream()
    리소스를 찾아 열고 리소스를 읽기 위한 InputStream을 반환

  • exists()
    리소스가 실제로 물리적 형태로 존재하는지 여부를 반환

  • getDescription()
    리소스 작업 시 오류 출력에 사용되는 리소스에 대한 설명을 반환
    정규화된 파일 이름이거나 리소스의 실제 URL인 경우가 많음

  • isOpen()
    리소스가 개방형 스트림의 핸들임을 나타내는지 여부를 반환
    InputStreamResource를 제외한 일반적인 리소스 구현에 대해서는 모두 false
    true일 경우 여러 번 읽을 수 없으며 한번만 읽은 후 닫아야 함

상기 메서드를 제외한 다른 메서드로는 리소스를 나타내는 실제 URL이나 File에 대한 객체를 얻을 수 있습니다.

Resource 인터페이스 종류

대표적인 Resource 인터페이스의 종류는 다음과 같습니다.

  • UrlResource
    java.net.URL를 래핑하고 파일, HTTPS 대상, FTP 대상 등 일반적으로 URL로 액세스할 수 있는 모든 개체에 액세스할 때 사용 (file:, https:, ftp:)

  • ClassPathResource
    클래스 경로에서 얻어야 하는 리소스를 구현.
    보통 스레드 컨텍스트 클래스 로더, 지정된 클래스 로더 또는 리소스 로드를 위해 지정한 클래스를 사용

  • FileSystemResource
    java.io.File, java.nio.file.Path 핸들 지원, 스프링의 표준 문자열 기반 경로 변환을 적용.
    파일 및 URL로 확인하는 것을 구현
    . 단, 모든 작업은 java.nio.file.Files API를 통해 처리

  • PathResource
    순수한 java.nio.path.Path 핸들 지원을 위한 인터페이스.
    java.nio.path.Path API를 통해 모든 작업과 변환을 수행

  • ServletContextResource
    ServletContext에 대한 리소스 구현이며 웹 어플리케이션의 루트 디렉토리 내의 상대 경로를 해석
    단, 웹 어플리케이션 아카이브가 확장되고 리소스가 물리적으로 파일 시스템에 있는 경우에만 java.io.File 액세스를 허용.
    파일 시스템에서 확장되거나 jar 파일 또는 데이터베이스 등과 같이 다른 곳에서 직접 액세스가 가능한지 여부는 서블릿 컨테이너에 따라 다름

  • InputStreamResource
    주어진 InputStream에 대한 구현이며 특정 리소스 구현을 적용할 수 없는 경우에만 사용해야 함
    위에서 소개했던 대로 isOpen() 이 true이기 때문에 여러번 읽을 수 없으므로 스트림을 여러 번 읽어야 하거나 리소스 설명자를 어딘가에 저장해야 하는 경우엔 사용하면 안됨
    공식 문서에서는 이 경우 가능하다면 ByteArrayResource나 파일 기반 리소스 구현을 권장

  • ByteArrayResource
    주어진 바이트 행렬에 대한 처리를 지원하며 행렬에 대한 ByteArrayInputStream 를 생성

3. Resource 관련 부가 기능 인터페이스

ResourceLoader

Resource 인스턴스를 반환할 수 있는(읽을 수 있는) 객체로 구현되는 인터페이스입니다.

public interface ResourceLoader {

	Resource getResource(String location);

	ClassLoader getClassLoader();
}

모든 어플리케이션 컨텍스트는 해당 인터페이스를 구현하므로 Resource 인스턴스를 얻을 수 있습니다.

  • ClassPathXmlApplicationContext : ClassPathResource
  • FileSystemXmlApplicationContext : FileSystemResource
  • WebApplicationContext : ServletContextResource ...

ResourcePatternResolver

ResourceLoader 인터페이스의 확장으로, 위치 패턴(Ant 스타일 경로 패턴 등)을 객체로 해결하기 위한 전략을 정의합니다.

public interface ResourcePatternResolver extends ResourceLoader {

	String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

	Resource[] getResources(String locationPattern) throws IOException;
}

ResourceLoaderAware

ResourceLoader 참조가 제공될 것으로 예상되는 구성 요소를 식별하는 특수한 콜백 인터페이스입니다.

public interface ResourceLoaderAware {

	void setResourceLoader(ResourceLoader resourceLoader);
}

4. 정리

Resource 인터페이스는 하위 수준 리소스에 대한 액세스를 추상하기 위한 인터페이스입니다.
Resource 인터페이스를 통해 유연하게 리소스를 다루며 테스트, 배포 환경에서도 일관성을 유지할 수 있습니다.

Resource 인터페이스는 스프링 프레임워크 내부에서 리소스가 필요한 모든 메서드들의 인자로 활용되는 등 광범위하게 사용되고 있으며, 스프링 프레임워크가 아니더라도 유틸리티 클래스로서 사용하기도 편하다고 합니다.

다양한 내장 인터페이스들은 여러 가지 리소스 타입을 구현하고 있으며 그 밖에도 다양한 부가 기능 인터페이스를 가지고 있는데 그 중에서 Resource 인스턴스를 반환하는(리소스를 읽어들이는) ResourceLoader 인터페이스를 모든 어플리케이션 컨텍스트들이 구현하고 있어 어플리케이션 컨텍스트를 사용하여 Resource 인스턴스를 읽어들일 수 있습니다.

Appendix. 레퍼런스

https://docs.spring.io/spring-framework/reference/core/resources.html

profile
Backend Developer

0개의 댓글