4월 21, 2022

에러 기록) WSL 늦게 켜지는 문제/ Code .

 가상 머신 또는 컨테이너에서 응답을 받지 못했기 때문에 작업 시간이 초과되었습니다.


[코드 4294967295 (0xffffffff)로 프로세스 종료됨]


Powershell에서 WSL을 실행하면 한~참 있다가 이 에러가 뜨고, 그 후에 WSL이 켜집니다.


https://gyunseo.com/devlog/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%9D%B4%EB%A6%84%EC%9D%84-%EC%B0%BE%EC%9D%84-%EC%88%98-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%BD%94%EB%93%9C-4294967295-0xffffffff%EB%A1%9C-%ED%94%84%EB%A1%9C/

해당 링크를 따라하니 이제 바로바로 켜지기는 하는데 이제는 code . 으로 vscode 여는 명령이 작동하지 않습니다....


https://www.reddit.com/r/vscode/comments/ilwkhi/cant_launch_vs_code_from_wsl2/

껐다키니깐 되네요 허헛... 


도커와 WSL 관련해서 자잘한 문제가 꾸준히 생기는데, 추후에 정리해서 한번에 포스팅하겠습니다.

4월 20, 2022

TIL)HTTP - Cache와 Cookie

 

Cache

HTTP캐시는 서버의 지연을 줄이기 위하여 주어진 웹 페이지 요소를 임시로 저장하는 기술입니다. 캐시 시스템은 이를 통과하는 문서들의 사본을 저장하며, 특히 이후에 필요할 것 같은 요소들을 저장합니다.


Cookie란

브라우저에 저장돼 있는 "{name} = {value}" pair입니다. 

브라우저는 Response의 Set-Cookie 헤더를 통해 Server에게 전달받은 값을 쿠키를 세팅할 수 있습니다.

이후 브라우저는 Requset의 Cookie 헤더를 통해 이 쿠키를 서버에게 보낼 수 있습니다




언뜻 보기에는 쿠키와 캐시 모두 정보를 저장하는 방법으로 보입니다. 


그러나 둘은 용도 및 성격의 차이점이 있습니다.

쿠키는 사용자의 PC를 인증하고, 커스터마이징 된 웹사이트를 구현하기 위해 존재합니다.

쿠키는 인증 정보 및 사용자의 활동과 성향을 트랙하기 위한 목적으로 고안됐습니다.

사용자가 웹사이트를 방문할 때, login정보와 개인정보 등을 쿠키에 담아서 전송합니다. 

웹사이트를 사용하면서 매번 로그인을 할 필요가 없는 이유는, 브라우저에 있는 쿠키를 이용하여 인증 절차를 대신하기 때문입니다. (매 request마다 쿠키가 서버로 보내집니다)

또한 개인정보의 경우, 유저의 선호사항 등이 담깁니다.

쿠키는 브라우저가 닫히면서 같이 삭제되거나, 일정 시간이 지난 이후 자동으로 expired(만료)됩니다

쿠키는 누구나 삭제 혹은 block할 수 있기에, 쿠키에 의존하는 웹 어플리케이션은 쿠키의 삭제 혹은 블록 이슈에 대해 취약합니다.


반대로 캐시는, 필요한 웹 페이지 리소스를  저장하는 방식입니다. 사실 메모리에 저장돼 있는 캐시 파일은 일종의 쿠키처럼 동작합니다. 

그러나, 쿠키와 다르게 캐시는 웹 페이지가 렌더링을 할 때, 이를 좀 더 빠르게 할 수 있게 도와주는 역할을 합니다. 

쿠키와 다르게 캐시는 유저가 수동으로 삭제해주기 전까지, 메모리에 남아있습니다. 




쿠키와 캐시의 차이점을 기록한 표입니다. 포인트들을 빨간색으로 체크해두었습니다.


참고

https://developer.mozilla.org/ko/docs/Web/HTTP/Caching

https://medium.com/@maheshlsingh8412/cookie-session-story-of-a-stateless-http-3cd09cc01541

https://www.quora.com/What-is-the-difference-between-cookies-and-cache

