[책] 객체지향의 사실과 오해
유스케이스
사용자의 목표를 달성하기 위해 사용자와 시스템 간에 이뤄지는 상호 작용의 흐름을 텍스트로 정리한 것
가치
사용자들의 목표를 중심으로 시스템의 기능적인 요구사항들을 이야기 형식으로 묶을 수 있음.
특성
- 유스케이스는 사용자와 시스템 간의 상호작용을 보여주는 텍스트임.
- 유스케이스는 하나의 시나리오가 아니라 여러 시나리오들의 집합임.
- 유스케이스는 단순한 기능 목록과 다름.
- 기능들을 유스케이스로 묶고 상호작용 흐름 속에서 기능들을 포함하는 이야기를 제공함.
- 유스케이스는 사용자 인터페이스와 관련된 세부 정보를 포함하지 말아야 함.
- 유스케이스는 내부 설계와 관련된 정보를 포함하지 않음.
재료 합치기
- 도메인 모델: 안정적인 구조 개념화
- 유스케이스: 불안정한 기능 서술
변경에 유연한 소프트웨어 만들기: 유스케이스에 정리된 시스템의 기능을 도메인 모델을 기반으로 한 객체들의 책임으로 분배해야 함.
-> 책임-주도 설계 적용
유스케이스 -> 사용자에게 제공할 기능을 시스템의 책임으로 보게 함으로써 객체 간의 안정적인 구조에 책임 분배
도메인 모델 -> 기능을 수용하기 위해 은유할 수 있는 안정적인 구조 제공
책임-주도 설계 -> 유스케이스로부터 첫 번째 메시지와 사용자가 달성하려는 목표, 도메인 모델로부터 기능을 수용할 수 있는 안정적인 구조를 제공받아 실제로 동작하는 객체들의 협력 공동체 창조
안정적인 도메인 모델
- 도메인 모델이 안정적인 이유
- 도메인 모델을 구성하는 개념은 비즈니스가 없어지거나 완전히 개편되지 않는 한 안정적으로 유지됨.
- 도메인 모델을 구성하는 개념 간의 관계는 비즈니스 규칙을 기반으로 하기 때문에 비즈니스 정책이 크게 변경되지 않는 한 안정적으로 유지됨.
-> 도메인 모델을 중심으로 객체 구조를 설계하고 유스케이스의 기능을 객체의 책임으로 분배하는 기본적인 객체지향 설계 방식의 유연함을 잘 보여줌.
객체지향 설계의 상호 연관 관점
개념 관점
도메인 안에 존재하는 개념과 개념들 사이의 관계를 표현함.
-> 실제 도메인의 규칙과 제약을 최대한 유사하게 반영하는 것이 핵심
클래스가 도메인 개념의 특성을 최대한 수용하면 변경을 관리하기 쉽고 유지보수성을 향상시킬 수 있음.
명세 관점
인터페이스와 구현을 분리해야 함.
-> 구현과 관련된 세부 사항이 드러나지 않도록 해야 함.
구현 관점
객체의 책임을 '어떻게' 수행할 것인가에 초점을 맞추며 인터페이스를 구현하는 데 필요한 속성과 메서드를 클래스에 추가함.
-> 메서드와 속성이 철저하게 클래스 내부로 캡슐화돼야 한다는 것을 의미
도메인 개념을 참조하는 이유
변경이 발생했을 때 코드를 좀 더 수월하게 수정하길 원하기 때문에 소프트웨어 클래스가 도메인 개념을 따르면 변화에 쉽게 대응할 수 있음.
[강의] 모든 개발자를 위한 HTTP 웹 기본 지식
전송 방식
- 단순 전송
- 압축 전송: 압축해서 전송
- 분할 전송: 몇 바이트씩 분할하여 전송
- Transfer-Encoding 사용, 대신 Content-Length 사용 금지
- 범위 전송: 데이터에 범위를 정하여 전송
일반 전송
- From: 유저의 에이전트의 이메일 정보
- Referer: 이전 웹 페이지 주소
- User-Agent: 유저 에이전트 애플리케이션 정보
- Server: 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
- Date: 메시지가 발생한 날짜와 시간
특별한 정보
- Host: 요청한 호스트 정보(도메인)
- 하나의 IP 주소에서 여러 도메인이 적용되어 있을 때 구분하기 위해 사용됨.
- Location: 페이지 리다이렉션
- 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동
- Allow: 허용 가능한 HTTP 메서드
- Retry-After: 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
인증
- Authorization: 클라이언트 인증 정보를 서버에 전달
- WWW-Authenticate: 리소스 접근시 필요한 인증 방법 정의
- 401 Unauthorized 응답과 함께 사용
쿠키
- 쿠키 정보는 항상 서버에 전송됨
- 네트워크 트래픽이 유발될 수 있으므로 최소한의 정보만 사용해야 함. (세션 id, 인증 토큰)
생명주기
- Set-Cookie: expires=시간GMT
- Set-Cookie: max-age=3600(초)
- 세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
- 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지
도메인
- Set-Cookie: domain=example.org
- 명시: 명시한 문서 기준 도메인 + 서브 도메인 포함
- example.org와 dev.example.org 접근 가능
- 생략: 현재 문서 기준 도메인만 적용
- example.org에서만 쿠키 접근 가능, dev.example.org 접근 불가능
경로
- Set-Cookie: path=/home
- 해당 경로를 포함한 하위 경로 페이지만 쿠키 접근
- 일반적으로 path=/로 지정
보안
- Secure
- 쿠키는 http, https를 구분하지 않고 전송
- Secure를 적용하면 https인 경우에만 전송
- HttpOnly
- XSS 공격 방지
- 자바스크립트에서 접근 불가(document.cookie)
- HTTP 전송에만 사용
- SameSite
- XSRF 공격 방지
- 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송
검증 헤더와 조건부 요청
- 캐시 유효 기간이 초과해서 서버에 다시 요청하면
- 서버에서 기존 데이터를 변경했거나
- 기존 데이터를 변경하지 않은 경우가 생김.
- 캐시 만료 후에도 서버에서 데이터를 변경하지 않았다면 저장한 캐시를 재사용할 수 있음.
- 이때 클라이언트가 가진 데이터와 서버의 데이터가 같다는 사실을 확인해야 함. -> Last-Modified
- 가지고 있는 캐시 데이터의 최종 수정일과 서버의 데이터 최종 수정일과 같은 지 다른 지 확인 -> If-Modified-Since
-> 최종 수정일이 같다면 304 Not Modified 코드와 HTTP 헤더만 전송
단점
- 1초 미만 단위로 캐시 조정이 불가능함.
- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우 한 번 더 다운로드 받게 됨.
- 서버에서 별도의 캐시 로직을 관리할 수 없음.
-> ETag(Entity Tag): 캐시용 데이터에 임의의 고유한 버전 이름을 달아둠.
- 데이터가 변경되면 이름을 변경함.
- 이름이 같으면 유지, 다르면 다시 다운로드
- ETag를 전송하는 헤더는 If-None-Match임.
캐시와 조건부 요청 해더
캐시 제어 헤더
- Cache-Control: 캐시 지시어(directives)
- max-age: 캐시 유효 시간, 초 단위
- no-cache: 데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용
- no-store: 데이터에 민감한 정보가 있으므로 저장하면 안됨 (메모리에서 사용하고 최대한 빨리 삭제)
- Expires: 캐시 만료인 지정(하위 호환)
- 캐시 만료일을 정확한 날짜로 지정
- Cache-Control: max-age 권장 (같이 사용되면 expires 무시)
- 검증 헤더 (Validator)
- ETag: "v1.0", ETag: "adf8jiov"
- Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT
- 조건부 요청 헤더
- If-Match, If-Not-Match: ETag 값 사용
- If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용
프록시 캐시
- 클라이언트와 가까운 어딘가에 프록시 캐시 서버를 설치함.
- 클라이언트는 캐시를 이용할 때 프록시 캐시 서버를 지나야 함.
- 프록시 캐시 서버에 있는 캐시를 public 캐시, 클라이언트에 있는 캐시를 private 캐시라고 함.
- Cache-Control: public
- Cache-Control: private
- 응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
- Cache-Control: s-maxage
- Age: 60 (HTTP 헤더)
- 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)
캐시 무효화
캐시 무효화 응답을 하기 위해선 다음과 같은 헤더를 전부 넣어야 함.
- Cache-Control: no-cache
- 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용
- Cache-Control: no-store
- 데이터에 민감한 정보가 있으므로 저장하면 안됨.
- Cache-Control: must-revalidate
- 캐시 만료 후 최초 조회시 원 서버에 검증함.
- Pragma: no-cache
- HTTP 1.0으로 요청이 오는 경우도 있기 때문에 넣어야 함.
no-cache vs must-revalidate
no-cache의 경우 원 서버와 통신이 단절된 경우 프록시 서버에 남아있는 오래된 데이터를 가져오는 경우가 있음.
하지만 중요한 정보의 경우 어떤 데이터로 대체하기 보다는 에러를 확실히 띄우는게 맞음.
그러므로 must-revalidate를 사용하여 504 Gateway Timeout을 띄우도록 해야 함.
[강의] 스프링 MVC 1편 - 백엔드 웹
자바 웹 기술 역사
과거 기술
- 서블릿 - 1997
- JSP - 1999
- HTML 생성은 편리하지만, 비즈니스 로직까지 너무 많은 역할 담당
- 서블릿, JSP 조합 MVC 패턴 사용
- MVC 프레임워크 춘추 전국 시대 - 2000년 초 ~ 2010년 초
- MVC 패턴 자동화, 복잡한 웹 기술을 편리하게 사용할 수 있는 다양한 기능 지원
- 스트럿츠, 웹워크, 스프링 MVC(과거 버전)
현재 사용 기술
- 애노테이션 기반의 스프링 MVC 등장
- @Controller
- MVC 프레임워크의 춘추 전국 시대 마무리
- 스프링 부트의 등장
- 스프링 부트는 서버를 내장
- 과거에는 서버에 WAS를 직접 설치하고, 소스는 War 파일을 만들어서 설치한 WAS에 배포
- 스프링 부트는 빌드 결과(Jar)에 WAS 서버 포함 -> 빌드 배포 단순화
최신 기술 - 스프링 웹 기술의 분화
- Web Servlet - Spring MVC
- Web Reactive - Spring WebFlux
- 특징
- 비동기 넌 블러킹 처리
- 최소 쓰레드로 최대 성능 - 쓰레드 컨텍스트 스위칭 비용 효율화
- 함수형 스타일로 개발 - 동시처리 코드 효율화
- 서블릿 기술 사용X
- 단점
- 기술적 난이도 매우 높음
- RDB 지원 부족
- 일반 MVC의 쓰레드 모델도 충분히 빠름.
- 실무에서 아직 많이 사용하지는 않음.
HTML을 편리하게 생성하는 뷰 기능
- JSP
- 프리마커(Freemarker), Velocity(벨로시티)
- 타임리프(Thymeleaf)
- 내추럴 템플릿: HTML의 모양을 유지하면서 뷰 템플릿 적용 가능
- 스프링 MVC와 강력한 기능 통합
- 최선의 선택, 단 성능은 프리마커, 벨로시티가 더 빠름.