request header

Cache Control

  • 세가지의 속성들을 모두 사용하여 웹접근성 보장
    • 어느 브라우저에서도 캐시컨트롤이 될 수 있도록

Pragma

Cache-Control

Expires

  • 캐시 만료시간 셋팅
  • setMaxAge vs. Expires
    • setMaxAge: 기간
    • Expires: 시점

refresh

  • 서버사이드에서 주기적으로 갱신되는 데이터들을 어떻게 클라이언트가 쉽게 가져갈 것인가

동기

header에 refresh 셋팅

  • 동기방식으로 적용
  • 전체 윈도우 대상으로 refresh
    • 페이지자체의 ui가 다시 로딩됨

비동기

  1. 화면 전체에 락을 걸지 않고 (=ui는 리프레시하지않고) 데이터만 리프레시해서 가져오는 방법
  2. 주기적으로 비동기요청을 발생시키려면 long polling 방식이 필요
  • Long Polling
    • long polling으로 주기설정하려면 js의 스케줄링 함수 필요
      • setTimeout: 시간지연
      • setInterval: 주기적인 작업 (+ clearInterval)
    • long poliing방식의 단점
      • 1) 완전한 실시간이 아님 (마치 실시간인 것처럼 과장)
        • setInterval의 주기1초
        • 1초와 1초사이 그중간에 0.5초사이에 갱신데이터 실시간으로 가져갈수있어? -> 못함
      • 2) 빠른 주기의 요청으로 인한 서버의 부하
        • 서버 입장: 불특정 다수의 클라이언트가 매 1초마다 요청
    • longpollling 단점 해결
      • 1) 웹소켓
      • 2) server-sent event
  • ajax와 fetch의 공통점, 차이점
    • 공통점: ajax나 fetch나 setInterval없으면 소용x => long polling 방식이란 증거
    • 차이점: 비동기 요청을 어떤 식으로 발생시킬 것인가?
      • 사용하는 api는 다르지만, 기본적으로 락을 걸지않고 비동기요청을 발생시킨다는 사실은 같음
      • ajax: XMLHttpRequest
      • fetch: promise객체를 이용해 promise pattern을 이용

Ajax

$.ajax({
    url : "getServerTime.jsp",
    method : "get",
    dataType : "text",
    error : function(xhr) {
      console.log(xhr);
  }).done(function(xhr) {  //xhr로 성공실패 판단
    // xhr이 가지고있는 상태값, promise패턴 파악
    timeArea.text(resp);
  }
});
  • 기본적인 사항
    • 응답데이터의 사이즈가 크다면 네트워크에서 처리할 수있는 단위의 청크로 끊어져서 옴
  • success
    • 모든 청크가 다 들어와서 완전한 형태의 응답데이터가 만들어지고 그 응답데이터에 대해 언마셜링까지 끝나고 나서야 호출
  • done
    • 요청에 대한 처리가 다 끝나면(= 응답데이터가 완전히 다 도착을 하고 나면) 호출
    • done을 넣었다는 것은 success 펑션을 넣은 것과 비슷
  • done과 success 차이점
    • success: 콕 찝어 성공했을때만
    • done: 성공 실패, 모든 상황을 커버함 (promise 객체처럼)
      • 마치 fetch처럼 사용하기 위해 ajax에서 이 방식을 사용

Fetch

  • 함수 자체를 호출할 때는 많은 정보를 넘기지않지만 비동기 요청 이후의 상황을 promise객체의 상태로 넘겨줌
  • promise를 받은 이후에 취할 액션을 then과 fetch로 설정
  • promise를 쓰냐 안쓰냐의 차이가 xhr과 fetch의 차이
  • 간혹 필드에서는 ajax에서 fetch방식을 사용하기도함

Server-Sent Event (SSE)

  • server-sent
    • Event Source로 단 1번의 요청을 넘김(인터벌로 묶여놓지않기때문) -> 한번의 요청으로 인해 연결이 수립된 이후 건건의 데이터(메시지 이벤트)가 그 통로로 계속 전달이 되어 클라이언트사이드에서 처리됨
      • connectless 방식이 아니다
      • text 형식의 stream data가 흘러와야한다
  • interval이나 timeout으로 묶여있지않음
    • = 주기적으로 요청을 넘기는 구조가 아님
  • getservertime sse.jsp
    • mime: text/event-stream; : 흐름으로 전달이되어야한다
      • 데이터가 흐름으로 전달될때 문제점?
        • 경계가 어디냐? 경계모호해짐
        • 데이터가 건 by 건으로 전송되어야하는데 한 건과 다른 건의 이벤트를 어떻게 식별할거냐? -> enter 2번
  • 건 별 데이터를 처리하기 위해 eventlistenr를 사용하고있음
    • 데이터타입을 test로 했기떄문 이벤트의 타입이 test인것
  • 이벤트소스에서는 하나의 어플리케이션을 구성할때 Event-driven 방식으로 구성할 수 있다
    • SSE 장점
      • 한 번의 요청으로 연결통로를 수립한 후, 여러번의 요청을 보내지 않고도 통로를 재활용하여 사용 가능
      • 서버사이드에서 클라이언트쪽으로 푸시메세지를 보낼때 (섭->클의 일방적구조) 적합
    • SSE 단점
      • 클->섭으로의 데이터 전달 불가능
      • 양방향 실시간 통신이 필요하다면 웹소켓을 사용해야함