4월 19, 2022

TIL) HTTP 헤더 : Content-Type

 

HTTP 콘텐트 타입은 리소스의 미디어 타입을 나타내기 위해 존재합니다.

Media Type이란, 파일의 형식을 나타내기 위해 파일과 함께 보내지는 string입니다.

데이터를 받는 서버(request일때), 클라이언트(response일때)는 Content-Type을 보고 데이터의 형식을 파악하고, 이를 어떻게 처리할지 결정하게 됩니다.

예를 들어, 브라우저는 서버로부터의 Response를 보고, 여기의 Content-Type을 통해 컴퓨터에 보여줘야 하는 컨텐트의 타입을 알 수 있습니다. 


이때 브라우저는 MIME sniffing 이라는 작업을 수행하는데요.  

MIME은 "Multipurpose Internet Mail Extensions"의 약자입니다. 원래는 이메일에 있는 non-ASCII Text와 non-text binary를 정의하기 위해 고안됐다고 합니다.

현재, Mime standard에 있는 content-type들은 HTTP 프로토콜에서 request나 response의 컨텐트 타입을 파악하기 위해 쓰입니다.

브라우저는 바로 이 MIME 타입을 Content-Type을 보면서 파악합니다. (Content-Type은 MIME타입의 일부입니다)

개발자들은 Response 내용에 걸맞지 않는 Content-Type을 부여할 수 있습니다, 



사진은 자바스크립트 리소스에 text/plain 의 컨텐트 타입이 잘못 부여된 경우입니다.

브라우저는 이러한 경우에도 웹사이트가 의도대로 작동할 수 있도록 Content-Type이 잘못 표시된 리소스를 분석하여 렌더링 할 수 있습니다.

여기서 MIME Sniffing 이 사용됩니다. Content_Type에 의존하기보다, response의 content에 대해 직접 분석하여서 , 브라우저는 효과적으로 mime type을 Sniffing을 통해 알 수 있습니다. MIME Sniffing의 알고리즘은 브라우저마다 상이합니다.

 

X-Content-Type-Options

보안 이슈를 위하여 , 브라우저가 MIME Sniffing을 하지 않도록 서버의 HTTP Response header에 X-Content-Type-Option을 줄 수 있습니다. 

이 헤더의 유일한 값은 "nosniff"입니다. 

 

문법

type/subtype

type은 카테고리이며, subtype은 개별 혹은 멀티파트 타입입니다.


application/octet-stream

Content-Type에는 수많은 종류가 있습니다. 그 중 주목할만한 application/octet-stream에 대해 얘기해보겠습니다

8 비트(1바이트) 단위의 바이너리 데이터를 의미합니다(...?) 엄밀히 따지면 모든 컴퓨터 상 파일은 binary data이긴 합니다만...

이렇게 두루뭉술하게 표현한 이유는 , 특별히 표현할만한 프로그램이 존재하지 않는 경우에 octet-steam을 사용하기 때문입니다.

보통 브라우저는 해당 타입에 대해 유저에게 실행할지 묻거나, 실행하지 않는다고 합니다.

"Content-Dispostion" 헤더를 "attachment로 줌으로써 해당 데이터를 수신 받은 브라우저가 파일을 저장, 또는 다른 이름으로 저장여부를 설정하게 할 수 있습니다.

뭐라 정의하기 애매한 경우에 해당 Content-Type을 주는 듯 합니다.



참고

https://www.coalfire.com/the-coalfire-blog/mime-sniffing-in-browsers-and-the-security 

https://www.geeksforgeeks.org/http-headers-content-type/

https://pygmalion0220.tistory.com/entry/HTTP-Content-Type

http://www.webmadang.net/community/community.do?action=read&boardid=5001&page=1&seq=3

https://dololak.tistory.com/130

4월 18, 2022

TIL) 구글 코딩 인터뷰 풀이

 https://www.youtube.com/watch?v=XKu_SEDAykw&t=430 

해당 영상을 보고 풀이 과정을 기록한 코드입니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# 문제
# collection of numbers
# find matching pair equal to sum(given)
# [1,2,3,9]  sum 8
# [1,2,4,4]  sum 8
 
