복습

1. request

2. response

3. out

4. session

  • 통로 : 두 피어 사이에 유일하게 개방된 연결, 하지만 브라우저 이용하며 서버와 나사이의 연결 끊으라고 한적 없기때문에 웹에서는 애매한 의미
  • 기간 : 한 클라이언트가 하나의 브라우저를 이용해서 어플리케이션 사용 시작 이벤트를 발생시킨 후, 종료 이벤트를 발생시킬 때까지의 기간

세션의 생명주기

  1. 클라이언트의 최초요청(ⓐ)으로 인해 세션이 하나 만들어지고, ID가 부여된다.
  2. 서버에서 클라이언트로 응답데이터(ⓑ)를 내보낸다.
  • 이 때 응답데이터(ⓑ)에 세션ID가 숨어서 함께 나간다
  • ID는 클라이언트가 직접 필요로 하는 데이터가 아니기때문에, 바디가 아닌 헤더에 담겨 나간다 (setCookie)
  1. 브라우저가 응답데이터(ⓑ)를 받아 헤더의 cookie를 확인한 후 자신의 쿠키 저장소에 쿠키를 보관한다
  • 쿠키저장소는 브라우저마다 따로따로 가지고 있다.
  1. 새로운 요청(ⓒ)이 발생할 때, 쿠키는 ID로 리퀘스트의 헤더에 함께 전송된다.
  2. 요청을 받은 WAS가 요청(ⓒ)에 ID가 포함되어있다는 것을 알고 최초요청이 아니라는 것을 판단한다. 그 후 서버가 가지고 있던 세션ID들과 비교하여, 요청이 특정 세션에서 발생한 요청인 것을 파악한다.
  3. 이를 통해 클라이언트와 서버 사이에 세션ID라는 공통점이 생기게 된다 -> 상태가 유지될 수 있는 구조가 만들어짐
    상태 유지하기 위한 방법의 차이점: 세션은 서버에 쿠키는 브라우저(클라이언트)에!

예시: 비회원의 멜론 재생목록

  • 로그인 하지 않은 상태에서, 재생목록을 만들어놓고 나중에 다시 방문했을 때 그대로 재생목록이 남아있게 하려면 어떻게할까?
    • db에 저장하는 방법이 가장 쉽지만 부하 걸리기 쉬움
    • -> 브라우저의 쿠키에 저장할 수 있음!
  • 쿠키에 저장하는 것의 문제점
    • 1) 재생목록은 단순한 문자열이 아닌데 쿠키에 문자열로 어떻게 저장해?
      • -> json데이터로 마셜링,직렬화 후 이렇게 저장된 저장목록을 서버에서 역직렬화, 언마셜링하여 복원함
    • 2) 한 사이트에서 동시에 저장할 수 있는 쿠키의 갯수와 용량은 제한되어있음
    • 3) 클라이언트가 가지고있는 정보이기때문에 클라이언트가 언제든지 지울수있음 (언제까지 살아있으리라는 보장을 할 수 없음)
    • 4) 보안에 취약함 (누구나 볼 수 있음)

세션 트래킹모드로서 쿠키의 단점

  • 한번 로그인을 하면 브라우저 쿠키에 세션ID가 들어있게됨 = 브라우저 쿠키를 지우게 되면 세션 유지가 불가능함
  • 서버사이드에서는 이때 발생한 요청을 새로운 요청으로 판단하고 새로운 세션id가 만듬

5. Servlet Context

  • 서블릿 컨텍스트: 서블릿이 운영되고 있는 환경
    • 서블릿 컨텍스트 = 어플리케이션 정보 + 서버정보
      • 어플리케이션 없이 서블릿 존재할수 없음!
      • 서버 없이 어플리케이션 존재할 수 없음!
    • context: 한 컴포넌트가 운영되고 있을 때 그 컴포넌트가 운영되고있는 환경에 대한 정보
  • Servlet Context 사용 목적
    • dynamic web module version 확인 (서블릿스펙정보)
    • 서버에 직접적인 로그 남기기
    • ★★ web resource 확보
      • 모든 자원은 파일의 형태로 존재하기때문에, 파일에 접근하기 위해서는 원칙적으로 파일시스템상 경로가 필요함
      • 하지만 서버가 갖는 독베이스가 어디냐에 따라 파일 시스템상 경로는 다르기때문에 파일시스템 상 절대경로를 알 수없음
      • 절대경로를 알기위해서는 독베이스 기반으로 계산해서 알아야함
      • ServletContext는 이를 위한 메서드를 지원해줌 => getRealPath, getResource, getResourceAsStream

6. page

7. config

8. exception

