티스토리 뷰

반응형

보통 많은 운영 환경에서 Web Server(정적인 파일 서비스)와 WAS 을 연동해서 서비스하는 경우가 많습니다. Tomcat 으로 서비스되고 있는 환경에서조차 내부에 경량 Apache HTTPd 가 내장되어 있기 때문에 별도의 Web Server 없이도 괜찮은 속도로 정적인 파일을 서비스 할 수 있지만, 몇 가지 이유(납득되는 것도 있고, 그렇지 않은 것들도 있지만) 때문에 여전히 기존 방식을 이용하는 곳도 많습니다.


개인적으로 생각할 때 가장 납득이 가는 경우는 "파일 업로드" 기능 때문입니다. 업로드된 파일을 다시 사용자가 내려받아야 할 경우라면 파일 원본 그 자체를 잘 보관하고 있다가 다른 영향 없이 다시 다운로드가 가능해야 합니다. 물론 파일 다운로드 시 권한 체크를 정교하게 한다거나 다운로드 횟수를 제한한다는 등의 제약이 붙으면 여전히 WAS 에서 이를 관리해야 하지만, 일반적인 파일 업로드 시 무조건 다운로드 하면 된다는 정책이 있다면 굳이 WAS 에서 이를 처리할 필요는 없습니다.

또한, 업로드된 파일을 Java 의 배포 디렉토리 혹은 classpath 하위에 저장할 경우 새로운 배포 시 기존 파일이 모두 지워질 수도 있습니다. 배포 전에 미리 업로드 디렉토리를 이동 시킨 뒤 배포 후에 다시 원상복구 하는 것은 위험천만한 생각입니다.

그래서 보통 OS 의 특정 경로에 업로드되는 파일을 저장해두고 Web Server 에서 그 디렉토리를 설정해서 파일을 URL 로 제공할 수 있도록 설정하곤 합니다.


하지만, 최근 들어 Spring Boot 로 외장 WAS 가 아닌 내장 WAS 로 서비스를 하면서 Web Server 조차 구성하지 않는 경우가 많이 생기고 있습니다. 특히 microservice 가 각광받고 있어서 더욱 두드러집니다. 이 때 Spring Boot 에서 main/resources/static/ 디렉토리에 파일을 올려서 사용하는 방법 외에 어떠한 식으로 처리하는지 몰라서 엉뚱한 방법으로 코딩하는 분들이 많습니다.



Spring Boot 에서는 WebMvcConfigurer#addResourceHandlers 을 이용해 다음과 같이 외부(로컬 뿐만 아니라 외부 URL 도 가능) 위치를 resource 로 사용할 수 있도록 할 수 있습니다.


@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/upload/**")
				.addResourceLocations("file:///opt/upload/");

	}

}


위 예제에서 알 수 있듯이 URI 가 /upload/ 이하로 요청이 될 경우 로컬 Disk 의 /opt/upload/ 경로에 있는 파일을 사용자에게 제공하겠다는 의미입니다. /upload/ 경로 이하의 모든 경로와 파일명은 /opt/upload/ 에서 동일하게 찾아서 제공해줍니다.

주의할 것은 resourceLocation 지정 시 로컬 경로일 때 "file:///" 접두어를 빼먹으면 안된다는 것입니다.


당연히 파일 업로드를 구현할 때 저장될 위치에 대해서는 가변적으로 경로를 설정하거나 파일명을 수정하는 형태로 저장할텐데, File 객체를 통해서 저장될 위치를 지정해줘야 할 때 /opt/upload/ 을 여기저기 코드에 적어놓고 쓰는건 비효율적입니다. 그러므로 application.properties 혹은 yml 에 경로를 지정해두고 이를 불러다 쓰는 방법을 권장합니다. 이렇게 할 경우 Spring Profiles 을 이용해 상황에 맞는 가번적인 값을 설정하기에 편리합니다.


resources:

  location: /opt/upload/

  uri_path: /upload



@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	@Value("${resources.location}")
	private String resourcesLocation;
	@Value("${resources.uri_path:}")
	private String resourcesUriPath;

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler(resourcesUriPath + "/**")
				.addResourceLocations("file://" + resourcesLocation);

	}

}


반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함