# 매칭 pair 없는 경우도 있음
# memory에 있고, ordered된 상태(ascending)
# repeating element? : 같은 인덱스에 있는 값 재활용 불가능
# 다른 인덱스에 같은 값은 나올 수 있음
# int, 마이너스도 가능
 
# nested for loop 사용 가능 i Loop과 i+1 Loop
# 그러나 O(n^2) 이기에 time consuming함 
 
# 1이라고 치면, 7을 찾으면 되는데.. sorted 돼있기에 binary search하면 된다
# log algorithm 
# 아직 좀 느림
 
ex = [1,2,3,4,4]
 
def binary_search(array, left, right, ele):
  if right >= left:
    mid = (left+right)//2
    if array[mid] == ele:
      return True
    elif array[mid] > ele:
      return binary_search(array,left,mid-1, ele)
    else:
      return binary_search(array,mid+1, right, ele)
  else:
    return False
    
def slightly_better_pair_sum(array,sum):
  for i in range(len(array)):
    comp=sum-array[i]
    if binary_search(array,i+1,len(array)-1,comp):
      return "yes"
  return "No"
 
# 단방향인 binary search보다 
# 가장 큰 sum은 마지막 두 값일 것임
# 가장 작은 sum은 첫 두 값
# 그러니깐, 첫번째 값보다 작은 것은 없고, 마지막 값보다 큰 것은 없음
# range를 가운데로 줄여가며 linear하게 접근
 
# binary search를 하게된다면, 각 element마다 binary search를 반복해야 하는 반면, 이렇게하면 한번의 흐름으로 끝남
 
# python으로 해보자
def findSumPair(array,sum):
  left = 0
  right = len(array)-1
  while right>left:
    if array[left] + array[right] == sum:
      return "yes"
    elif array[left] + array[right] < sum:
      left += 1
    else:
      right -= 1
  return "No"
 
 
# print(findSumPair([1,2,4,4],8))
# O(n) 의 시간 복잡도 
 
 
# sorted 돼있지 않다면? - error check
# sort 한 이후 해당 코드 반복
 
def SortPairSum(array,sum):
  array.sort()
  left = 0
  right = len(array) -1
  while right>left:
    if array[left] + array[right] == sum:
      return "yes"
    elif array[left] + array[right] < sum:
      left += 1
    else:
      right -= 1
  return "No"
 
# print(findSumPair([4,5,2,3,7],8))
 
# 개선점
# O(nlog n)의 시간복잡도
# O(n) 으로 돌아가기 위하여 
  # array를 가면서 만나는 요소를 딕셔너리에 넣음
  # 현재 요소의 complement(요소와 더해서 sum되는 것)없다는 것은
  # array를 loop하면서 현재 요소의 complement가 딕셔너리에 있는지 확인하고
  # 있으면 yes를 리턴
  # 없으면 no를 리턴하고 현재 element를 딕셔너리에 더함
 
def smartestPairSum(array,sum):
  dictionary = dict()
  for item in array:
    comp = sum - item
    if not comp in dictionary:
      dictionary[item] = True
    else:
      return "YES"
  return "No"
 
print(smartestPairSum([4,5,2,3,7],8))
# 더해서 sum이 되는
# complement1 , complment2이 있을때,
# 먼저 나온 complement1을 기록해두었다가, 이후에 complemnet2 가 나오면 딕셔너리에서 이를 찾아서 합이 되는 수가 있음을 return 하고 끝냄.
# array개수만큼 operation이 늘어나기에 O(n)임
cs

참조 : https://github.com/VicodinAbuser/ZTM-DS-and-Algo-Python/blob/master/venv/Scripts/How%20to%20solve%20coding%20problems/Google%20Interview%20Question.py 


4월 17, 2022

TIL) HTTP메서드 속성

 

1. 안전

: 계속해서 메서드를 호출해도 리소스를 변경하지 않습니다.

GET은 안전 속성을 가지고 있으나, POST,PUT,PATCH 등은 호출했을 때 리소스의 변경이 일어나기 때문에 안전하지 않습니다. 



