Resource Handling in Spring MVC

Arawn Park
Arawn ParkSoftware Engineer at 스프링러너
Resource Handling 
in Spring MVC
박용권 
SK planet 
: 봄싹(SpringSprout) 
: 한국 스프링 사용자 모임(KSUG) 
: 라 스칼라 코딩단 
http://about.me/arawn 
: twitter / @arawnkr
Spring MVC에서 
정적 자원(css, js, etc)을 
처리해본 경험을 공유합니다.
Spring MVC : 리소스 제공(Serving) 
✔ ResourceHttpRequestHandler 
: URL 패턴에 따라 정적 자원 요청을 처리 
: org.springframework.core.io.Resource 인터페이스를 사용 
servletcontext, classpath, filesystem, etc 
: HTTP 캐시 설정 기능 제공 
expires 또는 cache-control를 사용한 캐시 설정 
last-modified 헤더 평가를 통해 304 상태코드 응답 
! 
✔ 설정 간소화 기능 제공 
: Java 기반 설정시 WebMvcConfigurer.addResourceHandlers(…) 사용 
: XML 기반 설정시 mvc:resources 태그 사용
리소스 제공 설정 
Java Config 
public void addResourceHandlers(ResourceHandlerRegistry registry) { 
registry.addResourceHandler("리소스에 접근할 URL 패턴") 
.addResourceLocations("리소스가 있는 위치"); 
} 
XML Config 
<mvc:resources mapping="리소스에 접근할 URL 패턴" 
location="리소스가 있는 위치"/>
리소스 제공 설정 
리소스에 접근할 URL 패턴 정의 
public void addResourceHandlers(ResourceHandlerRegistry registry) { 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("/resources/"); 
} 
http://spring.io/resources/css/default.css 
http://spring.io/resources/js/spring-by-pivotal.png 
http://spring.io/resources/img/spring-by-pivotal.png
리소스 제공 설정 
리소스가 있는 위치 설정 
public void addResourceHandlers(ResourceHandlerRegistry registry) { 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("/resources/"); 
} 
http://spring.io/resources/css/default.css 
. 
"## WEB-INF 
$ "## classes 
$ &## lib 
&## resources 
&## css 
&## default.css
DEMO 
(리소스 제공 설정)
Resource 인터페이스에 대한 다양한 구현체 
✔ ServletContextResource 
! 
! 
✔ ClassPathResource 
! 
! 
✔ FileSystemResource 
! 
! 
✔ UrlResource 
! 
! 
✔ etc 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("/resources/"); 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("classpath:/resources/"); 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("file:/resources/“); 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("http://spring.io");
리소스를 효율적으로 다루는 캐시 설정 
Java Config 
public void addResourceHandlers(ResourceHandlerRegistry registry) { 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("/resources/") 
.setCachePeriod(31556926); 
} 
XML Config 
<mvc:resources mapping="/resources/**" 
location="/resources/" 
cache-period="31556926"/>
리소스를 효율적으로 다루는 캐시 설정 
Java Config 
public void addResourceHandlers(ResourceHandlerRegistry registry) { 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("/resources/") 
.setCachePeriod(31556926); 
} 
Response headers : 
Cache-Control: "max-age=31556926, must-revalidate" 
Expires: "Sun, 16 Nov 2014 07:39:20 GMT" 
Last-Modified: "Thu, 20 Nov 2014 10:49:18 GMT"
리소스를 효율적으로 다루는 캐시 설정 
Java Config 
public void addResourceHandlers(ResourceHandlerRegistry registry) { 
registry.addResourceHandler("/resources/**") 
.addResourceLocations("/resources/") 
.setCachePeriod(0); 
} 
Response headers : 
Pragma: "no-cache" 
Cache-Control: "no-cache, no-store" 
Expires: "Thu, 01 Jan 1970 00:00:00 GMT”
DEMO 
(캐시 설정에 따른 동작)
Multi Module 
Web Application 
/ Backend) 
/ Server-side) 
(Frontend 
(Client-side
프로젝트 구조 
"## build.gradle - Gradle : 빌드 자동화 
"## gradle.properties 
"## settings.gradle 
"## backend - Spring IO Platform 사용해 개발된 Server-side 모듈 
$ &## src 
$ "## main 
$ $ "## java 
$ $ &## resources 
$ &## test 
&## frontend - 정적 자원(html, css, javascript)을 제공하는 Client-side 모듈 
"## package.json 
"## bower.json 
"## Gruntfile.js 
&## src 
"## assets 
"## helpers 
"## includes 
"## layouts 
"## libs 
&## pages
backend에 적용된 기술 훑어보기 
"## build.gradle - Gradle : 빌드 자동화 
"## gradle.properties 
"## settings.gradle 
"## backend - Spring IO Platform 사용해 개발된 Server-side 모듈 
$ &## src 
$ "## main 
$ $ "## java 
$ $ &## resources 
$ &## test 
&## frontend - 정적 자원(html, css, javascript)을 제공하는 Client-side 모듈 
"## package.json 
"## bower.json 
"## Gruntfile.js 
&## src 
"## assets 
"## helpers 
"## includes 
"## layouts 
"## libs 
&## pages 
✔ Spring Boot 
: Spring IO Platform 기반 개발을 빠르고 다양한 방법으로 시작 
: 애플리케이션 기능외 필요한 공통 컴포넌트를 제공 
✔ Thymeleaf 
: HTML 태그/속성 기반의 템플릿 엔진 
: Spring MVC & Security 와 통합을 위한 라이브러리 제공
frontend에 적용된 도구 훑어보기 
"## build.gradle - Gradle : 빌드 자동화 
"## gradle.properties 
"## settings.gradle 
"## backend - Spring IO Platform 사용해 개발된 Server-side 모듈 
$ &## src 
$ "## main 
$ $ "## java 
$ $ &## resources 
$ &## test 
&## frontend - 정적 자원(html, css, javascript)을 제공하는 Client-side 모듈 
"## package.json 
"## bower.json 
"## Gruntfile.js 
&## src 
"## assets 
"## helpers 
"## includes 
"## layouts 
"## libs 
&## pages 
✔ NPM(Node Package Manager) 
: 개발환경 및 의존성 관리 
✔ Bower 
: JavaScript Lib 의존성 관리(jquery, bootstrap, etc) 
✔ Grunt 
: Client-side 빌드 자동화 
: 다양한 Plugin 지원( jshint, usemin, filerev, assemble, etc )
frontend에 적용된 기술 훑어보기 (1/3) 
"## backend 
&## frontend 
"## package.json 
"## Gruntfile.js 
"## bower.json 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ "## cover.css 
$ $ $ &## default.css 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## bootstrap 
$ $ &## jquery 
$ "## includes 
$ $ "## common-css.hbs 
$ $ &## common-scripts.hbs 
$ "## layouts 
$ $ &## default.hbs 
$ &## pages 
$ &## about.hbs 
&## dist 
"## assets 
$ "## css 
$ $ &## style.min.99501602.css 
$ &## js 
$ &## app.min.264ed108.js 
&## pages 
&## about.html 
✔ CSS/JS 최적화(병합 및 압축) 
: grunt-usemin 
: grunt-contrib-concat 
: grunt-contrib-cssmin 
: grunt-contrib-uglify 
✔ Fingerprinting 
: grunt-filerev 
더 알아보려면 여기로! 
http://goo.gl/oGVCYT
frontend에 적용된 기술 훑어보기 (2/3) 
"## backend 
&## frontend 
"## package.json 
"## Gruntfile.js 
"## bower.json 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ "## cover.css 
$ $ $ &## default.css 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## bootstrap 
$ $ &## jquery 
$ "## includes 
$ $ "## common-css.hbs 
$ $ &## common-scripts.hbs 
$ "## layouts 
$ $ &## default.hbs 
$ &## pages 
$ &## about.hbs 
&## dist 
"## assets 
$ "## css 
$ $ &## style.min.99501602.css 
$ &## js 
$ &## app.min.264ed108.js 
&## pages 
&## about.html 
✔ 템플릿(HTML) 생성 
: assemble
frontend에 적용된 기술 훑어보기 (3/3) 
이제 
코드로 
만나보시죠! 
"## backend 
&## frontend 
"## package.json 
"## Gruntfile.js 
"## bower.json 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ "## cover.css 
$ $ $ &## default.css 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## bootstrap 
$ $ &## jquery 
$ "## includes 
$ $ "## common-css.hbs 
$ $ &## common-scripts.hbs 
$ "## layouts 
$ $ &## default.hbs 
$ &## pages 
$ &## about.hbs 
&## dist 
"## assets 
$ "## css 
$ $ &## style.min.99501602.css 
$ &## js 
$ &## app.min.264ed108.js 
&## pages 
&## about.html
frontend가 가출한 이유 
"## backend 
&## frontend 
"## package.json 
"## Gruntfile.js 
"## bower.json 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ "## cover.css 
$ $ $ &## default.css 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## bootstrap 
$ $ &## jquery 
$ "## includes 
$ $ "## common-css.hbs 
$ $ &## common-scripts.hbs 
$ "## layouts 
$ $ &## default.hbs 
$ &## pages 
$ &## about.hbs 
&## dist 
"## assets 
$ "## css 
$ $ &## style.min.99501602.css 
$ &## js 
$ &## app.min.264ed108.js 
&## pages 
&## about.html 
✔ dependency management 
✔ modularity 
✔ tests 
✔ build automation ( vs artifacts)
지금부터 Frontend의 
자원(html, css, javascript, image)을 
사용하는 방법을 살펴봅니다.
Frontend 의존성 다루기 
frontend 
backend
개발자의 친구 복붙- 
"## backend 
$ &## src 
$ "## main 
$ $ "## java 
$ $ "## resources 
$ $ &## webapp 
$ &## test 
$ "## java 
$ &## resources 
&## frontend 
&## src 
$ "## assets 
$ "## helpers 
$ "## includes 
$ "## layouts 
$ "## libs 
$ &## pages 
&## dist 
"## assets 
&## pages 
crtl + v 
crtl + c
Web Libraries in Jars 
WebJars 
✔ Client-side 웹 라이브러리를 JAR로 묶어서 제공하는 서비스 
✔ JVM 기반 빌드 도구(gradle, maven, sbt, etc)를 지원 (maven 저장소) 
bootstrap-3.3.1.jar 
&## META-INF 
&## resources 
&## webjars 
&## bootstrap 
&## 3.3.1 
"## css 
$ "## bootstrap.css 
$ &## bootstrap.min.css 
"## js 
$ "## bootstrap.js 
$ &## bootstrap.min.js 
"## fonts 
"## less 
&## webjars-requirejs.js 
<dependencies> 
<dependency> 
<groupId>org.webjars</groupId> 
<artifactId>bootstrap</artifactId> 
<version>3.3.1</version> 
</dependency> 
</dependencies>
DEMO 
(Servlet 3에서 webjars 사용)
Gradle로 통합하기 
"## build.gradle 
"## backend 
$ &## src 
$ "## main 
$ $ "## java 
$ $ "## resources 
$ $ &## webapp 
$ &## test 
&## frontend 
&## src 
$ "## assets 
$ "## helpers 
$ "## includes 
$ "## layouts 
$ "## libs 
$ &## pages 
&## dist 
"## assets 
&## pages 
frontend.jar 로 만든 후 
backend 모듈에 의존성을 추가!
frontend를 빌드 후 jar로 만들기 
"## build.gradle 
"## backend 
$ &## src 
$ "## main 
$ $ "## java 
$ $ "## resources 
$ $ &## webapp 
$ &## test 
&## frontend 
&## src 
$ "## assets 
$ "## helpers 
$ "## includes 
$ "## layouts 
$ "## libs 
$ &## pages 
&## dist 
"## assets 
&## pages 
project(':frontend') { 
apply plugin: 'java' 
! 
task npmInstall(type:Exec) { 
// do something 
} 
! 
task gruntBuild(type:Exec, dependsOn: [npmInstall]) { 
// do something 
} 
! 
jar { 
from 'dist' 
includeEmptyDirs = false 
} 
jar.dependsOn gruntBuild 
}
backend에 frontend 의존성 추가 
"## build.gradle 
"## backend 
$ &## src 
$ "## main 
$ $ "## java 
$ $ "## resources 
$ $ &## webapp 
$ &## test 
&## frontend 
&## src 
$ "## assets 
$ "## helpers 
$ "## includes 
$ "## layouts 
$ "## libs 
$ &## pages 
&## dist 
"## assets 
&## pages 
project(':frontend') { 
apply plugin: 'java' 
! 
task npmInstall(type:Exec) { 
// do something 
} 
! 
task gruntBuild(type:Exec, dependsOn: [npmInstall]) { 
// do something 
} 
! 
jar { 
from 'dist' 
includeEmptyDirs = false 
} 
jar.dependsOn gruntBuild 
} 
! 
project(':backend') { 
apply plugin: 'war' 
! 
dependencies { 
runtime project(':frontend') 
} 
}
DEMO 
(Gradle 통합과 자원 사용)
개발과 배포는 다르다
frontend: 배포시에는 최적화된 자원을 사용 
> grunt build:release 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ "## img 
$ $ &## js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
"## assets 
$ "## css 
$ $ &## style.min.6bde543a.css 
$ &## js 
$ &## app.min.142ca07c.js 
&## pages 
&## about.html 
<!DOCTYPE html> 
<html lang="ko"> 
<head> 
<link href='/assets/css/style.min.6bde543a.css' 
rel='stylesheet' type='text/css'/> 
</head> 
<body> 
<div class="site-wrapper"> 
// 생략 
</div> 
<script src='/assets/js/app.min.264ed108.js'></script> 
</body> 
</html>
frontend: 배포시에는 최적화된 자원을 사용 
> grunt build:release 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ "## img 
$ $ &## js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
"## assets 
$ "## css 
$ $ &## style.min.6bde543a.css 
$ &## js 
$ &## app.min.142ca07c.js 
&## pages 
&## about.html 
Classpath 위치한 자원을 사용 
! 
// build.gradle 
project(':frontend') { 
sourceSets.main.resources { srcDir 'dist' } 
} 
! 
// Java Config 
registry.addResourceHandler("/assets/**") 
.addResourceLocations("classpath:assets/");
frontend: 개발시에는 작성중인 css, js 사용 
> grunt build:develop 
<!DOCTYPE html> 
<html lang="ko"> 
<head> 
<link href="/libs/bootstrap/dist/css/bootstrap.css"/> 
<link href="/assets/css/default.css"/> 
</head> 
<body> 
<div class="site-wrapper"> 
// 생략 
</div> 
<script src="/libs/jquery/dist/jquery.js"/> 
<script src="/libs/bootstrap/dist/js/bootstrap.js"/> 
<script src="/assets/js/default.js"/> 
</body> 
</html> 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ &## default.css 
$ $ "## img 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
&## pages 
&## about.html
backend: 개발시에는 어떻게 자원에 접근하지? 
> grunt build:develop 
“어라!? dist/assets이 없네!?” 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ &## default.css 
$ $ "## img 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
&## pages 
&## about.html
backend: 개발시에는 어떻게 자원에 접근하지? 
> grunt build:develop 
src를 Classpath에 추가해볼까? 
! 
// build.gradle 
project(':frontend') { 
sourceSets.main.resources { srcDirs 'dist', 'src' } 
} 
! 
// console 
> gradle build 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ &## default.css 
$ $ "## img 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
&## pages 
&## about.html
backend: 개발시에는 어떻게 자원에 접근하지? 
없는게 없는 frontend.jar 
! 
frontend.jar 
"## assets 
$ "## css 
$ $ &## default.css 
$ "## img 
$ &## js 
$ &## default.js 
"## libs 
$ "## jquery 
$ &## bootstrap 
&## pages 
> grunt build:develop 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ $ &## default.css 
$ $ "## img 
$ $ &## js 
$ $ &## default.js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
&## pages 
&## about.html 
이건 아니야… ;;;
backend: 환경에 따른 자원 접근 전략 변경 
"## backend 
&## frontend 
"## src 
$ "## assets 
$ $ "## css 
$ $ "## img 
$ $ &## js 
$ "## libs 
$ $ "## jquery 
$ $ &## bootstrap 
$ &## pages 
&## dist 
"## assets 
$ "## css 
$ "## img 
$ &## js 
&## templates 
&## about.html 
String locations; 
! 
if(개발) { 
locations = src/assets 사용 
} else { 
locations = dist/assets 사용 
} 
! 
registry.addResourceHandler("/assets/**") 
.addResourceLocations(locations);
DEMO 
(환경에 따른 자원 접근 전략 변경)
회고
더 하고 싶었던 
이야기가 있었지만…
묻고 답하는 시간 
https://github.com/arawn/resource-handling-in-springmvc
끝.
1 of 43

Recommended

Generic Types in Java (for ArtClub @ArtBrains Software) by
Generic Types in Java (for ArtClub @ArtBrains Software)Generic Types in Java (for ArtClub @ArtBrains Software)
Generic Types in Java (for ArtClub @ArtBrains Software)Andrew Petryk
664 views64 slides
소프트웨어 개선 그룹(Sig) 개발 원칙 by
소프트웨어 개선 그룹(Sig) 개발 원칙소프트웨어 개선 그룹(Sig) 개발 원칙
소프트웨어 개선 그룹(Sig) 개발 원칙Hong Hyo Sang
85 views20 slides
Active Directoryドメインを作ってみよう ~ドメインの作成とDNSサーバーの設定~ by
Active Directoryドメインを作ってみよう ~ドメインの作成とDNSサーバーの設定~Active Directoryドメインを作ってみよう ~ドメインの作成とDNSサーバーの設定~
Active Directoryドメインを作ってみよう ~ドメインの作成とDNSサーバーの設定~Michio Koyama
4.3K views23 slides
Amazon Aurora 성능 향상 및 마이그레이션 모범 사례 - AWS Summit Seoul 2017 by
Amazon Aurora 성능 향상 및 마이그레이션 모범 사례 - AWS Summit Seoul 2017Amazon Aurora 성능 향상 및 마이그레이션 모범 사례 - AWS Summit Seoul 2017
Amazon Aurora 성능 향상 및 마이그레이션 모범 사례 - AWS Summit Seoul 2017Amazon Web Services Korea
3.3K views64 slides
How to Manage Scale-Out Environments with MariaDB MaxScale by
How to Manage Scale-Out Environments with MariaDB MaxScaleHow to Manage Scale-Out Environments with MariaDB MaxScale
How to Manage Scale-Out Environments with MariaDB MaxScaleMariaDB plc
1.2K views42 slides
(WEB302) Best Practices for Running WordPress on AWS | AWS re:Invent 2014 by
(WEB302) Best Practices for Running WordPress on AWS | AWS re:Invent 2014(WEB302) Best Practices for Running WordPress on AWS | AWS re:Invent 2014
(WEB302) Best Practices for Running WordPress on AWS | AWS re:Invent 2014Amazon Web Services
14.2K views55 slides

More Related Content

What's hot

AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트) by
AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트)AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트)
AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트)Amazon Web Services Korea
7.5K views43 slides
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019 by
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019Amazon Web Services Korea
3.2K views42 slides
Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트) by
Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트)Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트)
Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트)Amazon Web Services Korea
11.1K views75 slides
AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축 by
AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축
AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축Sungmin Kim
843 views169 slides
Apache Sling Generic Validation Framework by
Apache Sling Generic Validation FrameworkApache Sling Generic Validation Framework
Apache Sling Generic Validation FrameworkRadu Cotescu
1.7K views21 slides
MariaDB MaxScale by
MariaDB MaxScaleMariaDB MaxScale
MariaDB MaxScaleMariaDB plc
1.9K views41 slides

