728x90

Real Mysql

real mysql 책을 읽으면서 스터디 한 내용을 정리하고자 한다.
일단 11.1 부터 11.3까지의 내용만을 정리했다.
내가 사용하는 애플리케이션에서 특정 데이터를 테이터베이스에 저장하거나 조회를 할 때
SQL이라는 문장을 사용해야 한다.

데이터베이스의 테이블이나 구조를 변경할때는 DDL(데이터 정의 언어)

테이블의 데이터를 조작을 위한 언어는 DML(데이터 조작 언어) 이다.

SQL작성 규칙은 mysql의 서버 시스템 정책에 따라 바뀔 수 있다.
이 정책은 데이터베이스에 어떤 테이블의 데이터들이 들어가지 않았을 때 설정하는 것이 중요하다.

영문 대소문자 구분

Mysql에서는 설치된 운영체제에 따라서 대소문자를 구분하는데,
DB의 테이블이 디스크의 디렉토리나 파일로 매핑이 되기 때문이다.
윈도우의 명령 프롬프트에서는 대충 디렉토리를 대소문자 구분하지 않고
Tap키를 눌러 자동완성을 시키면 그냥 그 알파벳에 맞는 디렉토리를 자동완성 시킨다.
반면에 유닉스 계열에서는 대소문자를 구분해서 대문자로 시작하는 디렉토리를 소문자부터 눌러서 Tap키를 누르면 찾지를 못한다.
그래서 운영체제를 옮기면서 db를 이관할 경우 문제가 생길 수 있기 때문에

Mysql 설정 파일에 lower_case_table_name 시스템 변수를 설정해주면 된다.

Mysql 예약어

데이터베이스 테이블에 예약어와 겹치는 키워드로 생성하는 경우
역따옴표나 큰따옴표로 감싸주어야 한다.
근데 이 감싸주는 행동 때문에 애를 먹을 수 있다.
단순 조회에서도 에러가 나올텐데 이 에러가 상세 정보를 나타내주는 것이 아니라 문법 오류라고만 띄워준다고 한다.
테이블을 생성해주어야 할 때에도 역따옴표를 넣지않고 생성을 해보다가 에러를 맞는 방법이 좋을것 같다.
그리고 무엇보다 최선의 방법은 예약어 키워드와 같은 테이블을 만들지 않는것이
가장 좋은 방법이다.

문자열

나는 이 문자열이 좀 신기했는데,
자동으로 다른 칼럼으로 형변환해서 비교한다는게 조금 신기했었다.

SELECT * FROM Member
WHERE number = '123';

위와 같이 정수형인 컬럼에 문자열로 데이터를 조회하면
조건에 해당하는 저 문자열만 숫자로 자동 형변환이 들어가게 되니까 성능상 문제는 존재하지 않는다.
하지만 역으로 문자열 컬럼이지만 숫자데이터만 저장되어있는 경우에

SELECT * FROM Member
WHERE zipcode = 10001;

우편번호를 형식만 숫자인 문자열로 저장했다고 했을 때 숫자형으로 조건을 검색하면

zipcode에 해당하는 값을 전부 형변환하면서 하나씩 탐색하기 때문에

형변환에 대한 리소스를 많이 잡아먹는다. 이렇게 비교하는건 좋지 않다.

그리고 zipcode가 보편적으로 숫자가 99% 이겠지만, 만약 문자가 들어간게 하나라도 있었다면 위의 조건은 에러를 뱉게 될 것이다.

DATE

이부분은 따로 뗴어져서 있었지만, 마찬가지로 위에서 봤던것 처럼
이 날짜부분도 자동으로 형변환이 된다.
그래서 문자를 Date형식으로 치환하는 어떤 함수를 쓰지 않아도 된다.
그리고 문자열로 조회한다고 해서 인덱스를 못타는 것도 아니다.

Boolean

나는 이부분을 보자마자 바로 tinyint(1) 을 떠올렸다.
true는 1, false는 0으로 나타내주지만,
이것을 정수형 변수에 넣어도 동작한다.
대신 false는 딱 0만 표현이 되는데,
true라고 해서 1 이상의 값들을 표현해주지는 못한다.
그래서 사용할거라면 tinyint(1)로 제한해서 쓰는게 좋을것 같다고 봤다.