2. 멱등 Idempotent  => f(f(x) = f(x)

: 호출의 건수와 상관 없이 호출 결과가 항상 동일합니다.

GET은 서버에서 리소스를 불러오는 메서드이기에 멱등합니다.

DELETE 요청을 여러번 하여도, 삭제된 결과 자체는 똑같기에 DELETE는 멱등합니다.

PUT의 경우, 리소스를 완전히 "덮어쓰는" 메서드이기 때문에 여러번 요청하여도 같은 값으로 덮어쓰기에 멱등합니다. 리소스를 매 요청시마다 갱신하기에 멱등성이 생기는 것입니다.

그러나 POST는 멱등하지 않습니다. 예를 들어, POST를 통해 이미지를 업로드 할때, 여러번 POST하게 되면 중복 업로드가 될 수 있습니다.

더 심각하게는, POST를 통해서 결제를 처리하는 상황을 생각해 볼 수 있습니다. 

- 클라이언트는 POST를 통하여 결제 요청을 보냅니다.

- 서버는 결제 요청을 받고, 결제 로직을 실행합니다. 

이때 결제를 3번 요청하게 된다면, 3번의 중복 결제가 이뤄질 것입니다. 클라이언트 입장에서는 한번의 결제를 원하겠지만, 클라이언트의 의도와 다르게 여러번 결제가 중복해서 일어났습니다. 이처럼 POST는 멱등하지 않습니다


PATCH의 경우도 리소스의 일부를 변경하는 작업이기에, 멱등하지 않습니다.


멱등한 메서드들을 이용하여 자동 복구 메커니즘을 구현할 수 있습니다.

DELETE를 요청했는데, 서버에서 응답이 없다면 클라이언트는 다시금 DELETE를 요청할 수 있습니다. 이는 DELETE가 몇 번 호출하든 같은 결과를 내는 메서드라는 점을 활용하여, 클라이언트에서 임의적으로 재차 요청을 하는 것입니다.

이를 통하여 멱등성을 구분하는 이유를 알 수 있습니다.

서버 입장에서, 요청 실패 이후 재전송된 요청을 처리해도 괜찮은가? 에 대한 가이드를 제공해 주는 것이 멱등성입니다.



3. 캐시 가능

캐시 가능이라 함은 , 요청한 응답의 리소스를 향후 재사용을 위해 저장할 수 있는 속성을 의미합니다.

웹 캐시는 중간에 요청을 가로채, 서버로부터 리소스를 직접 다운로드 하는 대신, 리소스의 복사본을 반환합니다.

 응답 결과 리소스를 캐시해서 사용해도 괜찮을까요? 

이론적으로 GET,POST,PATCH 메소드는 캐시가 가능하다고 하지만, 실제로는 GET정도만 캐시를 사용할 수 있습니다. 

웹 캐시는 리소스를 보여주는데 필요한 시간을 줄여서, 웹 사이트를 더 빠르게 만들 수 있는 방법입니다.

캐시에는 두가지 종류가 있습니다.

1. 사설(Private)

2. 공유(Shared)

Shared cache는 한 명 이상의 사용자가 재사용 할 수 있도록 응답을 저장한 캐시인 반면, 

Private cache는 한 명의 사용자만  사용하는 캐시입니다.

대표적인 사설캐시로는 "브라우저 캐시"가 있습니다. 사용자가 http요청 이후 다운로드한 문서들을 저장하고 있다가, 앞뒤로 움직이기, 저장 등을 수행할 때 추가적인 서버 요청 없이 캐시를 활용합니다.

프록시캐시는 대표적인 공유 캐시입니다. 회사 혹은 ISP(Internet Service Provider)는 여러 사용자들을 위해 로컬 네트워크의 일부로 웹 프록시를 설치할 수 있습니다. 이를 통해 공통적으로 조회가 많이 되는 리소스들은 재사용되어 성능을 향상할 수 있습니다.



4월 16, 2022

TIL) Stateless

 

무상태 프로토콜 