What's hot(20)

AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트) by Amazon Web Services Korea
AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트)AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트)
AWS CLOUD 2017 - AWS 기반 하이브리드 클라우드 환경 구성 전략 (김용우 솔루션즈 아키텍트)
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019 by Amazon Web Services Korea
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
AWS를 활용한 글로벌 오피스 업무 환경 구축하기 - 류한진, 이랜드시스템스 :: AWS Summit Seoul 2019
Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트) by Amazon Web Services Korea
Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트)Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트)
Amazon ECS/ECR을 활용하여 마이크로서비스 구성하기 - 김기완 (AWS 솔루션즈아키텍트)
AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축 by Sungmin Kim
AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축
AWS Personalize 중심으로 살펴본 추천 시스템 원리와 구축
Sungmin Kim843 views
Apache Sling Generic Validation Framework by Radu Cotescu
Apache Sling Generic Validation FrameworkApache Sling Generic Validation Framework
Apache Sling Generic Validation Framework
Radu Cotescu1.7K views
MariaDB MaxScale by MariaDB plc
MariaDB MaxScaleMariaDB MaxScale
MariaDB MaxScale
MariaDB plc1.9K views
Liquibase migration for data bases by Roman Uholnikov
Liquibase migration for data basesLiquibase migration for data bases
Liquibase migration for data bases
Roman Uholnikov1.4K views
다양한 솔루션으로 만들어가는 AWS 네트워크 보안::이경수::AWS Summit Seoul 2018 by Amazon Web Services Korea
다양한 솔루션으로 만들어가는 AWS 네트워크 보안::이경수::AWS Summit Seoul 2018다양한 솔루션으로 만들어가는 AWS 네트워크 보안::이경수::AWS Summit Seoul 2018
다양한 솔루션으로 만들어가는 AWS 네트워크 보안::이경수::AWS Summit Seoul 2018
금융 서비스 패러다임의 전환 가속화 시대, 신한금융투자의 Cloud First 전략 - 신중훈 AWS 솔루션즈 아키텍트 / 최성봉 클라우... by Amazon Web Services Korea
금융 서비스 패러다임의 전환 가속화 시대, 신한금융투자의 Cloud First 전략  - 신중훈 AWS 솔루션즈 아키텍트 / 최성봉 클라우...금융 서비스 패러다임의 전환 가속화 시대, 신한금융투자의 Cloud First 전략  - 신중훈 AWS 솔루션즈 아키텍트 / 최성봉 클라우...
금융 서비스 패러다임의 전환 가속화 시대, 신한금융투자의 Cloud First 전략 - 신중훈 AWS 솔루션즈 아키텍트 / 최성봉 클라우...
Amazon Personalize 소개 (+ 실습 구성)::김영진, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나 by Amazon Web Services Korea
Amazon Personalize 소개 (+ 실습 구성)::김영진, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나Amazon Personalize 소개 (+ 실습 구성)::김영진, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
Amazon Personalize 소개 (+ 실습 구성)::김영진, 솔루션즈 아키텍트, AWS::AWS AIML 스페셜 웨비나
아마존 웹 서비스 상에서 MS SQL 100% 활용하기::김석원::AWS Summit Seoul 2018 by Amazon Web Services Korea
아마존 웹 서비스 상에서 MS SQL 100% 활용하기::김석원::AWS Summit Seoul 2018아마존 웹 서비스 상에서 MS SQL 100% 활용하기::김석원::AWS Summit Seoul 2018
아마존 웹 서비스 상에서 MS SQL 100% 활용하기::김석원::AWS Summit Seoul 2018
AWS Security 솔루션 자세히 살펴보기 :: 신용녀 :: AWS Finance Seminar by Amazon Web Services Korea
AWS Security 솔루션 자세히 살펴보기 :: 신용녀 :: AWS Finance SeminarAWS Security 솔루션 자세히 살펴보기 :: 신용녀 :: AWS Finance Seminar
AWS Security 솔루션 자세히 살펴보기 :: 신용녀 :: AWS Finance Seminar
좌충우돌 ORM 개발기 | Devon 2012 by Daum DNA
좌충우돌 ORM 개발기 | Devon 2012좌충우돌 ORM 개발기 | Devon 2012
좌충우돌 ORM 개발기 | Devon 2012
Daum DNA11.2K views
클라우드 세상에서 살아남기: 금융편 - 이한주 대표이사/공동창업자, 베스핀 글로벌 / 김민성 팀장, KB국민카드 :: AWS Summit ... by Amazon Web Services Korea
클라우드 세상에서 살아남기: 금융편 - 이한주 대표이사/공동창업자, 베스핀 글로벌 / 김민성 팀장, KB국민카드 :: AWS Summit ...클라우드 세상에서 살아남기: 금융편 - 이한주 대표이사/공동창업자, 베스핀 글로벌 / 김민성 팀장, KB국민카드 :: AWS Summit ...
클라우드 세상에서 살아남기: 금융편 - 이한주 대표이사/공동창업자, 베스핀 글로벌 / 김민성 팀장, KB국민카드 :: AWS Summit ...
Cross-account encryption with AWS KMS and Slack Enterprise Key Management - S... by Amazon Web Services
Cross-account encryption with AWS KMS and Slack Enterprise Key Management - S...Cross-account encryption with AWS KMS and Slack Enterprise Key Management - S...
Cross-account encryption with AWS KMS and Slack Enterprise Key Management - S...
Amazon Web Services2.1K views
[AWS Migration Workshop] 데이터베이스를 AWS로 손쉽게 마이그레이션 하기 by Amazon Web Services Korea
[AWS Migration Workshop]  데이터베이스를 AWS로 손쉽게 마이그레이션 하기[AWS Migration Workshop]  데이터베이스를 AWS로 손쉽게 마이그레이션 하기
[AWS Migration Workshop] 데이터베이스를 AWS로 손쉽게 마이그레이션 하기
AWS 고객이 주로 겪는 운영 이슈에 대한 해법-AWS Summit Seoul 2017 by Amazon Web Services Korea
AWS 고객이 주로 겪는 운영 이슈에 대한 해법-AWS Summit Seoul 2017AWS 고객이 주로 겪는 운영 이슈에 대한 해법-AWS Summit Seoul 2017
AWS 고객이 주로 겪는 운영 이슈에 대한 해법-AWS Summit Seoul 2017
AWS 클라우드 보안 및 규정 준수 소개 (박철수) - AWS 웨비나 시리즈 by Amazon Web Services Korea
AWS 클라우드 보안 및  규정 준수 소개 (박철수) - AWS 웨비나 시리즈AWS 클라우드 보안 및  규정 준수 소개 (박철수) - AWS 웨비나 시리즈
AWS 클라우드 보안 및 규정 준수 소개 (박철수) - AWS 웨비나 시리즈

