0118 - 0124
0118
스프링 웹 기초
- 정적 컨텐츠
- MVC와 템플릿 엔진
- API
정적 컨텐츠
- 톰캣 서버가 URI 요청을 받는다.
- 스프링 컨트롤러에서부터 해당 URI를 찾는다.
- resources 안에 있는 hello-static.html을 반환한다.
MVC와 템플릿 엔진
- 톰캣 서버가 URI 요청을 받는다.
- 스프링 컨트롤러에서부터 해당 URI를 찾는다.
- 컨트롤러에서 model에 키-값으로 URI에서 받은 파라미터를 뷰 리졸버에 보낸다.
- 뷰 리졸버에서 Thymeleaf 템플릿 엔진 처리하여 return할 html을 찾아 렌더링 해준다.
API
@ResponseBody
를 사용하면 뷰 리졸버로 던지지 않고 HttpMessageConverter이 동작- 반환 타입이 문자면 HTTP의 BODY에 문자 내용을 직접 반환한다.
- 반환 타입이 객체면 객체가 JSON을로 변환된다.
0119
HTTP 상태코드
상태 코드
클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능
- 1xx (Informational): 요청이 수신되어 처리중
- 2xx (Successful): 요청 정상 처리
- 3xx (Redirection): 요청을 완료하려면 추가 행동이 필요
- 4xx (Client Error): 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
- 5xx (Server Error): 서버 오류, 서버가 정상 요청을 처리하지 못함
만약 모르는 상태 코드가 나타나면?
- 클라이언트가 인식할 수 없는 상태코드를 서버가 반환한다면 클라이언트는 상위 상태코드로 해석해서 처리한다.
1xx (Informational) - 요청이 수신되어 처리중
- 거의 사용하지 않음
2xx (Successful) - 클라이언트의 요청을 성공적으로 처리
200 OK
- 요청 성공
201 Created
- 요청 성공해서 새로운 리소스가 생성됨
- 생성된 리소스는 응답의 Location 헤더 필드로 식별
202 Accepted
- 요청이 접수되었으나 처리가 완료되지 않았음
- 배치 처리 같은 곳에서 사용
204 No Content
- 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음
- ex) 웹 문서 편집기에서 save 버튼
3xx (Redirection) - 요청을 완료하기 위해 유저 에이전트의 추가 조치 필요
리다이렉션
- 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동 (새로운 경로로 다시 요청)
- 영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동
- 일시 리다이렉션 - 일시적인 변경
- ex) 주문 완료 후 주문 내역 화면으로 이동
- 특수 리다이렉션 - 결과 대신 캐시를 사용
영구 리다이렉션
- 원래의 URL를 사용X, 검색 엔진 등에서도 변경 인지
- 301 Moved Permanently
- 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음
- 308 Permanent Redirect
- 301과 기능은 같으나 리다이렉트시 요청 메서드와 본문 유지
일시적인 리다이렉션
- 리소스의 URI가 일시적으로 변경
- 검색 엔진 등에서 URL을 변경하면 안됨
- 302 Found
- 리다이렉트 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음
- 307 Temporary Redirect
- 리다이렉트시 요청 메서드와 본문 유지
- 303 See Other
- 리다이렉트 요청 메서드가 GET으로 변경
PRG: Post/Redirect/Get
일시적인 리다이렉션 예시
- POST로 주문후에 웹 브라우저를 새로고침하면 다시 요청하여 중복 주문이 될 수 있다.
- POST로 주분후에 주문 결과 화면을 GET 메서드로 리다이렉트
- 새로고침해도 결과 화면을 GET으로 조회
- 서버에서도 중복 주문같은 일을 잘 막아줘야 한다.
기타 리다이렉션
- 300 Multiple Choices: 안 쓴다
- 304 Not Modified
- 캐시를 목적으로 사용
- 클라이언트에게 리소스가 수정되지 않았음을 알려줘서 클라이언트는 로컬PC에 저장된 캐시를 재사용
- 캐시로 리다이렉트 한다.
- 응답에 메시지 바디를 포함하면 안 된다.(로컬 캐시를 사용해야 하므로)
- 조건부 GET, HEAD 요청 시 사용
4xx (Client Error) - 클라이언트 오류
- 클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없음
- 오류의 원인이 클라이언트에 있음
- 클라이언트가 이미 잘못된 요청, 데이터를 보내고 있기 때문에, 똑같은 재시도가 실패함
400 Bad Request
- 클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음
- 클라이언트는 요청 내용을 다시 검토하고 보내야함
- ex) 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때
401 Unauthorized
- 클라이언트가 해당 리소스에 대한 인증이 필요함
- 401오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명
- 인증(Authentication): 본인이 누구인지 확인, (로그인)
- 인가(Authorization): 권한부여
403 Forbidden
- 서버가 요청을 이해했지만 승인 거부
- 주로 인증 자격 증명은 있지만, 접근 권한이 불충분한 경우
404 Not Found
- 요청 리소스를 찾을 수 없음
- 요청 리소스가 서버에 없거나 클라이언트가 권한이 부족한 리소스에 접근할 때 해당 리소스를 숨기고 싶을 때
5xx (Server Error) - 서버 오류
- 서버 문제로 오류 발생
- 서버에 문제가 있기 때문에 재시도 하면 성공할 수도 있음
500 Internal Server Error
- 서버 문제로 오류 발생, 애매하면 500 오류
503 Service Unavailable
- 서비스 이용 불가
- 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음
- Retry-After 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있음
0120
HTTP 헤더1 - 일반 헤더
HTTP 헤더
- HTTP 전송에 필요한 모든 부가정보
표현
- Representation = representation Metadata + Representation Data
- 표현 = 표현 메타데이터 + 표현 데이터
- 메시지 본문(message body)을 통해 표현 데이터 전달
- 메시지 본문 = 페이로드
- 표현은 요청이나 응답에서 전달할 실제 데이터
- 표현 헤더는 표현 데이터를 해석할 수 있는 정보 제공 -> 전송, 응답 둘 다 사용
Content-Type
- 표현 데이터의 형식 설명
- 미디어 타입, 문자 인코딩
- text/html; charset=utf-8
- application/json
Content-Encoding
- 표현 데이터 인코딩
- 표현 데이터를 압축하기 위해 사용
- 데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가
- 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제
- gzip
Content-Language
- 표현 데이터의 자연 언어
- ko
- en
Content-Length
- 표현 데이터의 길이
- 바이트 단위
- Transfer-Encoding을 사용하면 Content-Length를 사용하면 안됨
협상(콘텐츠 네고시에이션)
- 클라이언트가 선호하는 표현 요청
- 협상 헤더는 요청시에만 사용
- Accept: 클라이언트가 선호하는 미디어 타입 전달
- Accept-Charset: 클라이언트가 선호하는 문자 인코딩
- Accept-Encoding: 클라이언트가 선호하는 압축 인코딩
- Accept-Language: 클라이언트가 선호하는 자연 언어
협상과 우선순위
- Quality Values(q) 값 사용
- 0~1, 클수록 높은 우선순위, 생략 시 1
- Accept-Language: ko-KR,ko;q=0.9,en;q=0.8
- 구체적인 것이 우선
- 구체적인 것을 기준으로 미디어 타입을 맞춘다.
전송 방식
단순 전송
- 단순히 Content-Type과 Content-Length정도만 보낸다.
압축 전송
- Content-Encoding을 추가하여 압축해서 보낸다.
분할 전송
- Transfer-Encoding: chunked
- content-Length가 예상이 안 되기 때문에 보내면 안 된다.
범위 전송
- 요청 시 Range, 응답 시 Content-Range로 범위를 설정해서 보낸다.
0121
HTTP 헤더
일반 정보
From
- 유저 에이전트의 이메일 정보
- 일반적으로 잘 사용되지 않음, 검색 엔진 같은 곳에서, 주로 사용
- 요청에서 사용
Referer
- 현재 요청된 페이지의 이전 웹 페이지 주소
- Referer를 사용해서 유입 경로 분석 가능
- 요청에서 사용
User-Agent
- 유저 에이전트 애플리케이션 정보(웹 브라우저 정보 등)
- 어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능
- 요청에서 사용
Server
- 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보
- 응답에서 사용
Date
- 메시지가 발생한 날짜와 시간
- 응답에서 사용
특별한 정보
Host
- 요청한 호스트 정보(도메인)
- 하나의 IP 주소에 여러 도메인이 적용되어 있을 때 구분하기 위해 사용
- 필수
Location
- 3xx 응답 결과에 Location 헤더가 있으면, 그 위치로 자동 이동(리다이렉트)
- 201에서는 요청에 의해 생성된 리소스 URI
Allow
- 허용 가능한 HTTP 메서드
- 405(Method Not Allowed)에서 응답에 포함해야함
Retry-After
- 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간
- 503에러시 서비스가 언제까지 불능인지 알려줄 수 있음
인증
- Authorization: 클라이언트 인증 정보를 서버에 전달
- WWW-Authenticate: 리소스 접근시 필요한 인증 방법 정의
쿠키
- Set-Cookie: 서버에서 클라이언트로 쿠키 전달(응답)
- Cookie: 클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청시 서버로 전달
- HTTP는 무상태 프로토콜이기 때문에 클라이언트와 서버가 서로 상태를 유지하지 않는다.
- 쿠키 저장소에 모든 쿠키 정보들을 저장해두고 요청 시마다 모든 쿠키를 꺼내 함께 보낸다.
- 사용자 로그인 세션관리 및 광고 정보 트래킹에 사용
- 쿠키 정보는 서버에 항상 전송되어 네트워크 트래픽을 추가 유발하므로 최소한의 정보만 사용해야 한다.
- 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지 사용
쿠키 - 생명주기
- Set-Cookie: expires
- 만료일이 되면 쿠키 삭제
- Set-Cookie: max-age
- 0이나 음수를 지정하면 쿠키 삭제
- 만료 날짜를 입력하면 해당 날짜까지 유지
- 세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
- 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지 유지
쿠키 - 도메인
- domain
- 명시하면 명시한 문서 기준 도메인 + 서브 도메인까지 포함하여 쿠키 생성
- 생략 시 현재 문서 기준 도메인만 적용
쿠키 - 경로
- Path
- 이 경로를 포함한 하위 경로 페이지만 쿠키 접근
- 일반적으로 path=/ 루트로 지정
쿠키 - 보안
- Secure
- Secure를 적용하면 https인 경우에만 전송
- HttpOnly
- XSS 공격 방지
- 자바스크립트에서 접근 불가
- HTTP 전송에만 사용
- SameSite
- XSRF 공격 방지
- 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송
0122
script async와 defer의 차이점
node js에는 자바스크립트 엔진이 있어서 브라우저 없이도 자바스크립트를 실행 가능하다.
async vs defer
head 안에 스크립트 파일을 포함할 경우
- HTML파일을 파싱하다가 멈춰서 js파일을 다운하고 실행한 뒤 다시 HTML을 파싱한다.
- JS 파일이 클 경우 HTML을 보기까지 시간이 오래걸린다.
body 끝에 스크립트 파일을 포함할 경우
- HTML파일 파싱을 마치고 js파일을 다운하고 실행한다.
- js파일에 의존적인 웹사이트라면 사용자가 정상적인 페이지를 보기 전까지 js파일을 다운하고 실행하는 시간을 기다려야한다.
head + async
- HTML파일을 파싱하다가 js파일을 다운하는 시간동안은 계속 파일을 파싱하고, 모두 다운되면 그 때 멈춰서 js파일을 실행한 후 다시 파싱한다.
- 파싱되기도 전에 js파일이 실행 되기 때문에 원하는 요소가 아직 정의되지 않았을 수 있다.
head + defer
- HTML파일을 파싱하다가 js파일을 다운하면서 HTML파일은 끝까지 파싱한다. 그리고 파싱이 마치면 js파일을 실행한다.
- 가장 좋은 방법
'use strict';
- 자바스크립트는 매우 유연한 언어기 때문에 이 명령을 선언하게 되면 문법을 좀 더 엄격하게 에러로 잡아내 준다.
- 자바스크립트 엔진이 더 빠르게 자바스크립트를 분석할 수 있어서 성능 개선 효과도 있다.
0123
데이터 타입
Immutable data types vs Mutable data types
Immutable data types - primitive types, frozen objects
Mutable data types - all objects
변수
- 메모리에 읽고 쓰기 가능
global scope - 문서 전체에서 사용할 수 있는 범위
block scope - 블록 내부에서 선언하고 사용할 수 있는 범위
-> global scope범위의 변수를 최대한 줄여 주는 것이 좋다.
var
- var hoisting - 어디에 선언했냐에 상관없이 제일 위로 끌어올려준다.
- 블록 스코프를 무시한다. 블록 내부에 선언해도 밖에서도 호출 가능
- 선언되지도 않은 변수에 값을 할당하거나 호출할 수 있다.
-> var을 let으로 대체한다.
상수
- 메모리에서 읽기만 가능 선언함과 동시에 값을 할당하고, 다시는 값을 변경할 수 없다.
웬만하면 값을 할당한 다음 값이 변경되지 않는 데이터 타입을 사용해라
- 보안
- 스레드 안전성 - 다양한 스레드들이 변수에 접근하여 값이 변경된다면 위험할 수도 있다.
- 값을 변경할 이유가 없다면 const를 이용해서 코드를 작성하는 것이 좋다.
변수 타입
숫자 타입
- 자바 스크립트에서 숫자 타입은 모두 number 타입
- 특별한 number 타입
- const infinity = 1 / 0;
- const negativeInfinity = -1 / 0;
- const nAn = ‘not a number’ / 2;
문자 타입
- 하나의 글자든 여러 개의 글자던 모두 string 타입
- template literals - 백 틱을 이용하여 문자 타입과 변수를 쉽게 연결
- 백 틱 ` 사이에 문자를 집어 넣고 변수는 ${}사이에 입력한다.
불리언 타입
- false: 0, null, undefined, NaN, ‘’
- true: 다른 값들
null - null이라고 확실히 지정되어 있는 상태
undefined - undefined라고 지정되어 있거나, 선언만 되어있고 값이 들어갈지 아닐지 모르는 상태
symbol
- 맵이나 다른 자료구조에서 고유한 식별자가 필요하거나, 동시다발적으로 일어날 수 있는 코드에서 우선순위를 주고 싶을 때 쓰여지는 것
const symbol1 = Symbol('id');
const symbol2 = Symbol('id'); // 이 둘은 비교 연산자로 비교해보면 다르다. 문자열로 비교 x
const symbol1 = Symbol.for('id');
const symbol2 = Symbol.for('id'); // 문자열로 심볼 값을 주고 싶다면 Symbol뒤에 .for을 붙여준다.
console.log(`value: ${symbol1.description}` // 출력 시에는 뒤에 .description을 붙여줘서 값을 받아올 수 있다.
Dynamic typing
- 자바 스크립트는 런타임 시 변수의 타입을 확인하는 동적 타이핑 언어이다.
- string타입 + number타입 = string타입으로 자동 변환
- string타입(내용은 숫자) / string타입(내용은 숫자) = number타입으로 자동 변환
- Dynamic typing으로 인해 에러가 많이 발생한다.
-> string타입으로 이용했던 변수가 number타입으로 변하고 추후에 다시 charAt()으로 참조하는 경우
first-class function
- 함수도 다른 데이터 타입처럼 변수에 할당이 가능하고, 인자나 리턴 값으로도 함수 사용이 가능하다.
연산자
논리 연산자
- 논리 연산자에서는 무거운 표현식이나 함수 호출을 가장 뒤에 적어야 한다.
-> 앞에서 전체 결과가 확정되면 뒤에 연산은 실행하지 않아도 되기 때문이다.
비교 연산자
- ==, !=
- loose equality, 타입 변환 허용
- ===, !==
- strict equality, 타입 변환 비허용
const con1 = { name: "con" };
const con2 = { name: "con" };
const con3 = con1;
console.log(con1 == con2); // false - reference가 다르다.
console.log(con1 === con2); // false
console.log(con1 === con3); // true
console.log(0 == false); // true
console.log(0 === false); // false
console.log("" == false); // true
console.log("" === false); // false
console.log(null == undefined); // true
console.log(null === undefined); // false
Function
Function declaration
function name(param1, param2) {
// 내용
return;
}
- 하나의 함수는 하나의 기능만 가져야 한다.
파라미터
- 기본형 파라미터: passed by value
- 객체형파라미터: passed by reference
디폴트 파라미터
function showMessage(message, from = "unknown") {
//from 인자 값을 넣어주지 않으면 디폴트 값 설정
console.log(`${message} by ${from}`);
}
Rest 파라미터
- 파라미터를
...args
로 설정하면 가변 배열로 인자를 받을 수 있다.
Local scope
- 안에서는 바깥 범위의 변수를 호출할 수 있지만, 바깥에서 안에서 선언한 변수를 호출할 수는 없다.
early return
- if문을 작성할 때 if문 안에 들어갔을 때 여러 복잡한 상황들을 넣어 주는 것보다, if문에 들어갔을 시에 빠르게 return문을 실행해 주도록 조건문을 설정하고, 그 밑에 복잡한 상황들을 넣어주는 것이 더 좋은 코드이다.
Function expression
- function declaration 방식은 선언되기 이전에 함수를 호출할 수 있다. - 호이스팅
- 반면 function expression은 실행에 도달한 이후에 함수가 생성된다.
const print = function () {
//anonymous function
console.log("print");
};
print();
function expression을 이용한 콜백 함수
function randomQuiz(answer, printYes, printNo) {
if (answer === "love you") {
printYes();
} else {
printNo();
}
}
const printYes = function () {
console.log("yes!");
};
const printNo = function print() {
// named function - 디버깅할 때 이용
console.log("no!");
};
randomQuiz("love you", printYes, printNo);
Arrow function
- 항상 익명함수
const add = (a, b) => a + b;
const add = (a, b) => {
//do something
return; // 중괄호 있으면 리턴 필수
};
IIFE
- Immediately invoked function expression
- 함수를 정의함과 동시에 실행
(function hello() {
console.log("hello");
})();
0124
클래스
- class: 템플릿
- object: 클래스의 인스턴스
클래스 정의
class Person {
//생성자
constructor(name, age) {
//필드
this.name = name;
this.age = age;
}
//methods
speak() {
console.log(`${this.name}: hello!`);
}
}
- 클래스를 생성할 때는
const 변수이름 = new Person('name', 20);
과 같은 형식으로 생성한다.
게터와 세터
class User {
constructor(firstName, Lastname, age) {
this.firstName = firstName;
this.Lastname = Lastname;
this.age = age;
}
get age() {
return this._age;
}
set age(value) {
this._age = value;
}
}
- 변수에 사용자가 적절하지 않은 값을 입력하여 대입될 수도 있기 때문에 이를 방지하기 위해 게터와 세터 메서드를 정의한다.
- 게터와 세터 메서드를 설정하면 this.age를 호출하거나 this.age에 값을 대입할 때 자동으로 게터와 세터 메서드가 호출된다. 세터에서 똑같은 필드명을 사용하면 계속해서 세터를 호출하여 무한루프를 돌기 때문에 변수명 앞에 ‘_‘를 붙여준다.
- console.log로 필드를 호출할 수 있는 이유도 내부적으로 필드를 호출하면 자동으로 게터 메서드가 호출되기 때문이다.
public, private
- 필드나 메서드 앞에
#
을 붙이면 private 접근 제한자를 가지게 된다. 기본은 public. - private한 변수를 콘솔에 찍어보면 ‘undefined’가 나온다.
static 속성과 메서드
- 필드나 메서드 앞에
static
을 붙이면 각 오브젝트가 공통으로 공유하는 변수나 메서드가 된다. - static 필드나 메서드를 호출할 때는
클래스이름.
으로 호출해야 한다.