더 많은 상태가 필요하다면 Enum을 사용하는게 바람직하다고 생각한다.

Like 연산자

이 연산자를 통해서 정규표현식을 사용하는 연산자보다는 좀 넓은 범위로 검색할 수 있는데 대신 인덱스를 사용할 수가 있다.

  • Like에서 사용하는 와일드카드
    • % : 0 또는 1개 이상의 모든 문자에 일치하는지
    • _ : 정확히 1개의 문자 일치

이 와일드카드들을 직접 문자열에 넣어서 탐색하고 싶다면

ESCAPE를 추가해서 검색하면 된다.

~로 시작하는 칼럼을 찾는 데에는 인덱스 레인지 스캔을 적용해서 탐색하는게 빠르지만,
~로 끝나는 칼럼을 찾는곳에서는 인덱스의 left-most 특성으로 인덱스 풀스캔을 진행하게 된다.
mysql의 B-Tree 인덱스를 이용한 검색은 100% 일치 또는 값의 앞부분(Left-most)만 일치하는 경우에 사용할 수 있다.

Between 연산자

위의 이미지는 real mysql에서 가져온 이미지이다.
왼쪽이 Between 연산, 오른쪽이 In 연산이다.
특정 조건이 명확하게 보이는경우엔 In 연산자를 적용해주는 것이 훨씬 빠를것이다.
둘다 같은 데이터를 조회할 수는 있지만 범위를 지정하기 때문에 인덱스를 타지 않고 해당 조건을 쭉 조회하게 될 것이다.

다시 설명하면, 값이 불분명한 범위내에서 검색을 해야하면 Between을 사용해야 하지만, 명확한 경우라면 In절을 사용하는것이 훨씬좋다는것

Mysql 내장함수

여기서 다른 JSON에 대한 특정 문법들에 대한 내용도 나오지만,
쓸일이 많이 없을것 같아서 읽기만 했고 제대로 봤던건

NOW, SYSDATE의 차이

이 두개는 나는 자바를 엮어서 생각했다.
아마 그 부분이 맞을거라고 생각한다.

SELECT NOW(), SLEEP(2), NOW();
SELECT SYSDATE(), SLEEP(2), SYSDATE();

NOW는 한 명령에 대해 동일한 시간을 가지고 2초를 지나서 데이터를 출력해주니까 값이 같다.
반면, SYSDATE는 한 명령이 아니라 그 자체의 함수가 있을때마다 즉각적으로 실행을 하기 때문에 두 값에 차이가 있다.
이게 이해가 잘 안된다면 아래의 자바 코드로 생각해보면 될 것 같다.

public class Demo {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        Thread.sleep(2000);
        System.out.println(now);

        System.out.println(LocalDateTime.now());
        Thread.sleep(2000);
        System.out.println(LocalDateTime.now());
    }
}

이 두개 방식의 차이이다.

그래서 조건식에 현재 시간을 여러번 넣어야하는 경우라면 NOW()를 쓰고

자바에서는 위쪽에 한번 선언한것으로 전부 넣어서 조회를 해주어야 조건이 제대로 동작할 것이다.

정리

11.3장이 MYSQL의 내장함수 설명부분이라 특정 함수들이 많아서
읽는데에 조금 분량이 많았던 것 같다.
다 같이 같은 공간에서 한번에 읽고 토론하는 시간을 가지니까
몰랐던부분도 이해하게 되고 집단지성으로 이게 이런의미구나! 라는걸 가져갈 수 있는 장점이 있다고 생각한다.
개발자에게 있어서 이 책은 2장이 더 괜찮을거라는 추천들 때문에 2장부터 보지만, 더 나아가서는 1장도 봐야 이해가 더 쉬울거라고 본다.

728x90

'CS > 데이터베이스' 카테고리의 다른 글

Mysql 인덱스  (1) 2023.12.21
쿼리 개선 2  (0) 2022.08.11
728x90