Similar to Resource Handling in Spring MVC

4-3. jquery by
4-3. jquery4-3. jquery
4-3. jqueryJinKyoungHeo
790 views12 slides
Node.js by
Node.jsNode.js
Node.jsymtech
1.6K views26 slides
Front-end Development Process - 어디까지 개선할 수 있나 by
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나JeongHun Byeon
50.5K views64 slides
스프링군살없이세팅하기(The way to setting the Spring framework for web.) by
스프링군살없이세팅하기(The way to setting the Spring framework for web.)스프링군살없이세팅하기(The way to setting the Spring framework for web.)
스프링군살없이세팅하기(The way to setting the Spring framework for web.)EunChul Shin
6.9K views38 slides
요즘웹개발 by
요즘웹개발요즘웹개발
요즘웹개발Lee MyoungKyu
193 views22 slides
Isomorphicspring Isomorphic - spring web seminar 2015 by
Isomorphicspring Isomorphic - spring web seminar 2015Isomorphicspring Isomorphic - spring web seminar 2015
Isomorphicspring Isomorphic - spring web seminar 2015sung yong jung
2.5K views31 slides

Similar to Resource Handling in Spring MVC(20)

Node.js by ymtech
Node.jsNode.js
Node.js
ymtech1.6K views
Front-end Development Process - 어디까지 개선할 수 있나 by JeongHun Byeon
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나
JeongHun Byeon50.5K views
스프링군살없이세팅하기(The way to setting the Spring framework for web.) by EunChul Shin
스프링군살없이세팅하기(The way to setting the Spring framework for web.)스프링군살없이세팅하기(The way to setting the Spring framework for web.)
스프링군살없이세팅하기(The way to setting the Spring framework for web.)
EunChul Shin6.9K views
Isomorphicspring Isomorphic - spring web seminar 2015 by sung yong jung
Isomorphicspring Isomorphic - spring web seminar 2015Isomorphicspring Isomorphic - spring web seminar 2015
Isomorphicspring Isomorphic - spring web seminar 2015
sung yong jung2.5K views
XE 오픈 세미나(2014-06-28) - (2/3) 레이아웃 제작 노하우 by XpressEngine
XE 오픈 세미나(2014-06-28) - (2/3) 레이아웃 제작 노하우XE 오픈 세미나(2014-06-28) - (2/3) 레이아웃 제작 노하우
XE 오픈 세미나(2014-06-28) - (2/3) 레이아웃 제작 노하우
XpressEngine11.3K views
Backend Master | 3.1.1 Build - JS build tools by Kyunghun Jeon
Backend Master | 3.1.1 Build - JS build toolsBackend Master | 3.1.1 Build - JS build tools
Backend Master | 3.1.1 Build - JS build tools
Kyunghun Jeon60 views
자바스크립트 프레임워크 살펴보기 by Jeado Ko
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
Jeado Ko4.6K views
React native 개발 및 javascript 기본 by Tj .
React native 개발 및 javascript 기본React native 개발 및 javascript 기본
React native 개발 및 javascript 기본
Tj .703 views
Html5 performance by yongwoo Jeon
Html5 performanceHtml5 performance
Html5 performance
yongwoo Jeon3.1K views
[아꿈사/111105] html5 9장 클라이언트측 데이터로 작업하기 by sung ki choi
[아꿈사/111105] html5 9장 클라이언트측 데이터로 작업하기[아꿈사/111105] html5 9장 클라이언트측 데이터로 작업하기
[아꿈사/111105] html5 9장 클라이언트측 데이터로 작업하기
sung ki choi1.9K views
Jenkins를 활용한 javascript 개발 by 지수 윤
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발
지수 윤21.6K views
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012 by Daum DNA
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
Daum DNA8.9K views

