[Spring Boot] 웹 최적화

홍준·2023년 6월 26일
8
post-thumbnail
post-custom-banner

들어가며

웹 개발을 하면서 웹 성능 최적화는 말을 한 번쯤 들어 봤을 것이라고 생각한다.
웹 개발자에게 웹 성능 최적화는 쉽게 접할 수 있는 이슈이며 피할 수 없는 숙제라고 생각한다.
이번 작업은 웹 성능 최적화 방법중 클라이언트 응답시간을 줄이는 방법으로 브라우저가 리소스를 불러오는 성능을 높이는 로딩 성능 최적화를 적용해보려고 한다.


1. 로딩 성능 최적화 - HTTP Cache (Web Cache)

💡 캐시란 데이터에 빠르게 접근하기 위해 자주 사용되는 데이터나 값을 미리 복사해 놓는 임시 장소를 의미한다.

웹 어플레이케이션에서 사용 되는 웹 캐시는 사용자(Client)가 웹 사이트(Serve)에 접속할 때, 정적 컨텐츠(이미지, JS, CSS 등)를 특정 위치(Client, Network 등)에 저장하여, 웹 사이트 서버에 해당 컨텐츠를 매번 요청하여 받는 것이 아니라, 특정 위치에서 불러옴으로써 사이트 응답시간을 줄이고 서버 트래픽 감소 효과를 볼 수 있는 것을 말한다.

HTTP Cache 적용하기

웹 서버는 응답에 Cache-Control 헤더를 추가하여 특정 리소스를 캐시 하도록 브라우저에 지시 할 수 있다.

우리는 Spring Boot 프로젝트를 생성하여 Spring MVC Cache-Control 적용 방법과 캐시 제어 방법을 확인하고 프로젝트에 적용해 보려고 한다.

1. Controller 캐시 제어

  • 1.1 ResponseEntity 이용한 Cache-Control 설정하는 법
@GetMapping("/exists")
@ResponseBody
public ResponseEntity<String> existCache () {
    CacheControl cacheControl = CacheControl.noCache()
    return ResponseEntity.ok()
      .cacheControl(cacheControl)
      .body(UUID.randomUUID().toString());
}
  • 1.2 HttpServletResponse 이용한 Cache-Control 설정하는 법
@GetMapping(value = "/exists02")
public String existCache02 (final HttpServletResponse response) {
  String cacheControl = CacheControl.noCache().getHeaderValue();
  response.addHeader("Cache-Control", cacheControl);
  return "index";
}

2. 정적 리소스에 대한 캐시 제어

  • 2.1 정적 리소스(js, css)에 대한 캐시 제어

💡 Spring Boot에서는 기본적으로 정적 리소스 요청을 처리할 수 있는 ResourceHttpRequestHandler 를 제공한다.

/* classpath:/static/ 에 있는 정적 리소스를 /resources/** 경로에 매핑 */
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
	registry.addResourceHandler("resources/**")
        	.addResourceLocations("classpath:/static/")
            .setCacheControl(CacheControl.noCache().cachePrivate());
}
 

3. 인터셉터에서 캐시 제어

  • 3.1 인터셉터에서 캐시 제어

💡 Spring MVC 애플리케이션에서 인터셉터를 사용하면 모든 요청에 대해 사전 및 사후 처리를 수행 할 수 있다.

/* /login으로 시작하는 모든 요청 Cache-Control 헤더를 추가 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
    WebContentInterceptor interceptor = new WebContentInterceptor();
    interceptor.addCacheMapping(CacheControl.noCache().cachePrivate(), "/login/*");
    registry.addInterceptor(interceptor);
} 

4. Etag (캐시 유효성 검사)

  • 4.1 Etag란?

💡 ETag란 EntityTag의 줄임말로, 웹 캐시 유효성 검증에 사용된다. 리소스의 특정 버전에대한 고유값이 ETag의 값이되고, 리소스의 내용이 업데이트되면 ETag도 바뀐다.

  • 4.2 Etag 적용하기

Spring 프레임 워크는 ShallowEtagHeaderFilter 클래스에서 Etag의 표준 기능을 구현하고 있다.

우리는 특정 URL 패턴에 Etag 적용을 위하여 아래와 같이 FilterRegistrationBean 을 통해서 ShallowEtagHeaderFilter를 빈으로 등록하여 Etag 적용해보자.

@Configuration
public class ETagHeaderFilter {
    @Bean
    public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
        FilterRegistrationBean<ShallowEtagHeaderFilter> filterRegistrationBean    = new FilterRegistrationBean<>( new ShallowEtagHeaderFilter());
        filterRegistrationBean.addUrlPatterns("/cache/*");
        return filterRegistrationBean;
    }
}
  • 4.3 Etag 검증하기

Test 코드를 통해 실제로 Etag 값이 다르게 나오는지 확인해보자.

@Test
void etagCheck () {

        TestRestTemplate rest = new TestRestTemplate();
        
        ResponseEntity<String> springRes =
                rest.getForEntity("http://localhost:8080/cache/exists03?name={name}",String.class,"Spring");

        ResponseEntity<String> summerRes =
                rest.getForEntity("http://localhost:8080/cache/exists03?name={name}",String.class,"Summer");

        assertThat(springRes.getHeaders().getETag()).isNotEqualTo(summerRes.getHeaders().getETag());

}

2.로딩 성능 최적화 - 압축전송 (GZIP)

💡 Gzip 이란?
Gzip 은 GNU zip 의 줄임말이며 리눅스/유닉스 시스템에서 널리쓰이는 압축 소프트웨어이다.

웹서버 통신을 할 때 데이터를 Gzip 압축하여 전송하면 속도가 더 빨라진다.

  • Gzip 사용 안할 경우 : [서버에서 데이터 전송] -> [클라이언트 브라우저가 표시]
  • Gzip 을 사용할 경우 : [서버에서 데이터를 압축 후 전송] -> [클라이언트 브라우저가 압축을 풀고 표시]

Gizp 적용하기

Spring Boot에서 설정하는 법은 간단하다. 설정파일에 아래와 같이 설정하면 사용이 가능하다.

server:
  compression:
    enabled: true
    mime-types: text/html,text/plain,text/css,application/javascript,application/json
    min-response-size: 500
  • enabled: true -> gzip 설정을 사용.
  • mime-types -> 압축을 허용할 mime-type.
  • min-response-size -> 압축을 허용할 최소 사이즈.

Gzip 적용확인


마무리

여기까지 Spring Boot 을 이용한 웹 최적화 설정하는 방법에 대해 알아보았다.

실제 실무에서 최적화를 한다면 캐시 생명주기를 어떤식으로 줄것이며, Gzip 적용을 Apache 나 Nginx 등 Web서버에서 처리 할지 Tomcat 이나 Weblogic 등 어플리케이션 서버(Was)에서 처리할지 고려할 부분이 많이 있다.

앞서 말했듯 웹 개발자에게 웹 성능 최적화는 쉽게 접할 수 있는 이슈이며 피할 수 없는 숙제라고 생각한다. 어떤 프로젝트든 웹 성능 최적화 고려하고 적용 해두자 👍

profile
어제의 나를 이기자 🔥
post-custom-banner

0개의 댓글