9. pageContext ★★★

  • 나머지 기본객체에 대한 getter를 가졌기때문에 중요
  • pageContext 하나 있으면 다 꺼내쓸수있다~!!!
    • pageContext.getRequest()
    • ((HttpServletRequest) pageContext.getRequest()).getContextPath()
    • ${pageContext.request.contextPath}
      • el에서도 pC있으면 장땡
  • getter라는 기능이 없다면 1) scope제어 2) 흐름제어 3) 에러데이터 확보라는 기능도 있을 수 없음



Scope

  • scopeDesc.jsp
  • SCOPE(영역): 속성(attribute) 데이터를 공유하기 위해 정의된 4가지 저장 영역
  • 모든 객체의 관리권한은 컨테이너만 가지고있다
    • -> 전역변수를 서로간에 접근할 수 없다
    • -> 단점보완하는것이 스코프
  • 예시
    • ImageListServlet.java
      • dataMap이 스코프의 역할을 해주던것
    • CalculateServlet.java
      • 요청은 서블릿이 받고 응답은 jsp에서 나가는 모델2구조jsp에 데이터 전달하기 위해, req.getRequestDispatcher(view).forward(req, resp); 방식 이용 -> 가장 최소한의 영역 스코프 이용
  • 스코프는항상 생명주기와 연계해서 이야기가 되어야함

1. page Scope

  • pageContext 라는 기본객체가 관리하는 맵
  • 한 페이지 내에서만 공유되는 영역
    • 한 페이지에서만 쓸 수 있기 때문에 공유의 의미에서 살짝 벗어나 있음
  • 커스텀태그 만들 때 주로 사용함

2. request Scope

  • request 가 관리하는 Map<String, Object>
  • request와 생명주기 동일
  • ⓐ ---리다이렉트---> ⓑ : request사라짐, 이때는 request Scope보다 큰 영역 필요

3. session Scope

  • seesion 이 관리하는 Map<String, Object>
  • session과 생명주기 동일
  • 한 사람의 유저가 자기만의 데이터를 넣기 위한 저장 공간
  • 서로의 세션 스코프에 접근할 수 없음

4. application Scope

  • servletContext가 관리하는 Map<String, Object>
  • servletContext와 생명주기 동일
  • 하나의 어플리케이션은 사용하고있는 모든 클라이언트가 동시에 접근할 수 있는 영역
  • 가장 큰 공유범위이기때문에 '부하'를 신경써서 접근해야함
  • 경우에 따라서는 스코프에 속성 데이터를 넣을 수도 있지만, 부하를 줄이기 위해서는 속성데이터를 지울 수도 있음 (removeAttribute)

객체 생성 방법

점층적 생성자

JavaBean

  • ValueObject, DataTransferObject, Model: 한가지 객체의 상태를 온전히 담기 위한 것
  • JavaBean 규약에 따라 정의된 재사용 가능한 객체
  • JavaBean 요건
    • 1) 상태 유지를 위한 property
    • 2) 캡슐화
    • 3) 캡슐화된 property에 접근하기 위한 인터페이스 제공
    • 4) 상태비교 방법 제공 (equals)
      • 캡슐화 되어있는 상태정보를 가지고 있는 객체가 여러개라면, 상태 비교를 통해 동일객체를 판단할 수 있어야함
    • 5) 상태확인 방법 제공 (toString)
    • 6) 상태기록 방법 제공 (serialize)
  • 계층형 아키텍쳐(layered architecture ≒ mvc)
    • layer: controller - service - dao처럼 하나의 역할을 가지고 일하는 애들
    • layer 간에 데이터 이동이 있어야함
    • 낱개의 데이터를 하나의 객체로 만들 때 vo를 사용

Builder패턴

  1. private으로 묶인 전체 생성자가 필요
  2. private인 생성자를 쓸 수 있는 이너클래스 필요
  3. 반드시 빌더에는 build라는 메서드가 하나 있어야함
  4. 빌더 안에 빌드의 대상이 되는 객체와 같은 상태인 property가 있어야함
  5. 마치 setter의 역할을 가지고 있는 것처럼 현재 가지고 있는 상태와 이름이 동일한 메서드를 완성, 그리고 그 메서드 안에서 상태를 결정한다. (return 타입이 존재해서 체인구조가 가능)

bts 페이지 문제

구성

  • btsForm.jsp
    • bts멤버의 목록을 클라이언트에게 제공 (목록 보여주는 ui)
    • 클라이언트가 한명을 선택하고나면 그다음 화면이 해당 멤버의 개인페이지가 보여야함
  • BtsServlet.java
    • 요청받는 서블릿
      • 누구의 개인페이지로 갈것인지 요청 처리해서 해당 멤버jsp로 보내줘야함