"컴퓨팅에서 무상태 프로토콜(stateless protocol)은 어떠한 이전 요청과도 무관한 각각의 요청을 독립적인 트랜잭션으로 취급하는 통신 프로토콜로, 통신이 독립적인 쌍의 요청과 응답을 이룰 수 있게 하는 방식이다. 무상태 프로토콜은 서버가 복수의 요청 시간대에 각각의 통신 파트너에 대한 세션 정보나 상태 보관을 요구하지 않는다. 반면, 서버의 내부 상태 유지를 요구하는 프로토콜은 상태 프로토콜(stateful protocol)로 부른다."

(https://ko.wikipedia.org/wiki/%EB%AC%B4%EC%83%81%ED%83%9C_%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C)

4월 15, 2022

TIL) 웹 브라우저 요청 흐름

https://commons.wikimedia.org/wiki/File:Tcp-handshake.svg 에 접속합니다

HTML 파일을 받아옵니다.

해당 링크 안에 이미지로 

https://upload.wikimedia.org/wikipedia/commons/9/98/Tcp-handshake.svg  가 들어있습니다.

브라우저는 HTML파일을 읽다가 이 이미지 주소로 서버에 요청을 보냅니다.

이것이 간단한 HTTP 트랜잭션입니다.


이미지를 받아오는 과정을 순서화하면,

1. DNS 조회 후 여기에서 서버의 IP 추출. 

2. PORT 정보 조회

3. HTTP 요청 메시지 생성

    


4. 웹 브라우저는 TCP 3 Way-handshake 방식으로 서버와 커넥션을 생성한다.

5. 웹 브라우저는 서버에 HTTP 요청을 보낸다.

6. 서버는 HTTP 요청을 해석한다. 

7. 서버는 요청을 받은 메서드를 찾는다.

8. 찾게되면 이를 200상태코드와 응답 메시지에 동봉하여 클라이언트에게 전송한다.

9. 서버와 클라이언트는 TCP4 Way-handshake 방식으로 커넥션을 종료한다.



(4way handshake 방식, 출처 https://gyoogle.dev/blog/computer-science/network/TCP%203%20way%20handshake%20&%204%20way%20handshake.html)

TCP4 Way-handshake 과정
a. 클라이언트는 FIN 보내고 FIN WAIT
b. 서버는 FIN을 확인했다는 ACK를 클라이언트에게 보냄
c. 데이터를 모두 보낸 이후 종료됐다는 FIN 플래그를 클라이언트에게 회신
d. 클라이언트는 혹시 받지 못한 데이터가 있을 수 있으므로 TIME_WAIT으로 기다린다
e. 서버는 ACK를 받은 이후 소켓을 닫는다
f. TIME_WAIT 이후 클라이언트도 닫는다.
4월 14, 2022

TIL) 인터넷 프로토콜 4 계층

 

정보가 전송될때에는 위에서 아래로, 애플리케이션 -> ~ -> 네트워크 인터페이스의 방향으로 전송됩니다.

애플리케이션 계층에서 정보를 만들어 전달하고, 전송 계층에서 정보의 통신 노드를 연결하고, 인터넷 계층에서 통신 노드간 패킷을 전송 및 라우팅 합니다. 네트워크 인터페이스 계층에서는 이를 실제로 전기 신호로 변환하여 전달합니다.

  • IP
클라이언트와 서버에 IP 주소가 부여됩니다.
IP는 지정한 주소에 데이터를 전달합니다. 이때의 통신 단위는 패킷(Packet)입니다.
IP패킷에는 출발지, 목적지, 전송데이터의 정보가 담깁니다.
    
IP **프로토콜은 패킷을 받을 대상이 없어도 전달된다는 비연결성, 패킷의 순서를 보장할 수 없고 중간에 패킷이 사라지는 경우를 대비할 수 없다는 비신뢰성의 두가지 단점이 있습니다.

또한 같은 IP를 사용하는 서버에서 여러 애플리케이션들과 통신하고 있다면, 이를 구분해야 하는 문제가 생깁니다.


이러한 문제를 해결하기 위해서 TCP 프로토콜을 사용합니다.