사용자가 프로그램을 실행시키면 메모리에 올라가며 프로세스가 실행된다.
지금의 컴퓨터는 수많은 프로세스들이 실행된다.
시분할 시스템이 사용되는 운영체제에서는 여러개의 프로세스를 돌아가면서 실행한다.
cpu가 병렬적으로 여러 프로세스를 막 실행시키는것이 아니라,
한 순간에 하나의 프로세스만 처리가 가능하다.
그렇지만, 그 속도가 우리가 눈치챌 수도 없을 만큼의 속도로 분할되어 실행되기
때문에 여러 프로세스가 동시에 실행되는것 처럼 느끼게 한다.
프로세스는 시분할 시스템 처리를 위한 5가지의 상태가 존재한다.

  • 생성

    • 이 상태는 PCB를 생성하고, 메모리에 프로그램 적재를 요청한 상태
    • 메모리에 프로그램 적재를 승인받으면 준비상태로 넘어간다.
  • 준비

    • CPU를 사용하기 위해 기다리고 있는 상태
    • 준비 상태의 프로세스는 CPU 스케줄러에 의해 CPU가 할당
    • 대부분의 프로세스가 이 상태에 존재함.
  • 실행

    • CPU스케줄러에 의해 CPU를 할당 받아 실행되는 상태
    • 실행 상태에 있는 프로세스의 수는 CPU의 개수만큼
    • 이 상태에 있는 프로세스도 CPU를 무한정 쓸 수 있는것이 아니라 할당된 시간만큼만 사용이 가능하다.
    • CPU스케줄러는 할당된 시간을 초과하면 할당했던 CPU를 강제로 뺏는다.
      • 이 때, 프로세스는 다시 준비 상태로 되돌아간다.
  • 완료

    • 프로세스가 종료된 상태
    • 프로세스가 사용했던 데이터들을 메모리에서 제거한 후 생성된 PCB도 제거한다.
  • 대기

    • 프로세스가 입출력요청이 있으면, 완료될 때까지 기다리는 상태
    • CPU는 굉장히 빠른데 비해 입출력은 굉장히 느린작업에 속함.
    • 특정 프로세스가 입출력 요청을 한다면 요청이 완료될 때까지 CPU를 기다리게 하는것은 굉장히 비효율적이기 떄문에 입출력 요청을 한 프로세스를 이 상태에 두고 다른 프로세스에게 CPU를 할당함.
    • 시간이 지나, 입출력이 완료되면 이 대기상태에게 CPU할당 기회를 준다.
    • 이렇게 되면, CPU에게는 미안하지만 쉬는 시간을 주지 않고 빡세게 굴릴 수 있다.
  • 출처

728x90

'CS > 운영체제' 카테고리의 다른 글

운영체제 3강  (0) 2022.08.22
운영체제 2강 - 2  (0) 2022.08.18
운영체제 2강 - 1  (2) 2022.08.11
운영체제 1강  (0) 2022.08.11
728x90

이진 트리 순회

불과 반년전만 해도 이름만 들었지 마냥 먼곳에 있다고 생각했던 자료구조들이다.
근데 공부하면서 깨닫는 것은 뭐를 알아야 준비를 하고 공부도 하고
재밌게 문제도 풀 수 있다는 것이다. 그것이 바로 코딩테스트 😱
DFS니 BFS니 하려면
일단 스택, 큐, 배열, 재귀에 대해서 알아야된다고 생각했다.
물론 그리고 지금 포스팅하는 이 이진 트리에 대해서도 좀 짚고 넘어가야 한다고 봤다.

이진트리란?

이진트리는 각각의 노드가 아래 자식 노드를 최대 두개를 가진 트리 자료 구조이다.

이진트리 예시

위 이미지는 위키백과 에서 가져와봤다.
깊이(depth)는 3이고 크기는 9인 이진트리이다.

     1
  2     3
4  5   6  7

이런식으로 구성된 트리가 있을 때 전위 표기식으로 순서를 나타내는 알고리즘을 구성해보자

코드

public class Main {
    private static class Node {
        private int value;

        private Node left;
        private Node right;