More from Arawn Park

우린 같은 곳을 바라 보고 있나요? by
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?Arawn Park
106 views32 slides
코틀린 멀티플랫폼, 미지와의 조우 by
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우Arawn Park
994 views58 slides
kotlinx.serialization by
kotlinx.serializationkotlinx.serialization
kotlinx.serializationArawn Park
243 views35 slides
#살아있다 #자프링외길12년차 #코프링2개월생존기 by
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기Arawn Park
1.8K views82 slides
우아한 모노리스 by
우아한 모노리스우아한 모노리스
우아한 모노리스Arawn Park
6.7K views59 slides
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다 by
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다Arawn Park
17.9K views41 slides

More from Arawn Park(17)

우린 같은 곳을 바라 보고 있나요? by Arawn Park
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?
Arawn Park106 views
코틀린 멀티플랫폼, 미지와의 조우 by Arawn Park
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
Arawn Park994 views
kotlinx.serialization by Arawn Park
kotlinx.serializationkotlinx.serialization
kotlinx.serialization
Arawn Park243 views
#살아있다 #자프링외길12년차 #코프링2개월생존기 by Arawn Park
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
Arawn Park1.8K views
우아한 모노리스 by Arawn Park
우아한 모노리스우아한 모노리스
우아한 모노리스
Arawn Park6.7K views
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다 by Arawn Park
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
잘 키운 모노리스 하나 열 마이크로서비스 안 부럽다
Arawn Park17.9K views
점진적인 레거시 웹 애플리케이션 개선 과정 by Arawn Park
점진적인 레거시 웹 애플리케이션 개선 과정점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정
Arawn Park5K views
이벤트 기반 분산 시스템을 향한 여정 by Arawn Park
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정
Arawn Park13.6K views
Introduction to Kotlin by Arawn Park
Introduction to KotlinIntroduction to Kotlin
Introduction to Kotlin
Arawn Park726 views
Reactive Web - Servlet & Async, Non-blocking I/O by Arawn Park
Reactive Web - Servlet & Async, Non-blocking I/OReactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/O
Arawn Park3.9K views
Spring framework 4.x by Arawn Park
Spring framework 4.xSpring framework 4.x
Spring framework 4.x
Arawn Park3.3K views
씹고 뜯고 맛보고 즐기는 스트림 API by Arawn Park
씹고 뜯고 맛보고 즐기는 스트림 API씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API
Arawn Park7.1K views
Spring framework 3.2 > 4.0 — themes and trends by Arawn Park
Spring framework 3.2 > 4.0 — themes and trendsSpring framework 3.2 > 4.0 — themes and trends
Spring framework 3.2 > 4.0 — themes and trends
Arawn Park8.1K views
overview of spring4 by Arawn Park
overview of spring4overview of spring4
overview of spring4
Arawn Park2.1K views
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 ) by Arawn Park
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
조금 더 좋은 개발자가 된다는 것( 부제: 컨퍼런스의 발표자가 된다는 것 )
Arawn Park2.4K views
[Spring Camp 2013] Java Configuration 없인 못살아! by Arawn Park
[Spring Camp 2013] Java Configuration 없인 못살아![Spring Camp 2013] Java Configuration 없인 못살아!
[Spring Camp 2013] Java Configuration 없인 못살아!
Arawn Park16.7K views
Vagrant와 chef로 개발서버 구축 자동화하기 by Arawn Park
Vagrant와 chef로 개발서버 구축 자동화하기Vagrant와 chef로 개발서버 구축 자동화하기
Vagrant와 chef로 개발서버 구축 자동화하기
Arawn Park26.6K views

