Http와 스프링 (1) : Encoding - Brotli
목차
https://adunhansa.tistory.com/261
요즘 BackToBasic - HTTP 스터디를 다니고 있는데 이런저런 옵션들을 한번 스프링에 적용해보고 싶었단 말이지?
0 . 소개
2015년에 나온 압축기술인데
https://blog.naver.com/kgj1/220622925193
머.. 아무튼.. 성능은 이정도로 Gzip 보다 더 작은 파일이 나온다고 하더라 ?
https://merj.com/blog/case-study-improve-page-speed-with-minification-and-compression
브라우저 request 헤더요청에서 다음과 같이 보내게되면 난 brotli 로 힙하게(2015년에 나왔지만) 받을 수 있어~라고 전달한다고 한다. 크롬에서는 사실 뭐 당연히 받는 인코딩방법이랄까
흠... 그리하야.. 그냥저냥 연습해보는 브랜치 하나 생성후.. 쪼~금 연습해보았다.
1단계 EncodedResourceResolver 의 등록
second 프로젝트에 있고..
GzipResourceResolver 를 넣으려고 하니, Deprecated 되었다고한다.
그래서 대신에 EncodedResourceResolver를 넣으라고 하는데... 뭐.. 자바로 대충 만들어서 로그 좀 찍어가면서 기능을 익혔다.
EncodedResourceResolver는 5.1부터 나온건가.. 스프링 소스 설명 잠시 읽고
baeldung 따라 만든 연습용 설정이심.
2단계 프론트파일의 준비
그리고 css 파일을 대충 만들고 브로틀리 압축을 시켜야 한다.
여기와서 대충 가져옴
https://www.npmjs.com/package/brotli
const path = require("path");
const fs = require('fs');
const compress = require('brotli/compress');
var brotli = require('brotli');
const brotliSettings = {
extension: 'br',
skipLarger: true,
mode: 1, // 0 = generic, 1 = text, 2 = font (WOFF2)
quality: 10, // 0 - 11,
lgwin: 12 // default
};
fs.readdirSync('./css').forEach(file => {
if (file.endsWith('.js') || file.endsWith('.css') || file.endsWith('.html')) {
const buffer = fs.readFileSync(path.resolve(__dirname, './css/' + file))
const result = brotli.compress(buffer, brotliSettings);
fs.writeFileSync('./css/' + file + '.br', result);
}
});
맨처음에 압축한 브로틀리 파일이 자꾸 null 떠서 뭔가 했더니 파일이 너무 작아서 null 떳던 것..
뭐.. 연습용으로 폴더도 대충대충^^
자..이제 웹페이지에 접속해보면..
브로틀리 인코딩으로 응답이 내려옴을 볼 수 있다.
실제 코드로 찾는 과정은 여기..흠..
protected Resource resolveResourceInternal(@Nullable HttpServletRequest request, String requestPath,
List<? extends Resource> locations, ResourceResolverChain chain) {
logger.info("resolve Resource Internal : " + request + " , locations : "+locations + " , requestPath : "+requestPath);
Resource resource = chain.resolveResource(request, requestPath, locations);
logger.info("resource : "+ resource);
if (resource == null || request == null) {
return resource;
}
String acceptEncoding = getAcceptEncoding(request);
logger.info("accept Encoding : "+ acceptEncoding);
if (acceptEncoding == null) {
return resource;
}
for (String coding : this.contentCodings) {
logger.info("coding : "+coding);
if (acceptEncoding.contains(coding)) {
try {
logger.info("acceptEncoding :"+acceptEncoding +", with coding :"+coding);
String extension = getExtension(coding);
logger.info("extension :"+extension);
Resource encoded = new CustomEncodedResourceResolver.EncodedResource(resource, coding, extension);
logger.info("encoded :"+encoded+", exists():"+encoded.exists());
if (encoded.exists()) {
return encoded;
}
}
catch (IOException ex) {
if (logger.isTraceEnabled()) {
logger.trace("No " + coding + " resource for [" + resource.getFilename() + "]", ex);
}
}
}
}
return resource;
}
참고했던 링크들 (글 잘 정리된 한글 블로그가 잇엇는데 링크가 보이질 않는다 ㅠ )
- https://www.baeldung.com/spring-mvc-static-resources
- https://www.slideshare.net/arawnkr/resource-handling-in-spring-mvc
연습깃헙 :
https://github.com/arahansa/learn_http_with_spring
다음의 책을 보면서 스프링 예제코드를 찾아보았습니다 . 리얼월드 HTTP 도서 입니다.
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=187943894