        public Node(int value) {
            this.value = value;
            left = right = null;
        }
    }

    private static void dfs(Node n) {
        if (n == null) {
            return;
        }

        System.out.print(n.value + " ");
        dfs(n.left);
        dfs(n.right);
    }

}

자기 자신의 노드 그리고 left, right의 자식 노드를 알고있어서 재귀로 다음 노드를 호출하며

null인 경우에는 바로 return을 해주어 바로 다음 로직으로 이동하게끔 구현이 되었다.

전위 순회로 출력하게 되면 1 2 4 5 3 6 7 순서로 나오게 된다.

728x90

'CS > 자료구조' 카테고리의 다른 글

자료구조  (0) 2022.08.10
728x90

선택 정렬 (Select Sort)

선택 정렬은 현재 위치에 들어갈 데이터를 찾아 선택하는 알고리즘이다.
오름차순을 기준으로 정렬한다.

개념

제자리 정렬의 알고리즘 중 하나이다.
정렬 되지 않은 입력된 배열 외에 다른 메모리를 사용하지 않는다.
해당하는 n번째에 넣을 정렬된 원소 자리는 이미 정해져있고,
어떤 값을 넣을지를 선택하는 알고리즘이다.

동작 과정

  1. 주어진 배열에서 최솟값을 찾는다.
  2. 그 최솟값을 배열의 맨 앞의 수와 자리를 교체해준다.
  3. 맨 처음 값을 뺀 나머지 배열로부터 최솟값을 찾는다.
  4. 교체한 다음 맨 앞의 배열과 값을 바꿔준다.
  5. 이 과정을 정렬이 완료될 때까지 계속 반복한다.

스크린샷 2022-02-07 오후 10 19 41

보기 좋은 예시 이미지를 가져와봤다.
이제 그러면 구현을 해보도록 하자.

Select Sort 구현

n 길이를 가진 배열을 생성하고 다음줄에 n개의 숫자를 입력받아 선택정렬 한다.

public class SelectionSort {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine()); //길이가 n
        StringTokenizer st = new StringTokenizer(br.readLine());

        int[] arr = new int[n]; //n개의 숫자를 넣을 배열

        for (int i = 0; i < n; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }

        final int[] results = solution(arr);

        for (int result : results) {
            System.out.print(result);
        }
    }

    private static int[] solution(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }

            //최소값과 해당 반복 index의 맨 앞자리와 치환
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
        return arr;
    }
}

결론

이런 사소한 지식이라도 안적어두면 까먹고 또 기억이 안나는것 같다.
위의 예시도 ide도움 없이 손코딩으로 포스팅을 올려보는데 더 상기되서 까먹지 않을것 같다.
계속 까먹기 때문에 이렇게 기록으로 남겨두는것이 좋을듯 하다. 😎

728x90

'CS > 알고리즘' 카테고리의 다른 글

에라토스테네스의 체  (0) 2022.08.09
728x90

자료구조

자료 구조의 사전적인 의미는,
효율적인 접근 및 수정을 가능케하는 자료의 조직, 관리, 저장을 의미한다.
그래서 이 자료구조는,
데이터들의 값 모임, 데이터간 관계 들을 의미한다.
이 사전적 의미를 보니까 알고리즘과 뗄래야 뗄 수가 없는거 같다.
결국 이 선택에 따라 효율적으로 알고리즘을 설계를 할 수 있으니까 말이다.

들어가며

이 자료구조들은 당연히 여러 가지가 있으며, 각각의 자료구조는 각자의 연산과 목적에 맞춰져 있다.

단순히 알고리즘 문제들만 풀 때 자료구조를 선택한다? 답은 NO

어떠한 기능을 설계함에 있어 자료구조를 선택하는 것은 필수일 것이다.
자꾸 예를 알고리즘으로 들어서 그렇지만, 이만큼 알고리즘과 뗄래야 뗄 수가 없다는것.
자료구조가 명확해지면, 그에 따라오는 알고리즘이 반드시 필요한게 있을 거라고 본다.

종류

