[백업][가리사니] servlet 으로 전달되는 이미지 캐싱! etag를 구현해보자!
http, servlet

이 문서는 가리사니 개발자 포럼에 올렸던 글의 백업 파일입니다. 오래된 문서가 많아 현재 상황과 맞지 않을 수 있습니다.

참고 문서 : https://en.wikipedia.org/wiki/HTTP_ETag

가리사니 회원정보의 문장(퍼스나콘)의 경우 파일시스템에 회원번호로 저장하지만, 회원번호는 외부에서 볼 수 없게 해야하기 때문에, 필명을 인자로 받은 서블릿이 파일스트림을 읽어 프록시처럼 전달합니다.

일반적인 프록시를 구현한다고 하면 크게 문제가 되지않지만, 이미지 같은경우는 텍스트와 비교해서 매우 용량이 크기 때문에 서버에 무리를 줄 수 있습니다.

그래서 HTTP 1.0의 웹캐싱을 주려고했지만, 몇가지 문제점이 있습니다. 그래서 HTTP 1.1의 캐시 기능인 304 (Not Modified) 를 사용하기위해 ETag를 사용했습니다.

1. ETag 는 무었인가?

HTTP 1.0 의 캐시의 경우 Expires 나 max-age 혹은 브라우저의 판단에 따라서 새로 가져오기때문에 도중에 갑자기 데이터가 바뀌더라도 바로 적용이 되지않습니다. HTTP 1.1 에서는 이걸 개선한 캐시가 나왔습니다. 어떤 파일을 받을때 응답 해더의 ETag : "1" 이라고 전달하면 브라우저는 "1"을 저장하고있다가 동일한 url로 전송할 경우 요청 해더의 If-None-Match : "1" 이라고 답합니다. 이때 버전이 같다면 아무내용없이 304 (Not Modified) 를 전달해주게됩니다. 버전의 변화가 있다면 새로운 ETag와함께 내용을 전달해주게 됩니다. ETag에 들어가는 내용에 대한 규칙이 없기 때문에 원하는 방법으로 구현할 수 있습니다. 필자의 경우 정확히 파일만을 전송해 주는 것 이기 때문에, 해당 파일의 마지막수정시간을 전달해주었습니다.

2. 구현예제

// 파일을 읽어서 마지막 수정시간을 가져온다.
File file = new File("파일경로");
String etag = '"'+Long.toString(file.lastModified())+'"';

// 브라우저로부터 받은 요청을 가져온다.
String ifNoneMatch = request.getHeader("If-None-Match");

// 해더에 전달할 내용.
response.setHeader("ETag", etag);

// 브라우저에서 가진 버전과 서버 버전이 같은경우.
if (etag.equals(ifNoneMatch))
{
	// 304 를 전달함과 동시에 종료한다.
	pageStatus(304);
	return;
}
... // 매칭되지않는 경우 전달할 것을 작성합니다.

위와 같이 작성하셨다면 브라우저의 네트워크 탐색기에서 아래와 같은 정보를 확인 할 수 있습니다. // 상태정보 Status Code:304 Not Modified // Response Headers 응답 - 숫자는 마지막 파일 수정시간입니다. ETag:"1441032441236" // Request Headers 요청 - ETag 와 값이 같은지 확인 If-None-Match:"1441032441236"

추신. 강의가 중간에 끊어진거 같지만.... 기분탓입니다... 뫼 프레임워크에 ETag를 설정동시에 체크하는 로직하나를 넣어야겟네요.