스프링 리소스는 다양한 형태의 자원을 추상화한 개념이에요. 자원의 형태로는 파일, 클래스패스 기준의 파일, 웹 리소스 등이 있고 스프링 리소스는 다양한 자원에 통일된 방식으로 접근하고 사용할 수 있도록 Resource라는 인터페이스를 제공해요.
리소스는 리소스 경로의 접두어를 보고 거기에 적합한 구현체를 제공해요. 접두어와 접두어에 따른 구현체는 다음과 같습니다.
- 기본 ServletContextResource: 웹 애플리케이션의 서블릿 컨텍스트에 있는 리소스를 나타냅니다.
- (classpath:/) ClassPathResource: 클래스패스에 있는 리소스를 나타냅니다.
- (file:/) FileSystemResource: 파일 시스템에 있는 리소스를 나타냅니다.
- (http:/, https:/, ftp:/, jar:/) UrlResource: URL을 통해 접근할 수 있는 리소스를 나타냅니다.
이 외에도 경로(문자열)가 아닌 다른 타입의 파라미터를 받는 InputStreamResource와 ByteArrayResource 구현체도 있어요.
리소스를 사용하는 방식은 ResourceLoader 빈을 사용하는 방식과 @Value 어노테이션과 SpEL (Spring Expression Language)을 활용하는 방식이 있어요. (SpEL은 추후에 더 자세히 설명할게요)
리소스 로더를 사용하는 방식은 빈으로 주입 받는 방법과 new DefaultResourceLoader()를 사용한 싱글톤 패턴을 이용하는 방식이 있어요. 이번에는 빈으로 주입받는 방식만 살펴볼게요.
@Component
@RequiredArgsConstructor
public class MyService {
private final ResourceLoader resourceLoader;
public void processFile(String location) throws IOException {
Resource resource = resourceLoader.getResource(location);
InputStream inputStream = resource.getInputStream();
...
}
}
생성자 주입을 통해 resourceLoader 빈을 주입 받아 리소스 파일을 읽는 소스코드에요. location의 경로 접두어에 따라 적합한 리소스 구현체를 알아서 선택하기 때문에 여러 형태의 리소스들을 읽어올 수 있어요.
리소스 로더를 통한 방식도 많이 사용하지만 애플리케이션 배포 시에 이미 가지고 있는 리소스인 경우 @Value을 더 많이 사용하고 선호해요.
@Component
public class MyService {
@Value("classpath:my-file.txt") // 클래스패스 리소스
private Resource myFile;
@Value("file:/path/to/my-file.txt") // 파일 시스템 리소스
private Resource myAnotherFile;
@Value("https://example.com/my-file.txt") // 웹 리소스
private Resource myWebFile;
public void processFile() throws IOException {
InputStream inputStream = myFile.getInputStream();
...
}
}
리소스 로더를 사용한 방식 대비 @Value 어노테이션을 사용하면 코드가 많이 간결해지는 장점이 있어요. (@Value어노테이션은 리소스외에도 SpEL (Spring Expression Language)을 통해 다양하게 사용할 수 있어요)