자료의 특성, 크기, 사용법, 연산에 따라 여러가지 종류가 있다.
크게 단순 구조, 선형 구조, 비선형 구조, 파일 구조로 나눌 수 있다.

스크린샷 2022-02-01 오후 9 42 40

단순 구조

  • True/False, 정수, 실수, 문자 및 문자열과 같이 컴퓨터가 기본적으로 제공하는 자료형

선형 구조

  • Array(배열)
    • 가장 일반적인 구조
    • 메모리 상에 같은 타입의 자료가 연속적으로 저장
    • 자료값을 나타내는 가장 작은 단위
  • LinkedList
    • 노드를 하나의 단위로 한다.
    • 노드는 자료와 다음 노드를 가리키는 참조값으로 구성
    • 점 조직 같은 느낌
  • Stack
    • 후입선출(Last-In-First-Out)
    • 먼저 저장된 것이 마지막에 나오게 되는구조
    • 자료의 나열 순서를 바꾸고 싶다면 스택에 넣었다가 꺼내면 역순으로 변경된다.
  • Queue
    • 선입선출(First-In-First-Out)
    • 먼저 저장된 것이 먼저 나오게 되는 구조
  • Deque
    • 양쪽에서 넣기 빼기를 할 수 있는 구조

비 선형 구조

  • Graph
    • 꼭짓점과 꼭짓점을 잇는 변으로 구성된다.
  • Tree
    • 뿌리와 뿌리 또는 다른 꼭짓점을 하나의 부모로 갖는 꼭짓점들로 이루어진 구조
    • 부모와 자식의 관계는 변으로 표현

파일 구조

하드디스크 같은 보조 기억장치에 저장되는 파일에 대한 자료구조
메모리에 한번에 로드할 수 없는 대용량의 자료
파일 구성 방식에 따라 순차, 색인, 직접으로 나뉘게 된다.

728x90

'CS > 자료구조' 카테고리의 다른 글

이진트리  (0) 2022.08.10
728x90

# 클라이언트 식별과 쿠키

이 장에서는 서버가 통신하는 대상을 식별하는데에 사용하는 기술을 알아본다.

## 개별 접촉

HTTP는 익명으로 사용하며 상태가 없고 요청(Request)과 응답(Response)로 통신하는 프로토콜

현대의 웹 사이트들은 개인화된 서비스들을 제공하고 싶어한다.

### 개별 인사

개인에게 맞춰져 있는 것처럼 느끼게 하려고 사용자에게 특화된 환영 메세지나 페이지 내용을 만듦

### 사용자 맞춤 추천

고객의 흥미가 무엇인지 학습해서 고객이 좋아할 만한 상품을 추천해준다.

개개인의 기념일이나 생일이 다가오면 그에 맞는 상품을 제시할 수도 있다.

### 저장된 사용자 정보

배송지 주소와 카드 정보를 매번 입력받게 하지말고

데이터베이스에 저장하여 저장하는 경우를 말한다.

### 세션 추적

HTTP 트랜잭션은 상태가 없다.

각 요청, 응답은 독립적으로 일어난다.

사용자가 사이트와 상호작용 할 수 있게 사용자의 상태를 남기는데,

여러 상태들을 유지하려면, 웹 사이트는 HTTP 트랜잭션을 식별할 방법이 필요하다.

- 사용자 식별 관련 정보를 전달하는 HTTP 헤더들
- 클라이언트 IP 주소 추적으로 알아낸 IP 주소로 사용자 식별
- 사용자 로그인 인증을 통한 사용자 식별
- URL에 식별자를 포함하는 뚱뚱한 URL
- 식별 정보를 지속해서 유지하는 쿠키

## HTTP 헤더

| 헤더 이름 | 헤더 타입 | 설명 |
|:------------|:-------|-------------------------|
| From | 요청 | 사용자의 이메일 주소 |
| User-Agent | 요청 | 사용자의 브라우저 |
| Referer | 요청 | 사용자가 현재 링크를 타고 온 근원 페이지 |

> From 헤더

사용자의 이메일 주소를 포함

고유한 이메일 주소를 갖기 때문에 이론상 From헤더로 사용자를 식별할 수 있다.