조건

  • ui구성 단계에서부터 모델2구조 사용할것
  • btsForm 으로 올때 get, btsForm이 전송될때 post -> 서블릿 1개로 해결
  • bts데이터는 맵으로 관리하여 서블릿에서 jsp로 보내 꺼내쓸 수 있도록 만들기

해결

  1. btsDB를 위한 map을 init시 제일 먼저 만들기 위해 WebServlet 어노테이션에 속성값 부여 loadStartup
  • loadonstartup = -1: 최초요청이 들어와야 생성됐던 것
  • loadonstartup = 1 : 바로 생성ㄱ
@WebServlet(urlPatterns="/bts", loadOnStartup=1)
public class BtsServlet extends HttpServlet{
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		System.out.println(this.getClass().getSimpleName()+"초기화됨.");
		Map<String, BtsVO> btsDB = new LinkedHashMap<>();
		getServletContext().setAttribute("btsDB", btsDB);
		btsDB.put("B001", BtsVO.getBuilder().code("B001").name("뷔").url("/bts/bui.jsp").build());
		btsDB.put("B002", BtsVO.getBuilder().code("B002").name("제이홉").url("/bts/jhop.jsp").build());
		btsDB.put("B003", BtsVO.getBuilder().code("B003").name("지민").url("/bts/jimin.jsp").build());
		btsDB.put("B004", BtsVO.getBuilder().code("B004").name("진").url("/bts/jin.jsp").build());
		btsDB.put("B005", BtsVO.getBuilder().code("B005").name("정국").url("/bts/jungkuk.jsp").build());
		btsDB.put("B006", BtsVO.getBuilder().code("B006").name("RM").url("/bts/rm.jsp").build());
		btsDB.put("B007", BtsVO.getBuilder().code("B007").name("슈가").url("/bts/suga.jsp").build());
	}
}

과제

1. model2 구조로 webStudy01 컨텍스트 익스플로러 구현

  • 서버 사이드 리소스 대상으로 익스플로러 구현
  • 파일 복사, 이동 삭제 구현
    • 선택 -> 삭제: 정말 지울거야?
    • 드래그 앤 드랍: 이동
    • 컨트롤 + 드래그 앤 드랍: 파일복사
  • https://github.com/mar10/fancytree
    • try live demo 보면서 api 활용

2. 회원가입

  • email, 이름, 패스워드 입력받아서 crud 모듈 완성
  • 모델1이든 모델2든 상관없음
  • db는 사용하지말되 layered architecture 사용해볼것
  • vo 설계
  • 왜 db대신 쓰는 애를 map으로 쓸까?? map이 뭐가 이뻐서..?

어떻게 풀까나

  • 모델2
    • 회원가입양식 jsp
      • 가입양식 form, post 로 action은 해당 url로 매핑된 서블릿에서 doPost로 받아줄것
      • jsp 서블릿 둘다 클라이언트, 서버 밸리데이션
    • 가입처리하는 서블릿
      • 성공시? redirect 로 웰컴페이지
      • 실패시? forward로 다시 가입양식페이지, 남겼던 정보가 그대로 보여야겠지? -> scope 범위?
  • vo: email, 이름, 패스워드 (pk를 뭘로잡을건지?)
    • 빌더 패턴활용
    • application scope
    • 중복체크에도 써야겠지
  • layered architecture?
    • 각 기능, 책임 분리
    • dao, service 전부 나누라는 말씀이실까
    • util이나 메서드로 빼는정도만 해도되지않을까
  • 신경써야할것
    • 책임분리, 밸리데이션, scope, 흐름제어, vo

숙제용 프로젝트 복사 시 설정변경

  • xml설정 webStudy01부분을 homework로 바꿔줄 것 (컨텍스트패스 중복 방지)
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
    <wb-module deploy-name="webStudy01">
        <wb-resource deploy-path="/" source-path="/WebContent" tag="defaultRootSource"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/res"/>
        <property name="context-root" value="webStudy01"/>
        <property name="java-output-path" value="/webStudy01/build/classes"/>
    </wb-module>
</project-modules>
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
    <wb-module deploy-name="homework">
        <wb-resource deploy-path="/" source-path="/WebContent" tag="defaultRootSource"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/res"/>
        <property name="context-root" value="homework"/>
        <property name="java-output-path" value="/homework/build/classes"/>
    </wb-module>
</project-modules>

3. 싱글톤을 thread-safety하게 만드는 방법

4. 어댑터 패턴 조사

  • FileUploadRequestWrapper 참고
  • 첫번째 과제에 적용하면 좋을거얌..
profile
갈 길이 멀다

0개의 댓글