์ด ๊ธ์์๋ Spring์์ ์ํ๋ ํด๋์
http://ip:port/resources/{file_name}๋ฑ์ uri๋ก ์ ๊ทผํ ์ ์๋๋ก ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ค๋ฃน๋๋ค.
๊ตฌํ ๋ฐฉ๋ฒ์๐งญ ํ๊ฒฝ ์ค์ ๋ถํฐ ๋์์์ต๋๋ค.
ํ์ฌ ์งํ ์ค์ธ ํ๋ก์ ํธ์์๋ FE, BE, AI๊ฐ ํ๋์ ์ํฌ์คํ ์ด์ ์์ ๋์๊ฐ๋๋ก ํด์ผํ๋ค๋ ์๊ตฌ์ฌํญ์ด ์์๋ค. ์ด๋ฌํ ํน์ฑ์ ๋ฐ์ํด ํ์ผ์ ์ฃผ๊ณ ๋ฐ์ ๋ resource path๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์ relative path๋ฅผ ์ฃผ๊ณ ๋ฐ๋๋ก API๋ฅผ ์ค๊ณํ๋ค. ๊ทธ๋์ ํ์ผ์ ์ง์ ์ ์ผ๋ก ์ ์กํ์ง ์๊ณ , ํ์ํ ํ์ผ์ path๋ง ์ ๋ฌํด ์ฌ์ฉํ๋ค.
ํด๋น ํ๋ก์ ํธ์์๋ DICOM ํ์ผ์ ์ฃผ๊ณ ๋ฐ์์ผ ํ๋ค. ์ฒ์์๋ ํ์ผ์ ์ง์ ์ ์ผ๋ก ์ ์กํ๋ ๋ฐฉํฅ์ผ๋ก ์ค๊ณ๋ฅผ ํ์์ง๋ง, DICOM ํ์ผ์ ํฌ๊ธฐ๋ฅผ ๋ณด๊ณ ์ค๊ณ๋ฅผ ์์ ํ๊ฒ ๋์๋ค. DICOM ํ์ผ์ ๊ฐ๋น 20~30MB์ ํฐ ์ฉ๋์ ๊ฐ์ง๊ณ ์๋ค. ๊ฐ study์ ์ธ๋ถ ์กฐํ ๋ฑ์์ ์ฝ 20๊ฐ ์ด์์ DICOM ํ์ผ์ ์ ์กํด์ผํ๊ธฐ์ ์ง์ ์ ์กํ๋ ๋ฐฉ์์ด ์ค๋ฒํค๋๊ฐ ํด ๊ฒ์ด๋ผ ํ๋จํ๋ค. ํนํ DICOM ํ์ผ์ BE โ FE๋ก ํด๋น DICOM ํ์ผ์ด ์๋ resource path๋ง ์ ๋ฌํด์ฃผ๋ฉด ํ๋ก ํธ์์ ํ์ํ ๋ ํ์ผ์ ๋ก๋ฉํ ์ ์์ด ํจ์จ์ ์ด์๋ค. ๊ฒฐ๋ก ์ ์ผ๋ก๋ ๊ทธ๊ฒ ํจ์จ์ ์ด๋ผ์ ๊ทธ๋ ๊ฒ ์ค๊ณํ๊ฒ ๋์๋ค๋ ์๊ธฐ๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ฉด ์๋ {project root path}/src/main/resources/static ๋ด๋ถ์ ์๋ ํ์ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅํ๋ค. ๋ณ๋๋ก ์ค์ ํด์ฃผ์ง ์์๋ ์์ ๊ฒฝ๋ก์ ์๋ ๋ชจ๋ ์ ์ ๋ฆฌ์์ค๋ค์ ๋ํด http://ip:port/{static_resource_file}๋ก ์ ๊ทผํ๋ฉด ๋๋ค.
์ ๊ทผ ๊ฒฝ๋ก(url)๋ ๊ธฐ๋ณธ์ ์ผ๋ก /**(root)๋ถํฐ ๋งคํ๋๋ค. ์ด๋ฅผ ์์ ํ๊ณ ์ถ๋ค๋ฉด, application.yml์์ spring.mvc.static-path-pattern์ ์๋์ ๊ฐ์ด ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
spring:
mvc:
static-path-pattern: {์ํ๋ url ์ค์ } (e.g. /static/**)
{project root path}/src/main/resources/ ๋ด๋ถ์ ์ํ๋ ๋๋ ํ ๋ฆฌ์ ์ ๊ทผํ๋๋ก ์ค์ ํ ์๋ ์๋ค. ์ด๋ฅผ ์ค์ ํ๊ธฐ ์ํด์๋ application.yml์์ spring.resources.static-locations๋ฅผ ์ค์ ํด์ฃผ๋ฉด ๋๋ค. ๊ธฐ๋ณธ ๊ฐ์ /static/๋ก ์ค์ ๋์ด์๋ค.
spring:
resources:
static-locations: {์ํ๋ ๊ฒฝ๋ก ์ค์ } (e.g. /images/)
๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ๋ ์ ์ ๋ฆฌ์์ค ์ ๊ทผ์ ์ํ๋ ๋ฆฌ์์ค๋ฅผ ๋ชจ๋ ์์ ๊ฒฝ๋ก์ ๋ฃ์ด์ค์ผ ํ๊ธฐ ๋๋ฌธ์ ํด๋น ํ๋ก์ ํธ์์๋ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ด์๋ค. ๋ฐ๋ผ์ BE ์๋ฒ ๋ด๋ถ ์ ์ฅ ๊ณต๊ฐ์ ์๋ resource ๋๋ ํ ๋ฆฌ๋ฅผ ์ํ๋ url์ ๋งคํํด์ฃผ๊ธฐ ์ํด ๋ณ๋๋ก ์ค์ ํด์ฃผ์๋ค.
์ ์ ๋ฆฌ์์ค ์ ๊ทผ์ ์ปค์คํ
ํ๊ธฐ ์ํด์๋WebMvcConfigurer๋ฅผ ๊ตฌํํ๋ ํด๋์ค์์ addResourceHandlers๋ฅผ overrideํด์ฃผ๋ฉด ๋๋ค. ResourceHandler๋ฅผ ์ ์ํ๋ฉด์ uri์ ํ์ผ ์์คํ
๋ด๋ถ์ ๊ฒฝ๋ก๋ฅผ ์ค์ ํด์ฃผ๋ฉด url์ ํตํด ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
resourcePath ๋๋ ํ ๋ฆฌ ํ์์ ๋ชจ๋ resource์ ์ ๊ทผํ๊ธฐ ์ํด์๋ /๋ก ๋๋๋๋ก ์๋์ ๊ฐ์ด directory path๋ฅผ ์ค์ ํด์ผ ํ๋ค. ํ๊ฒฝ ๋ณ์๋ช
์ ์ํ๋๋๋ก ์ค์ ํด์ค๋ ๋๋ค. ์ฌ๊ธฐ์๋ DICOM ํ์ผ๋ค์ ๋ํ resourcePath๋ฅผ ์๋์ ๊ฐ์ด ์ค์ ํด์ฃผ์๋ค.
dicom:
resourcePath: /home/ubuntu/dicom/
MvcConfig.java ํด๋์ค๋ WebMvcConfigurer์ ๊ตฌํ์ฒด์ด๋ค.resource handler ์ค์ ์ ์์์ ๋ฏธ๋ฆฌ ์ ์ํด๋ ํ๊ฒฝ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค. ๋ด ๊ฒฝ์ฐ์๋ http://ip:port/api/v1/resources/**๋ก ์ ๊ทผํ๊ธฐ ์ํด ์๋์ ๊ฐ์ด ์ค์ ํด์ฃผ์๋ค.
package example.global.config;
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Value("${dicom.resourcePath}")
private String localStoragePath;
/**
* add resource handlers to serve static resources with http://ip:port/api/v1/resources/**
*
* @param registry resource handler registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(File.separator + "api/v1/resources" + File.separator + "**")
.addResourceLocations("file:" + localStoragePath);
}
}
ํ
์คํธ ์ ์น ๋ธ๋ผ์ฐ์ ์ http://ip:port/api/v1/resources/{resource file path}๋ฅผ ์
๋ ฅํด ์ ์์ ์ผ๋ก ์ ๊ทผ ๊ฐ๋ฅํ ๊ฒ์ ํ์ธํ๋ค. ๋น์ฐํ ๋ง์ด์ง๋ง ์์์ ์ค์ ํ url๋ก ์ ๊ทผํด์ผํ๋ค. ํ๋ก ํธ์์ ์์ฒญ ์ ๋์ผํ url์ GET ์์ฒญ์ ์ ์กํด ์ ๊ทผ ๊ฐ๋ฅํ๋ค.
์ ๋ ๊ฒ๋ง ์ค์ ํ๋ฉด ๋ชจ๋ ๊ฒ ์ข์ ๊ฒ ๊ฐ์ง๋ง...... ์ฌ์ค ํฐ ๋จ์ ์ด ์๋ค. ์ธ์ฆ ๋ฐ ์ธ๊ฐ ์์ด uri๋ก ์ ์ ์์์ ์ ๊ทผํ ์ ์๊ฒ ๋ง๋๋ ๊ฒ์ ๋ณด์ ์ธก๋ฉด์์ ๋ฌธ์ ์ ์์ง๊ฐ ์๋ค. ๋ณ๋ก ํฐ ๋ฌธ์ ๊ฐ ์๋ ์ ์๋ค๊ณ ์๊ฐํ ์ ์์ง๋ง, ๊ฒฝ๋ก๋ง ์๋ค๋ฉด ๊ฐ์ธ์ ๋ณด ๋ฑ์ด ๋ด๊ธด ํ์ผ์ ์ ๊ทผํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์๋์ ์กฐ์น๋ฅผ ๋ฏธ๋ฆฌ ์ทจํด๋๋ ๊ฒ์ ์ถ์ฒํ๋ค. ๋ฌผ๋ก ์์ฝ์ฒ ๋ฑ์ ๊ณต๊ณต๊ธฐ๊ด์์ ์๊ตฌํ๋ ์ฌ์ด๋ฒ๋ณด์ ์๊ตฌ์ฌํญ์๋ ํฌํจ๋์ด ์์ง๋ ์๋ค.
์ํ๋ ์์์ด ํฌํจ๋ ๋๋ ํ ๋ฆฌ๋ฅผ resourcePath๋ก ์ค์ ํด๋๋ฉด ํ์ ๋๋ ํ ๋ฆฌ ๋ฐ ํ์ผ์ ๋ชจ๋ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค. ๋ฐ๋ผ์ ๋ถํ์ํ๊ฒ ์์ ๋๋ ํ ๋ฆฌ๊ฐ resourcePath๋ก ์ค์ ๋์ด์๋ค๋ฉด ์ด๋ฅผ ํ์ํ ์์๋ง ๋ชจ์๋ ํ์ ๋๋ ํ ๋ฆฌ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค. ๋ฌผ๋ก ๊ทธ๋๋ ์ ๊ทผ ์์ฒด๋ฅผ ๋ง์ง๋ ๋ชปํ๋ค.
Spring security๋ฅผ ํ์ฉํด ์ธ์ฆ์ ๊ตฌํํ๊ณ ์๋ค๋ฉด, ์ค์ ํด๋ ์ ์ ์์์ ์ ๊ทผํ uri์ ๊ถํ ์ค์ ์ ๋ถ์ฌํ ์ ์๋ค. ๋ด ๊ฒฝ์ฐ์๋ /api/v1/resources/**์ ์ ์ด๋ ๋ก๊ทธ์ธํด์ผ ์ ๊ทผํ ์ ์๋๋ก SecurityConfig.java์์ ์๋์ ๊ฐ์ด ์ค์ ํด์ฃผ์๋ค.
package example.global.config;
// package ์๋ต
/**
* Security Configuration
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
... // ๋๋จธ์ง ์ค์ ์ ์๋ต
.authorizeHttpRequests(
(authorizeRequests) ->
authorizeRequests
// ์ ์ ์์์ ์ ๊ทผํ๋ uri์ ๋ํด ๊ถํ ์ค์
.requestMatchers("/api/v1/resources/**").authenticated()
.anyRequest().permitAll()
)
return http.build();
}
}
์ด์ ์ /resources/**์ ๋ํด์ authenticated()๋ฅผ ์ค์ ํด ํ
์คํธ ํด๋ณธ ์ ์ด ์์๋๋ฐ, ๋์ํ์ง ์์๋ค. ์ปค์คํ
ํ ๊ฒฝ์ฐ์๋ง ์ค์ ๋๋ ์ด์ ์ ๋ํด์๋ ๋ ๊ณต๋ถ๊ฐ ํ์ํ ๊ฒ์ผ๋ก ์๊ฐ๋๋ค.
Reference : Serve Static Resources with Spring | Baeldung