악의적 서버가 이 이메일 주소들을 모아 스팸메일을 발송할 수 있는 문제가 있다.

로봇이나 스파이더는 본의 아니게 웹 사이트에 문제를 일으킨 경우, 항의 메일을 보낼 수 있도록

From헤더에 이메일 주소를 기술한다고 함

> User-Agent 헤더

사용자가 쓰고 있는 브라우저의 이름과 버전정보, 등등을 서버에게 알려준다.

이는 특정 브라우저에게 특화된 컨텐츠를 최적화하는데 도움을 줄 수 있지만,

특정 사용자들을 식별하는 데는 큰 도움이 되지 않는다.

- 헤더 예시

<img width="904" alt="스크린샷 2022-01-08 오후 1 36 08" src="https://user-images.githubusercontent.com/74235102/148631546-27fa5967-75df-4055-b7aa-a8041352bf65.png">

> Referer 헤더

사용자가 현재 페이지로 유입하게 한 웹페이지의 URL을 가리킨다.

<img width="220" alt="스크린샷 2022-01-08 오후 1 45 45" src="https://user-images.githubusercontent.com/74235102/148631796-b615f35b-9b08-40c7-86dc-75d69e2bbf69.png">

이 헤더로 이전에 어떤 페이지를 방문했었는지 알 수 있다.

`왜?` - 여기까지 들어오기 직전의 URL을 파악할 수 있기 때문에 유추할 수 있게 된다.

---

하지만 이 세가지 헤더로 확실하게 뭔가를 식별하기엔 정보가 부족함.

## 클라이언트 IP 주소

사용자가 확실한 IP 주소를 가지고 있고, 그 주소가 바뀌지 않고, 웹 서버가 요청마다

클라이언트 IP를 알 수 있다면 문제없이 동작한다.

### 약점

**클라이언트 IP 주소는 사용자가 아닌, 사용하는 컴퓨터를 가리킴.**

여러 사람이 이용하는 경우 그들을 식별할 수 없다.

**인터넷 서비스 제공자는 동적으로 IP주소를 할당**

그렇기 때문에 사용자를 IP 주소로 식별할 수 없음

**보안을 강화하고 부족한 주소들을 관리하려고 NAT 방화벽을 통해 인터넷을 사용함.**

클라이언트의 실제 IP 주소를 방화벽 뒤로 숨기기 때문에 식별할 수 없음

**HTTP 프락시와 게이트웨이는 원서버에 새로운 TCP 연결**

이렇게 되면 실제 IP주소가 아닌 프락시의 IP주소를 보게 됨

## 사용자 로그인

IP 주소로 식별하는 수동적 방식보다,

웹 서버는 사용자 이름과 비밀번호 인증을 요구하여 명시적으로 식별할수 있다.

`WWW-Authenticate`, `Authorization` 헤더를 사용하여 사용자 이름을 전달하는 체계를 갖고 있음.

자세한 내용은 12장에서 다룰 예정

## 뚱뚱한 URL

어떤 웹 사이트는 사용자의 URL마다 버전을 기술하여 사용자를 식별하고 추적했다.

> 뚱뚱한 URL이란?

사용자의 상태 정보를 포함하고 있는 URL

사용자와 관련된 정보를 찾아서 밖으로 향하는 모든 하이퍼링크에 정보를 포함하기 때문에

뚱뚱한 URL이 되고,

이 뚱뚱한 URL은 심각한 문제들이 있다.

### 못생긴 URL

브라우저에 보이는 뚱뚱한 URL은 새로운 사용자에게 혼란을 준다.

### 공유하지 못하는 URL

당연한 얘기인것은, 이 뚱뚱한 URL에 사용자에 관련된 정보들이 포함되어 있다.

그렇기에 공유하는 순간 내 개인정보들도 같이 공유한다는 것이 된다.

### 캐시를 사용할수 없음

URL로 만드는 것은, 계속해서 요청되는 URL이 변경되기 때문에 기존 캐시에 접근할 수 없다.

### 서버 부하 가중

서버는 뚱뚱한 URL에 해당하는 HTML 페이지를 다시 그려야 한다.