위의 애플리케이션 계층에서 데이터가 전달되면, 이를 포함한 tcp 정보를 생성한 이후, 이들을 담은 IP패킷을 만들어 LAN등의 네트워크 인터페이스를 통해서 정보를 전송합니다.

TCP 프로토콜은 IP의 단점을 보완하는 IP위에서 동작하는 프로토콜입니다.
  • 연결 지향적이며 (TCP 3 Way-handshake)
  • 데이터 전달을 보증하며(데이터가 중간에 누락된 경우 알 수 있습니다)
  • 흐름을 제어하고
  • 혼잡을 제어합니다

IP가 패킷을 이용한 통신의 방식이라면, TCP/UDP는 전송을 제어하는 "프로토콜"입니다.

IP가 목적지를 찾아가는 것, 그 자체에 중점을 둔다면, 

TCP정보에는 출발지와 목적지의 Port 정보, 전송 제어, 순서, 검증에 대한 정보들이 있습니다.

잠깐, PORT가 뭘까요? 목적지 서버(IP)의 다양한 프로세스(애플리케이션)을 구분하기 위한 번호입니다.

위의 3 Way-handshake는 TCP에서 연결을 확인하는 방식입니다.
1. Synnchronize : 클라이언트에서 서버로 SYN(접속요청) 메시지를 보냅니다
2. Acknowledge: 서버에서 SYN에 대한 응답으로 ACK을 보냅니다. 이때 서버에서도 SYN을 보내야 하기에 이를 ACK과 동봉합니다
3. 클라이언트도 서버의 SYN에 대한 답장으로 ACK을 보냅니다.

이때 3번의 ACK과 함께 데이터도 전송하곤 합니다.

3 way-handshake는 실제적인 연결을 보장하는 것이 아닌, "개념적인" 연결입니다. 서로 syn, syn+ack, ack 의 과정이 이뤄졌기에  연결이 됐다는 논리적 보장이 있을 뿐입니다. 또한, handshake과정에서 거치는 수많은 노드들에 대해서도 알 방법이 없습니다.

흐름 제어의 경우. TCP 헤더의 Window size를 이용해 주고/받을 수 있는 데이터의 양을 정합니다. 이는 수신자 측에서 자신의 상황을 보아가며 수시로 변경합니다.

혼잡 제어는 무엇일까요? 데이터가 지나가는 네트워크 망의 혼잡도를 제어하기 위한 방식입니다. 데이터 송신자는 초기 데이터 송신량을 낮게 잡은 이후, 수신 여부를 확인하며 이를 천천히 늘려나갑니다. 이를 통해 현재 네트워크에서 가장 적합한 데이터 송출량을 확인할 수 있습니다. 이를 slow start 라고 합니다. 혼잡 제어에는 이 외에도 다양한 방식이 있다고 합니다.

어느 순간 congestion point를 만나면, window 크기를 1로 줄인 이후 slow start를 다시 적용하는 것을 볼 수 있습니다



TCP와 같은 전송계층에는 UDP도 있습니다. 

전송제어 , 순서, 검증에 대한 정보가 담긴 TCP와 다르게, UDP에는 담겨있는 정보와 기능이 거의 없습니다.
다만 단순하고 빠릅니다. TCP와 다르게 프로토콜에 손을 댈 수도 있습니다.

IP와 거의 같다고도 볼 수 있지만, Port 정보와 체크섬(메시지가 제대로 왔는지 검증해주는 데이터) 가 담깁니다.


** 프로토콜 : 컴퓨터 사이(내부 포함)의 데이터 교환 방식을 정의하는 규칙 체계. 기기간 통신은 교환되는 데이터에 대한 상호 합의를 요하는데, 이런 형식을 정의하는 규칙의 집합이 프로토콜.

해당 글을 참조하였습니다 : https://aws-hyoh.tistory.com/entry/TCPIP-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0

4월 13, 2022

TIL) Cache : 검증 헤더와 조건부 요청

 

브라우저는 서버의 응답결과를 캐시에 저장합니다

이후 재차 요청을 보내기 전에, 브라우저는 캐시의 유효기간이 초과되지 않았다면 네트워크를 거치지 않고 캐시를 통해 데이터를 조회합니다.