흐름제어

  • flowControl.jsp

dispatch (forward, include)

  • 공통점: 둘다 RequestDispatcher(분기제어 관리자)를 이용해서 서버내에서 이동하는 구조
    • 서버내에서만 이동: 중간에 응답데이터가 나가지않는다
      • a -> b로갈때 a에게 발생한 요청정보가 사라지지않는다
      • 분기라고 표현하는 이유: 출발점에서 발생한 데이터를 도착지까지 그대로 가져가기때문
    • state가 그대로 유지가된다
  • dispatch 주로 쓰이는 상황
    • 1) 모델2구조 (forward)
      • 컨트롤러에서 모델데이터가 만들어지고 뷰단으로 넘겨야할때 이때 forward를 주로사용
    • 2) validation하다가 문제가 생겼을 때 (forward)
      • 요청이 완전히 처리되지 않았는데 request를 없애버리면안되니까 request살리기위해 dispatch 방식이용
    • 3) 페이지모듈화 (include)
      • 하나의 응답데이터를 보낼 떄 여러 개의 JSP로 페이지만들떄 쓰는 방식

forward

  • 최종 응답데이터는 a -> b로 갔다면 b에서 최종 응답데이터가 나감

include

  • a -> b로 간후 b에서 데이터 처리후 a로 돌아감
  • a에서 만들어졌던 데이터 + b에서 만들어졌던 데이터가 모두 합쳐져서 응답데이터가 나감
  • b를 include한다
  • 출발지와 도착지에서 만들어진 모든 UI가 전송되는 구조

redirect

  • 다시 새로운 요청이 발생하는 구조
  1. 최초 요청 발생
  2. 최초 요청에 대한 처리가 이루어짐
  3. 바디가 없고, 302/307이라는 상태코드와 로케이션, 함께 내보냄
  4. 브라우저가 300번대 상태코드를 보고 헤더를 뒤져 로케이션을 찾아냄
  5. 로케이션에 있는 주소(클라이언트사이드 주소)로 브라우저가 새로운 요청을 보냄
  6. 최종 응답은 마지막으로 이동한 최종 도착지인 B에서 완전한 UI가 나가게됨
  • 클라이언트는 도착지 B에 대한 정보를 안다
    • 브라우저가 새로운요청을 보냈기때문에 알고있음
    • 하지만 디스패치방식에서는 서버 안에서만 이동 했기때문에 클라이언트는 B의 정보를 모른다
    • 디스패치 방식에서는 클라잉언트가 모든 응답이 A에서 왔다고 착각
      • 클라이언트가 이 상태에서 F5키를 눌럿을떄 다시 A에 대한 요청이 발생함
    • 리다이렉트방식으로 F5를 누르면 이번엔 B로 요청발생

redirect vs. forward예시

예시1: 로그인 후 페이지 이동 (redirect)

  • 네이버에서 비로그인상태로 검색 이용
  • 상단 메일 버튼 누름
  • 로그인 페이지로 연결됨
  • ID/PW 입력
  • 로그인버튼누름
  • 메일 페이지로 넘어감
  • 메일 페이지에서 F5 -> 메일페이지가 나와야함
  • 로그인에서 성공하고 메일페이지로 가는 방식 -> 리다이렉트
    • 로그인 성공 후 리다이렉트로 응답데이터가 하나 전송
    • 그 응답데이터 헤더의 로케이션에 메일 페이지 주소를 심어져있음
    • 그럼 브라우저에서 헤더에 있는 메일 페이지로 새로운 요청을 보냄
    • 브라우저 주소는 메일 페이지가 남아있겠지 -> 그럼 역시 새로고침해도 메일페이지
  • 만약 디스패치방식으로 갔다면?
    • 클라이언트의 주소에는 여전히 로그인을 하기위해 사용했던 주소가 남아있음 - 메일페이지가 뜨기는 떴더라도 새로고침을 하더라도 로그인 페이지가 나오게됨

예시2: 회원 가입 (redirect)

  • 가입 버튼 클릭
  • 가입 양식 출력
  • 가입에 필요한 정보 입력 후 가입하기 버튼 클릭
  • 모든 정보가 서버쪽으로 전송
  • 서버에서는 DB에 저장해서 회원으로 만듬
    • 이 순간 가입하겠다는 명령에 대한 처리는 전부 끝남
    • 그럼 request에 들어있던 개인정보는 남아있을 필요없음
  • 최종적으로 가입에 성공했다면 클라이언트에게 로그인 페이지를 줘야함
    • 가입이 완전히 끝남 = 가입하기위해 가지고 있던 정보는 없애도 됨
    • 그걸 없애고 최종적으로 로그인 페이지로 가기위해서 리다이렉트로 가야함