### 이탈

URL에 정보들이 추가된것만 사용해야 문제없이 동작한다.

하지만 중간에 사용자가 이탈하게 되면, 진행상황들이 다 리셋이 되는 경우가 발생할 것이다.

### 세션 간 지속성의 부재

특정 URL을 저장해놓지 않는 이상은, 로그아웃하게 되면 정보를 전부 잃는것이 된다.

## 쿠키

쿠키는 사용자를 식별하고 세션을 유지하는 방식 중, 현재 가장 널리 사용하는 방식

쿠키는 넷스케이프에서 개발했지만, 지금은 모든 브라우저에서 지원한다.

쿠키는 캐시와 충돌할 수 있어서, 대부분의 캐시나 브라우저는 쿠키에 있는 내용물을

캐싱하지 않는다.

### 쿠키의 타입

쿠키는 세션쿠키, 지속쿠키 두가지 타입이 존재

세션 쿠키 - 사용자가 브라우저를 닫으면 삭제되는 쿠키

지속 쿠키 - 삭제되지 않고 더 길게 유지될 수 있는 쿠키

두개의 차이점은 **파기되는 시점**

파기까지 남은 시간인 `Expires` 또는 `Max-Age` 파라미터가 없다면 세션 쿠기가 된다.

### 쿠키 동작

사용자가 웹 사이트에 방문하면, 웹사이트는 서버가 사용자에게 할당한 값들을 모두 읽을 수 있다.

쿠키는 임의의 이름=값 형태의 리스트를 가지고, `Set-Cookie` or `Set-Cookie2(확장 헤더)`와 같은 HTTP 응답 헤더에 기술되어

사용자에게 전달 된다.

### 쿠키 상자: 클라이언트 측 상태

쿠키의 기본은 브라우저가 서버 관련 정보를 저장하고, 사용자가 해당 서버에 접근할 때 마다

그 정보를 함께 전송하게 하는 것

브라우저가 쿠키 정보를 저장할 책임이 있는데 이게 클라이언트 측 상태 = `HTTP 상태 관리 체계`

#### 구글 크롬 쿠키

<img width="1226" alt="스크린샷 2022-01-13 오후 10 59 56" src="https://user-images.githubusercontent.com/74235102/149343821-0261788e-579d-4551-9965-bfc04e3f5625.png">

### 각 사이트마다 다른 쿠키

브라우저는 수백 수천 개의 쿠키를 가지고 있을 수는 있지만,

브라우저가 쿠키 전부를 모든 사이트에 보내지는 않는다.

1. 모두 전달하면 성능이 크케 저하
2. 특정 서버에 특화된 이름=값 쌍을 포함하기 때문에 인식하지 않는 무의미한 값 존재
3. 특정 사이트에서 제공된 정보를 다른 사이트에서 가져갈 수 있어 개인적인 정보 문제 존재

#### 쿠키 도메인 속성

`Set-cookie: user="lsj8367"; domain="sprout.or.kr"`

`sprout.or.kr` 도메인에 `user="lsj8367"`을 전달한다라는 의미

#### 쿠키 Path 속성

Path 속성으로 해당 경로쪽에 속하는 페이지만 쿠키를 전달하게 하는 속성

## Version 0 쿠키

넷스케이프 쿠키

Set-Cookie 속성

- 이름=값
- **필수 속성**
- 이름, 값 둘다 큰따옴표로 감싸지 않은, `;`, `,`, `=`, 공백 을 포함하지 않는 문자열
- Expires
- 선택적 속성
- 쿠키의 생명주기를 가리키는 날짜 문자열
- 이 일자에 다다르면 그 쿠키는 삭제됨
- 사용할 수 있는 타임 존 = GMT
- 형식 : `요일, DD-MM-YY HH:MM:SS GMT`
- 명시하지 않으면 사용자 세션이 끝날 때 파기
- Domain
- 선택적 속성
- 속성에 기술된 도메인을 사용하는 호스트만 쿠키를 전송
- 명시되어 있지 않다면, `Set-Cookie` 응답을 생성한 서버의 호스트명을 사용
- Path
- 선택적 속성
- 서버에 있는 특정 URL만 쿠키 할당
- 경로를 명시하지 않으면, `Set-Cookie` 응답을 전달하는 URL의 경로 사용
- Secure
- HTTP가 SSL 보안 연결을 사용할 때만 쿠키 전송

