네이버의 인덱스 페이지 하나가 동작하기위해 많은 자원이 필요하기때문에 매번 실시간으로 가져올 때 부하를 방지하기 위해 캐시에 정적 자원을 저장해둠.
재방문시에는 HTML, CSS JS와 같은 정적 자원은 미리저장된 캐시에서 꺼내쓰라는 의미에서 304라는 상태코드로 회신하기때문에 로딩이 빨리됨.
하지만 피씨 밀고 처음 열고 브라우저 켜서 네이버 들어가면 캐시없어서 로딩 오래걸림.
response.setHeader("Pragma", "no-cache");
: 캐시를 남기지마response.addHeader("Pragma", "no-store");
: 저장하지마response.setHeader("Cache-Control", "no-cache");
: 캐시를 남기지마response.addHeader("Cache-Control", "no-store");
: 저장하지마response.setDateHeader("Expires", 0);
<script type="text/javascript" src="<%=request.getContextPath() %>/js/sample.js?time=<%=(new Date()).getTime()%>"></script>
The Cache-Control HTTP/1.1 general-header field is used to specify directives for caching mechanisms in both requests and responses. Use this header to define your caching policies with the variety of directives it provides.
Cache-Control: no-store
The cache should not store anything about the client request or server response. A request is sent to the server and a full response is downloaded each and every time.
Cache-Control: no-cache
A cache will send the request to the origin server for validation before releasing a cached copy.
The "public" directive indicates that the response may be cached by any cache. This can be useful if pages with HTTP authentication, or response status codes that aren't normally cacheable, should now be cached.
On the other hand, "private" indicates that the response is intended for a single user only and must not be stored by a shared cache. A private browser cache may store the response in this case.
Cache-Control: private
Cache-Control: public
The most important directive here is max-age=< seconds >, which is the maximum amount of time in which a resource will be considered fresh. This directive is relative to the time of the request, and overrides the Expires header (if set). For the files in the application that will not change, you can normally use aggressive caching. This includes static files such as images, CSS files, and JavaScript files, for example.
Cache-Control: max-age=31536000
When using the "must-revalidate" directive, the cache must verify the status of the stale resources before using it and expired ones should not be used. For more details, see the Validation section below.
Cache-Control: must-revalidate
현재 서버의 시각 : <%=new Date() %>
<meta http-equiv="Refresh" content="5;url="https://www.naver.com">
<body>
$(document).ready(function(){})
과 같음function init() {
setTimeout(() => {
location.reload();
}, 1000); // ★ 유의 ★ 람다식의 this는 언제나 window!!
}
// getServerTime.jsp
<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8"%>
<%=new Date()%>
let timeArea = $("#timeArea");
setInterval(() => {
$.ajax({
url : "getServerTime.jsp",
method : "get",
dataType : "text",
success : function(resp) { // resp: 응답으로 돌아온 문자열
timeArea.text(resp);
},
error : function(xhr) {
console.log(xhr);
}
});
}, 1000); // 요청 주기 1초
let timeArea = $("#timeArea");
// 전역으로 빼두어서 그냥 쓰면되는데, 필기 편의상 복붙중
setInterval(() => {
fetch("getServerTime.jsp") // 리턴타입: promise (then, failed를 콜백으로 씀)
.then(funtion(response) {
if(response.ok) { // success(ajax)
console.log(response);
return response.text(); // body데이터 꺼내기 위함. 하지만 아직 body 아닌 promise객체 리턴
/*
* ex)
* 서버에서 문자열 1gb를 보내야하는 상황.
* 1. 한번에 읽을 수 없고,
* 2. 네트워크 대역폭때문에 쪼개져서 응답이 나가야함
* (대역폭 1mb 이라면 1024개의 낱개 데이터(청크)로 내보내야 함)
* 이런 상황때문에 데이터를 한번에 return data로 넘기는 것이 아닌,
* 다 모으면 바꾸라고 promise 객체로 넘긴다. (응답데이터 수신에 시간 소요 많기때문)
* return type이 다시 promise이기 때문에 또 아래의 then 콜백함수가 작동함
*/
}else { // 200외 다른 상태 코드: fetch와 ajax의 차이 = fetch:1 100~500 모두 resp로 도착
console.log(response.status);
}
}).then(function(text) { // 응답데이터 수신이 완료되어 콜백 실행됨, 매개변수 = text
timeArea.text(text);
})
}, 1000);
// getServerTime_SSE.jsp
<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/event-stream; charset=UTF-8"
pageEncoding="UTF-8" buffer="8kb"%>
<%
boolean flag = true;
while(flag == true){
Thread.sleep(1000); // 1초의 갭
Date now = new Date();
%>
id:<%=now.getTime() %> <%-- 그냥 내보내면 뭔지 모르기때문에 식별자 필요--%>
event:test<%--type결정 --%>
data:<%=now%>
data:line data<%--라인 개행 따로 안해주니 \\n 한개라고 생각해서 한건의 데이타로 구별됨, 데이터구별하려면 n두번 --%>
<%
out.flush(); // buffer 다 차지않아도 flush하겠다
}
%>
let timeArea = $("#timeArea");
// 전역으로 빼두어서 그냥 쓰면되는데, 필기 편의상 복붙중
let es = new EventSource("getServerTime_SSE.jsp");
es.onopen = function(event){
console.log(event);
}
/*
// 아래의 3가지 방식중 하나 사용
// 1. type이 message 일때
es.onmessage = function(event) {
console.log(event);
timeArea.text(event.data);
// timeArea가 밑에서 선언되어도 사용할 수 있음
// -> 선언 이후에 function이 실행되기때문
}
// 2. type을 test로 변경했을 때 (SSE.jsp 참조)
// 2-1. jquery 이용
// 이 방식을 그냥 사용할 경우 시간이 화면에 나오지 않음
// -> $사용으로 jquery이벤트로 전환되었기때문
$(es).on("test", function(event) {
console.log(event);
timeArea.text(event.originalEvent.data); // 해결방안: js이벤트로 다시 변경
}
*/
// 2-2. 기본 js 사용
es.addEventListener("test", function(event) {
console.log(event);
timeArea.text(event.data);
}
es.onerror = function(event) {
if(event.target.readyState != EventSource.CLOSED) { // 에러 발생 후에도 연결이 유지되고 있다면
ex.close(); // 연결 끊어라.
// 이렇게 명시적으로 중단하지 않는다면?
// -> es가 스트림 데이터를 계속 가져와야한다고 생각하고 3-5초 간격으로 새로고침(서버에 요청)을 계속함
}
}
-flowControl.jsp
- 클라이언트: A에게 요청
- 서버 내에서 A -> B로 이동 (서버 내 이동 = 서버사이드 경로 이용)
- 클라잉너트: 응답받으면 클라이언트는 a에게 요청해서 받은 것이기 때문에 a한테 왔다고 생각함
- B의 존재 모름, A -> B이동사실 모름
클라이언트 -> a -> b -> 다시 a -> 클라이언트
- 클라이언트가 A에게 요청
- A가 만든 req(1번)는 사라져버림
- A에서 다시 클라이언트에게로 응답내보냄 -> Forward, Include와의 차이
- resp에 제대로된 message body 없이 response line, header만 구성됨
- 대신 resp에 (B에 대한 정보 + 이 응답 데이터는 body가 없다는 메시지 + SC) 내보내야됨
- status code(302, 307: moved, 여기로 이사갔어요)
- 클라이언트가 A의 resp를 뜯어봤더니 302가 까꿍 -> 아하! 하고 헤더에 로케이션찾아서 다시 요청보냄
- 다시 클라이언트가 B에게 요청함
- 이때 새로운 req(2번)가 생김
- B에서 최종응답 내보냄
- 최종응답데이터는 4마지막단계 b에서 나가는 데이터
요약
① B를 찾기 위해 A로 클라이언트가 요청보냄
② A가 님이 찾는 B 여기 없어요 하고 응답 보내면서, B의 위치와 상태코드 내보내야함 -> 이때 위치를 헤더 location에 셋팅