예시3: 가입에 실패할 경우 (forward)

  • 가입 양식 전송함
  • 하지만 서버에서 확인해보니 중복아이디 -> 가입불가한 상황
  • 다시 가입FORM 페이지
    • 아이디만 중복이된거지 나머지 데이터는 전부정상
    • 나머지 데이터는 다시 입력해야할 필요없음
  • 가입하다가 실패했을때는 가입양식으로 다시보내야한다 -> FORWARD
    • 아직 가입처리가 완료가 되지않았다 == RQUEST를 아직 다 못써먹었다 == REQUEST에는 아직 가입을 위한 데이터들이 남아있고 가입이 아직 안끝났으니까 살려둬야함
    • 이래야 클라이언트가 귀찮게 또 입력안하지

CalculateServlet

if(MimeType.HTML == mime) {
  String view = "/WEB-INF/views/calculate.jsp";
  req.getRequestDispatcher(view).forward(req, resp);
//resp.sendRedirect(req.getContextPath() + view);
}

모델2: 요청은 서블릿, 응답은 jsp가 처리

  • jsp: 요청을 직접적으로 받을 필요 없기 때문에 주로 /WEB-INF/ 밑에 위치
  • 서블릿: /WEB-INF 밖에 있으면서 웹에서 요청을 받을수 있음, 명령에 대한 처리 후 모델 데이터를 만듬, 그 모델데이터를 jsp에 넘겨줘야함,
  • 서블릿->jsp(/WEB-INF)로 가야하는 상황
  • forward 사용 이유
    • 모델2에서 뷰단으로 넘겨야하는 데이터를 request 스코프에 담아갈 수 있음
  • redirect 사용 불가 이유
    • /WEB-INF/views: 서버에서만 접근할 수 있는 경로
    • /WEB-INF 밖이라 하더라도 응답 나가는 순간 요청데이터 사라지기때문에 사용할 수 없음
    • 이때의 최소한의 스코프는 session
  • inlcude 굳이 안쓰는 이유
    • 되긴 되는데 쓸 이유가 없음
    • 서블릿에서는 ui가 만들어지지 않기 때문에 다시 돌아올 필요가 없음



로그인 & 로그아웃

loginForm.jsp

  • <form id="loginForm" action="<%=request.getContextPath() %>/login/loginProcess.do" method="POST">
    • action을 번역하는 건 브라우저 -> 컨텍스트패스 필요(클라이언트사이드 경로)
    • 보안이 필요한 요청 -> POST
  • attr vs. prop
    • attr: 문자열로 관리하는 속성에 접근
    • prop: boolean값 속성

LoginProcessServlet.java

LogoutServlet.java

  1. HttpSession session = req.getSession();
  2. session.removeAttribute("authMember");
  • 로그아웃 상태로 바뀌는 게 아닌 로그아웃상태가 된 것 처럼 보이는 것일 뿐
    • 만약에 로그인 후, 세션 스코프에 필요한 데이터를 넣어두었다면 로그아웃 시에 그 데이터를 전부 remove 하고 authmember 를 지운 후 세션을 만료 시켰어야함
  1. session.invalidate(); (세션 만료시키기)
  • 세션 스코프 안 모든 attribute를 하나 하나 다 지워준 후 현재 세션을 만료시킴
  • 만료시키면서 각 세션을 식별하는 세션 id도 없애줌

index.jsp

  • a 태그를 통해서 post 방식으로 요청 발생시키기
    • 요청 방식 단일화
function clickHandler(event){
  event.preventDefault(); // a태그 원래 기능 상실시키기 

  /*
   * parameter로 들어온 event : MouseEvent
   * 모든 이벤트는 자기를 발생시킨 target의 레퍼런스를 가지고있다
   * 이 event의 target: a
   * a의 dataset (dataset은 map, data어트리뷰트를 그대로쓰게되면 데이터타입이 유지안되고 문자열로만 관리가된다. -> 이게싫으면 jquery사용)
   * dataset의 href: 아래 a태그 data-href에서 온 것
   */

  let href = event.target.dataset["href"];
  let logoutForm = document.logoutForm;
  logoutForm.action = href;
  logoutForm.submit();

  return false;
}
<!-- a태그로 post요청 발생시키기 위해 만든 input태그 없는 서버전송용 form -->
<form name="logoutForm" method="post"></form>
<a onclick="clickHandler(event)"
   data-href="<%=request.getContextPath()%>/login/logout.do"
   href="#"> 로그아웃</a>



코드 유의사항

validation 시점 = 전송 하기 전!

  • 1) 데이터 입력시
    • 각각의 input 태그에 change 이벤트
  • 2) 정말로 전송하기 바로직전
    • form 태그 대상으로 validation 수행

1. 클라이언트 사이드 검증

2. 서버 사이드 검증

  • null 체크 및 validation 체크 따로 해줘야함

과제

  • 서버사이드 validation
  • python regex
profile
갈 길이 멀다

0개의 댓글