Resource Handling in Spring MVC

  • 1. Resource Handling in Spring MVC
  • 2. 박용권 SK planet : 봄싹(SpringSprout) : 한국 스프링 사용자 모임(KSUG) : 라 스칼라 코딩단 http://about.me/arawn : twitter / @arawnkr
  • 3. Spring MVC에서 정적 자원(css, js, etc)을 처리해본 경험을 공유합니다.
  • 4. Spring MVC : 리소스 제공(Serving) ✔ ResourceHttpRequestHandler : URL 패턴에 따라 정적 자원 요청을 처리 : org.springframework.core.io.Resource 인터페이스를 사용 servletcontext, classpath, filesystem, etc : HTTP 캐시 설정 기능 제공 expires 또는 cache-control를 사용한 캐시 설정 last-modified 헤더 평가를 통해 304 상태코드 응답 ! ✔ 설정 간소화 기능 제공 : Java 기반 설정시 WebMvcConfigurer.addResourceHandlers(…) 사용 : XML 기반 설정시 mvc:resources 태그 사용
  • 5. 리소스 제공 설정 Java Config public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("리소스에 접근할 URL 패턴") .addResourceLocations("리소스가 있는 위치"); } XML Config <mvc:resources mapping="리소스에 접근할 URL 패턴" location="리소스가 있는 위치"/>
  • 6. 리소스 제공 설정 리소스에 접근할 URL 패턴 정의 public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/"); } http://spring.io/resources/css/default.css http://spring.io/resources/js/spring-by-pivotal.png http://spring.io/resources/img/spring-by-pivotal.png
  • 7. 리소스 제공 설정 리소스가 있는 위치 설정 public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/"); } http://spring.io/resources/css/default.css . "## WEB-INF $ "## classes $ &## lib &## resources &## css &## default.css
  • 9. Resource 인터페이스에 대한 다양한 구현체 ✔ ServletContextResource ! ! ✔ ClassPathResource ! ! ✔ FileSystemResource ! ! ✔ UrlResource ! ! ✔ etc registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/"); registry.addResourceHandler("/resources/**") .addResourceLocations("classpath:/resources/"); registry.addResourceHandler("/resources/**") .addResourceLocations("file:/resources/“); registry.addResourceHandler("/resources/**") .addResourceLocations("http://spring.io");
  • 10. 리소스를 효율적으로 다루는 캐시 설정 Java Config public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/") .setCachePeriod(31556926); } XML Config <mvc:resources mapping="/resources/**" location="/resources/" cache-period="31556926"/>
  • 11. 리소스를 효율적으로 다루는 캐시 설정 Java Config public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/") .setCachePeriod(31556926); } Response headers : Cache-Control: "max-age=31556926, must-revalidate" Expires: "Sun, 16 Nov 2014 07:39:20 GMT" Last-Modified: "Thu, 20 Nov 2014 10:49:18 GMT"
  • 12. 리소스를 효율적으로 다루는 캐시 설정 Java Config public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/resources/") .setCachePeriod(0); } Response headers : Pragma: "no-cache" Cache-Control: "no-cache, no-store" Expires: "Thu, 01 Jan 1970 00:00:00 GMT”
  • 13. DEMO (캐시 설정에 따른 동작)
  • 14. Multi Module Web Application / Backend) / Server-side) (Frontend (Client-side
  • 15. 프로젝트 구조 "## build.gradle - Gradle : 빌드 자동화 "## gradle.properties "## settings.gradle "## backend - Spring IO Platform 사용해 개발된 Server-side 모듈 $ &## src $ "## main $ $ "## java $ $ &## resources $ &## test &## frontend - 정적 자원(html, css, javascript)을 제공하는 Client-side 모듈 "## package.json "## bower.json "## Gruntfile.js &## src "## assets "## helpers "## includes "## layouts "## libs &## pages
  • 16. backend에 적용된 기술 훑어보기 "## build.gradle - Gradle : 빌드 자동화 "## gradle.properties "## settings.gradle "## backend - Spring IO Platform 사용해 개발된 Server-side 모듈 $ &## src $ "## main $ $ "## java $ $ &## resources $ &## test &## frontend - 정적 자원(html, css, javascript)을 제공하는 Client-side 모듈 "## package.json "## bower.json "## Gruntfile.js &## src "## assets "## helpers "## includes "## layouts "## libs &## pages ✔ Spring Boot : Spring IO Platform 기반 개발을 빠르고 다양한 방법으로 시작 : 애플리케이션 기능외 필요한 공통 컴포넌트를 제공 ✔ Thymeleaf : HTML 태그/속성 기반의 템플릿 엔진 : Spring MVC & Security 와 통합을 위한 라이브러리 제공
  • 17. frontend에 적용된 도구 훑어보기 "## build.gradle - Gradle : 빌드 자동화 "## gradle.properties "## settings.gradle "## backend - Spring IO Platform 사용해 개발된 Server-side 모듈 $ &## src $ "## main $ $ "## java $ $ &## resources $ &## test &## frontend - 정적 자원(html, css, javascript)을 제공하는 Client-side 모듈 "## package.json "## bower.json "## Gruntfile.js &## src "## assets "## helpers "## includes "## layouts "## libs &## pages ✔ NPM(Node Package Manager) : 개발환경 및 의존성 관리 ✔ Bower : JavaScript Lib 의존성 관리(jquery, bootstrap, etc) ✔ Grunt : Client-side 빌드 자동화 : 다양한 Plugin 지원( jshint, usemin, filerev, assemble, etc )
  • 18. frontend에 적용된 기술 훑어보기 (1/3) "## backend &## frontend "## package.json "## Gruntfile.js "## bower.json "## src $ "## assets $ $ "## css $ $ $ "## cover.css $ $ $ &## default.css $ $ &## js $ $ &## default.js $ "## libs $ $ "## bootstrap $ $ &## jquery $ "## includes $ $ "## common-css.hbs $ $ &## common-scripts.hbs $ "## layouts $ $ &## default.hbs $ &## pages $ &## about.hbs &## dist "## assets $ "## css $ $ &## style.min.99501602.css $ &## js $ &## app.min.264ed108.js &## pages &## about.html ✔ CSS/JS 최적화(병합 및 압축) : grunt-usemin : grunt-contrib-concat : grunt-contrib-cssmin : grunt-contrib-uglify ✔ Fingerprinting : grunt-filerev 더 알아보려면 여기로! http://goo.gl/oGVCYT
  • 19. frontend에 적용된 기술 훑어보기 (2/3) "## backend &## frontend "## package.json "## Gruntfile.js "## bower.json "## src $ "## assets $ $ "## css $ $ $ "## cover.css $ $ $ &## default.css $ $ &## js $ $ &## default.js $ "## libs $ $ "## bootstrap $ $ &## jquery $ "## includes $ $ "## common-css.hbs $ $ &## common-scripts.hbs $ "## layouts $ $ &## default.hbs $ &## pages $ &## about.hbs &## dist "## assets $ "## css $ $ &## style.min.99501602.css $ &## js $ &## app.min.264ed108.js &## pages &## about.html ✔ 템플릿(HTML) 생성 : assemble
  • 20. frontend에 적용된 기술 훑어보기 (3/3) 이제 코드로 만나보시죠! "## backend &## frontend "## package.json "## Gruntfile.js "## bower.json "## src $ "## assets $ $ "## css $ $ $ "## cover.css $ $ $ &## default.css $ $ &## js $ $ &## default.js $ "## libs $ $ "## bootstrap $ $ &## jquery $ "## includes $ $ "## common-css.hbs $ $ &## common-scripts.hbs $ "## layouts $ $ &## default.hbs $ &## pages $ &## about.hbs &## dist "## assets $ "## css $ $ &## style.min.99501602.css $ &## js $ &## app.min.264ed108.js &## pages &## about.html
  • 21. frontend가 가출한 이유 "## backend &## frontend "## package.json "## Gruntfile.js "## bower.json "## src $ "## assets $ $ "## css $ $ $ "## cover.css $ $ $ &## default.css $ $ &## js $ $ &## default.js $ "## libs $ $ "## bootstrap $ $ &## jquery $ "## includes $ $ "## common-css.hbs $ $ &## common-scripts.hbs $ "## layouts $ $ &## default.hbs $ &## pages $ &## about.hbs &## dist "## assets $ "## css $ $ &## style.min.99501602.css $ &## js $ &## app.min.264ed108.js &## pages &## about.html ✔ dependency management ✔ modularity ✔ tests ✔ build automation ( vs artifacts)
  • 22. 지금부터 Frontend의 자원(html, css, javascript, image)을 사용하는 방법을 살펴봅니다.
  • 23. Frontend 의존성 다루기 frontend backend
  • 24. 개발자의 친구 복붙- "## backend $ &## src $ "## main $ $ "## java $ $ "## resources $ $ &## webapp $ &## test $ "## java $ &## resources &## frontend &## src $ "## assets $ "## helpers $ "## includes $ "## layouts $ "## libs $ &## pages &## dist "## assets &## pages crtl + v crtl + c
  • 25. Web Libraries in Jars WebJars ✔ Client-side 웹 라이브러리를 JAR로 묶어서 제공하는 서비스 ✔ JVM 기반 빌드 도구(gradle, maven, sbt, etc)를 지원 (maven 저장소) bootstrap-3.3.1.jar &## META-INF &## resources &## webjars &## bootstrap &## 3.3.1 "## css $ "## bootstrap.css $ &## bootstrap.min.css "## js $ "## bootstrap.js $ &## bootstrap.min.js "## fonts "## less &## webjars-requirejs.js <dependencies> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.1</version> </dependency> </dependencies>
  • 26. DEMO (Servlet 3에서 webjars 사용)
  • 27. Gradle로 통합하기 "## build.gradle "## backend $ &## src $ "## main $ $ "## java $ $ "## resources $ $ &## webapp $ &## test &## frontend &## src $ "## assets $ "## helpers $ "## includes $ "## layouts $ "## libs $ &## pages &## dist "## assets &## pages frontend.jar 로 만든 후 backend 모듈에 의존성을 추가!
  • 28. frontend를 빌드 후 jar로 만들기 "## build.gradle "## backend $ &## src $ "## main $ $ "## java $ $ "## resources $ $ &## webapp $ &## test &## frontend &## src $ "## assets $ "## helpers $ "## includes $ "## layouts $ "## libs $ &## pages &## dist "## assets &## pages project(':frontend') { apply plugin: 'java' ! task npmInstall(type:Exec) { // do something } ! task gruntBuild(type:Exec, dependsOn: [npmInstall]) { // do something } ! jar { from 'dist' includeEmptyDirs = false } jar.dependsOn gruntBuild }
  • 29. backend에 frontend 의존성 추가 "## build.gradle "## backend $ &## src $ "## main $ $ "## java $ $ "## resources $ $ &## webapp $ &## test &## frontend &## src $ "## assets $ "## helpers $ "## includes $ "## layouts $ "## libs $ &## pages &## dist "## assets &## pages project(':frontend') { apply plugin: 'java' ! task npmInstall(type:Exec) { // do something } ! task gruntBuild(type:Exec, dependsOn: [npmInstall]) { // do something } ! jar { from 'dist' includeEmptyDirs = false } jar.dependsOn gruntBuild } ! project(':backend') { apply plugin: 'war' ! dependencies { runtime project(':frontend') } }
  • 30. DEMO (Gradle 통합과 자원 사용)
  • 32. frontend: 배포시에는 최적화된 자원을 사용 > grunt build:release "## backend &## frontend "## src $ "## assets $ $ "## css $ $ "## img $ $ &## js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist "## assets $ "## css $ $ &## style.min.6bde543a.css $ &## js $ &## app.min.142ca07c.js &## pages &## about.html <!DOCTYPE html> <html lang="ko"> <head> <link href='/assets/css/style.min.6bde543a.css' rel='stylesheet' type='text/css'/> </head> <body> <div class="site-wrapper"> // 생략 </div> <script src='/assets/js/app.min.264ed108.js'></script> </body> </html>
  • 33. frontend: 배포시에는 최적화된 자원을 사용 > grunt build:release "## backend &## frontend "## src $ "## assets $ $ "## css $ $ "## img $ $ &## js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist "## assets $ "## css $ $ &## style.min.6bde543a.css $ &## js $ &## app.min.142ca07c.js &## pages &## about.html Classpath 위치한 자원을 사용 ! // build.gradle project(':frontend') { sourceSets.main.resources { srcDir 'dist' } } ! // Java Config registry.addResourceHandler("/assets/**") .addResourceLocations("classpath:assets/");
  • 34. frontend: 개발시에는 작성중인 css, js 사용 > grunt build:develop <!DOCTYPE html> <html lang="ko"> <head> <link href="/libs/bootstrap/dist/css/bootstrap.css"/> <link href="/assets/css/default.css"/> </head> <body> <div class="site-wrapper"> // 생략 </div> <script src="/libs/jquery/dist/jquery.js"/> <script src="/libs/bootstrap/dist/js/bootstrap.js"/> <script src="/assets/js/default.js"/> </body> </html> "## backend &## frontend "## src $ "## assets $ $ "## css $ $ $ &## default.css $ $ "## img $ $ &## js $ $ &## default.js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist &## pages &## about.html
  • 35. backend: 개발시에는 어떻게 자원에 접근하지? > grunt build:develop “어라!? dist/assets이 없네!?” "## backend &## frontend "## src $ "## assets $ $ "## css $ $ $ &## default.css $ $ "## img $ $ &## js $ $ &## default.js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist &## pages &## about.html
  • 36. backend: 개발시에는 어떻게 자원에 접근하지? > grunt build:develop src를 Classpath에 추가해볼까? ! // build.gradle project(':frontend') { sourceSets.main.resources { srcDirs 'dist', 'src' } } ! // console > gradle build "## backend &## frontend "## src $ "## assets $ $ "## css $ $ $ &## default.css $ $ "## img $ $ &## js $ $ &## default.js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist &## pages &## about.html
  • 37. backend: 개발시에는 어떻게 자원에 접근하지? 없는게 없는 frontend.jar ! frontend.jar "## assets $ "## css $ $ &## default.css $ "## img $ &## js $ &## default.js "## libs $ "## jquery $ &## bootstrap &## pages > grunt build:develop "## backend &## frontend "## src $ "## assets $ $ "## css $ $ $ &## default.css $ $ "## img $ $ &## js $ $ &## default.js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist &## pages &## about.html 이건 아니야… ;;;
  • 38. backend: 환경에 따른 자원 접근 전략 변경 "## backend &## frontend "## src $ "## assets $ $ "## css $ $ "## img $ $ &## js $ "## libs $ $ "## jquery $ $ &## bootstrap $ &## pages &## dist "## assets $ "## css $ "## img $ &## js &## templates &## about.html String locations; ! if(개발) { locations = src/assets 사용 } else { locations = dist/assets 사용 } ! registry.addResourceHandler("/assets/**") .addResourceLocations(locations);
  • 39. DEMO (환경에 따른 자원 접근 전략 변경)
  • 41. 더 하고 싶었던 이야기가 있었지만…
  • 42. 묻고 답하는 시간 https://github.com/arawn/resource-handling-in-springmvc
  • 43. 끝.