## Version 1 쿠키

Set-Cookie2 속성

- 이름=값
- **필수 속성**
- `$` 는 예약된 문자이므로 쿠키 이름은 `$`로 시작하면 안된다.
- Version
- **필수 속성**
- 쿠키 명세 버전을 가리키는 정수 값
- Comment
- 선택적 속성
- 서버가 쿠키를 사용하려는 의도 기술
- 인코딩 반드시 UTF-8
- CommentURL
- 선택적 속성
- 쿠키 사용 목적과 정책에 대해 상세하게 기술된 URL 링크 제공
- Discard
- 선택적 속성
- 이 속성이 있다면, 클라이언트 프로그램 종료될 때 클라이언트가 해당 쿠키를 삭제
- Domain
- 선택적 속성
- 기술된 도메인에 해당하는 서버 호스트들에게만 쿠키 전송
- Max-Age
- 선택적 속성
- 쿠키 생명주기 `초 단위`
- 클라이언트는 HTTP/1.1 수명 계산 규칙에 따라 수명을 계산해야 한다
- Path
- 선택적 속성
- 서버에 있는 특정 문서에만 쿠키 할당
- Version 0 과 동일
- Port
- 선택적 속성
- 값 없이 속성의 키워드만 기술할 수 있고, 포트를 한개 이상 콤마를 이용하여 구분 기술할 수 있음
- Secure
- HTTP가 SSL 보안 연결을 사용할 때만 쿠키가 전송

## 쿠키와 세션 추적

쿠키는 웹 사이트에 수차례 트랜잭션을 만들어내는 사용자를 추적하는데 사용한다.

## 쿠키와 캐싱

쿠키 트랜잭션과 관련된 문서를 캐싱하는 것을 주의해야 한다.

> 이유?

이전 사용자의 쿠키가 다른 사용자에게 할당되거나, 개인정보까지도 노출이 될 수 있다.

### 캐시를 다루는 기본 원칙

**캐시되지 말아야 할 문서가 있다면 표시해라**

문서가 `Set-Cookie` 헤더를 제외하고 캐시해도 되는 경우라면,

그 문서에 명시적으로 `Cache-Control: no-cache="Set-Cookie"` 를 기술하여 명확히 표시한다.

캐시를 해도 되는 문서에 `Cache-Control: public` 을 사용하면 웹의 대역폭을 더 절약시켜준다.

**Set-Cookie 헤더를 캐시 하는 것에 유의하라**

같은 `Set-Cookie` 헤더를 여러 사용자에게 보내게 되면, 사용자 추적에 실패할 것

어떤 캐시는 `Set-Cookie` 헤더를 응답 저장전에 제거한다.

이런 문제를 방지하기 위해서 모든 요청마다 캐시가 원 서버와 재검사를 시켜 `Set-Cookie` 헤더 값을 주어

이 문제를 개선할 수 있다.

`Cache-Control: must-revalidate, max-age=0`

**Cookie 헤더를 가지고 있는 요청을 주의하라**

요청에 Cookie 헤더와 같이 넘겨지면, 결과가 개인정보를 담고 있을 수 있다.

## 쿠키, 보안 그리고 개인정보

쿠키를 사용하지 않도록 비활성화도 가능하기 때문에, 이 자체가 보안상으로 위험하다고 할수는 없다.

개인정보를 다루거나 사용자를 추적하는 기술은 잘못된 의도로 사용할 수 있기 때문에 주의하여야 한다.

**가장 큰 오용중 하나는 사용자 추적을 위한 지속 쿠키**이다.

개인 정보를 누가 받는지 명확하게 파악하고, 개인정보 정책을 유의한다면

위험성 보다는 세션 조작이나 트랜잭션상 편리함이 크다.

728x90

+ Recent posts