이때, 만약 캐시의 시간이 초과됐다면 브라우저는 똑같은 응답을 위한 요청을 재차 보내야만 합니다. 이때, 서버에서 데이터를 바꾼 것이 없다면 똑같은 데이터를 굳이 다시 다운로드 받아야 하나? 하는 의문이 생깁니다.


이때 검증 헤더와 조건부 요청을 이용합니다. 

캐시 유효 시간이 초과된 이후, 서버에 다시 요청을 보낼 때, 다음의 두가지 경우의 수가 있습니다.

1. 서버에서 기존 데이터를 변경한 경우

2. 서버에서 기존 데이터를 변경하지 않은 경우

2번의 경우, 서버가 데이터를 변경하지 않았다면 기존 데이터를 재사용 할 수 있겠죠? 다만 이때 서버의 데이터와 클라이언트의 데이터가 같다는 것을 검증할 필요성이 있습니다.

이를 위해서 검증헤더를 사용합니다. 검증 헤더는 캐시 데이터와 서버의 데이터가 같은 지를 검증하는 역할을 합니다.

검증헤더에는 Last-Modified와 ETag가 있습니다. 

Last-modified의 경우, 조건부 요청 헤더에 if-modified-since 를 사용합니다. 

캐시의 데이터 최종 수정일과, 서버의 데이터 최종 수정일이 다를 경우, 200OK, 같을 경우 304 Not Modified(변한게 없다)의 응답이 옵니다. 304 Not Modified의 경우, 데이터가 바뀌지 않았으므로 HTTP BODY가 오지 않습니다.


ETag 는 if-Not-Match의 조건부 요청 헤더를 사용합니다. 

ETag는 캐시용 데이터에 고유한 이름을 달아놓은 것입니다.

ETag는 서버 사이드에서 관리하는 것이기에, 캐시 제어 로직은 서버에서 온전히 가지고 있다고 볼 수 있습니다.

 서버는 데이터가 변동됐을 시, 해시를 통해서 ETag를 재 생성합니다(해시 함수에 넣는 값이 동일하면 해싱의 결과도 동일하기에, 이를 통해 데이터의 변동을 표현할 수 있습니다). 사용자는 ETag를 통해서 데이터가 변경됐는지 아닌지를 알 수 있습니다.


개발자도구를 켜서, 네트워크 탭에서 트랜잭션을 확인할 수 있습니다 


자세히 보면 204는 검은색이고, 200은 회색입니다.

회색인 경우는 기존 캐시에서 불러왔음을 뜻합니다.


해당 특정 트랜젝션을 클릭해보면, 캐시에서 불러왔음을 알 수 있는 문구가 있네요.

이렇게 서버로 부터 데이터가 바뀌지 않았다는 응답인 304를 확인해 볼수도 있습니다.


4월 12, 2022

TIL) django.db.utils.IntegrityError: (1048, "Column 'kakao_id' cannot be null")

 

코드 


시리얼라이저


모델


해당 값을 바디에 담아서 POST요청을 보냄



serializer.save() -> serializers.py의 get_or_create에서 문제가 생김

kakao_id를 .get으로 키가 없는 경우 빈 값 들어가도록 처리해주었고, kakao_id 모델 컬럼은 blank=True이므로 kakao_id가 없이 요청을 보내도 문제 없는 것 아닌가?

get_or_create는 다른 기능에서 사용하는 코드라 로직을 변경하기 어려움 

해당부분을 주석처리하고 요청 보내면 원하는대로 user object가 만들어지긴 함

kakao_id가 없으면 get_or_create()에서 get을 하기위해 찾아 줄 조건인 kakao_id 자체가 없어지기에 해당 코드는 kakao_id 값이 없이 요청이 들어오면 동작하지 않는 것이 맞음


생각해보니, 핸드폰 로그인에서도 1회 회원가입 이후 회원 정보를 get해와야 하기에 serializer를 나눠서 get_or_create()를 써주자 


해당 serializer를 추가하여 이를 이용했을 시 원하는 대로 동작한다.