728x90
반응형

import random


  • random() : 0 이상 1 미만의 실수 난수 생성
  • randrange(a, b, c) : a가 시작점, b가 끝점(포함 x), c는 간격(step). 간격은 필수 아님
  • choice() : 하나 골라줌
  • shuffle() : 시퀀스 객체를 셔플 시켜줌

lambda, map, reduce, filter


# lambda 매개변수 : 표현식
def multi(x, y):
    return x * y

if multi(2, 4) == (lambda x, y: x * y)(2, 4):
    print('결과가 똑같아용')

# map(함수, 리스트)
print(list(map(lambda x: x ** 3, range(3))))  # [0, 1, 8] 출력

# reduce(함수, 순회 가능한 데이터[, 초기값]) -> 누적 집계
from functools import reduce

r = reduce(lambda x, y: x + y, range(5))
print(r)  # 10 출력

users = [{'mail': 'gregorythomas@gmail.com', 'name': 'Brett Holland', 'sex': 'M', 'age': 73},
         {'mail': 'hintoncynthia@hotmail.com',
             'name': 'Madison Martinez', 'sex': 'F', 'age': 29},
         {'mail': 'wwagner@gmail.com', 'name': 'Michael Jenkins', 'sex': 'M', 'age': 51},
         {'mail': 'daniel79@gmail.com',
             'name': 'Karen Rodriguez', 'sex': 'F', 'age': 32},
         {'mail': 'ujackson@gmail.com', 'name': 'Amber Rhodes', 'sex': 'F', 'age': 42}]

sum_age = reduce(lambda acc, cur: acc + cur["age"], users, 0)
print(sum_age)

# filter(함수, 순회 가능한 데이터) -> 원소를 함수에 적용시켜 결과가 참인 값들을 걸러낸다.
f = filter(lambda x : x < 5, range(10))
print(list(f)) # [0, 1, 2, 3, 4] 출력

Django 복습 - 요새 기존에 알던 것도 공식 문서로 다시 공부 중입니당

verbose_name


  • verbose_name is a human-readable name for the field.
  • If the verbose name isn’t given, Django will automatically create it using the field’s attribute name, converting underscores to spaces.
  • This attribute in general changes the field name in admin interface.
  • 요약 : 필드 이름을 인간이 읽기 쉽도록 바꿈. 안 쓰면 기본적으로 속성 이름 따라감(공백은 ‘_’로 치환)

related_name → 참고 docs


  • 모델이 외래키로 참조’되고’ 있을 때, 해당 모델은 FOO_set을 통해 관련 모델의 필드를 반환하는 Manager에 접근할 수 있다.
  • 이때 FOO는 소스가 되는 모델의 소문자 이름이다.
  • 또는 FOO_set 대신 related_name으로 따로 이름을 지정해줄 수도 있다.
  • 해당 Manager는 QuerySets을 반환한다.
from datetime import date
from django.db import models

class Blog(models.Model) :
    name = models.CharField(max_length = 100)
    tagline = models.TextField()

    def __str__(self) :
        return self.name

class Entry(models.Model) :
    blog = models.ForeignKey(Blog, on_delete = models.CASCADE)
    headline = models.CharField(max_length=255)

b = Blog.objects.get(id=1)
b.entry_set.all() # b와 연관된 모든 Entry 객체를 들고 온다.
  • 만약 blog = models.ForeignKey(Blog, on_delete = models.CASCADE, related_name = 'entries')로 설정돼있을 경우 b.entries.all()로 가져올 수 있다.
  • Django가 역방향 관계(Backwards relation)를 생성하지 않길 원한다면 related_name을 '+'로 설정하거나 '+ '+'로 끝내면 된다. (아래 예시)
class Entry(models.Model) :
    blog = models.ForeignKey(Blog, on_delete = models.CASCADE, related_name = "+", )
    # Blog 모델이 역방향 관계를 갖지 않도록 한다.
  • QuerySet의 kwarg로도 활용할 수 있다. 즉 reverse filter name으로 쓸 수 있다.

related_query_name


  • 타겟 모델의 reverse filter name으로 사용하는 이름
  • if set 따로 지정하지 않을 경우 related_name이나 default_relaged_name과 동일하다(→_set). otherwise 모델 이름으로 설정된다/
  • related_name처럼 app label과 class interpolation을 지원한다.

related_name과 related_query_name 사용 시 주의할 점 → 참고 docs%3A%0A%20%20%20%20%20%20%20%20pass-,Be%20careful%20with%20related_name%20and%20related_query_name,-%C2%B6)


  1. 추상 기본 클래스(abstract base classes)의 필드는 매번 속성값(attribute, related_name과 related_query_name 포함)을 똑같이 가지고 각각의 자식 클래스에 포함된다.
  2. 따라서 외래키나 ManyToManyField를 가진 추상 기본 클래스(abstract base classes)를 상속받을 경우 항상 related_name 또는 related_query_name 속성값이 동일한 문제가 발생할 수 있다. (migrate할 때 에러가 나버릴지도~)
  3. 그러므로 외래키나 ManyToManyField에서 related_name 또는 related_query_name 사용하는 경우, 필드의 고유한(unique) reverse name과 query name 필수로 지정해주어야 한다.
  4. 이때 %(app_label)s과 %(class)s를 활용한다.
    • %(class)s : 해당 필드가 사용되는 자식 클래스의 소문자(lower-cased) 이름.
    • %(app_label)s : 자식 클래스가 포함돼있는 앱의 소문자(lower-cased) 이름. 이때 각 앱과 앱 내 모델 클래스의 이름이 모두 unique해야 이름이 다르게 나온다.
  5. 예시
from django.db import models

class Base(models.Model):
    m2m = models.ManyToManyField(
        OtherModel,
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",
    )

    class Meta:
        abstract = True

class ChildA(Base):
    pass

class ChildB(Base):
    pass
  • The reverse name of the common.ChildA.m2m field will be common_childa_related and the reverse query name will be common_childas. (누가 내 블로그를 볼까 싶어서 굳이 한글로 해석하진 않았다../)
  • The reverse name of the common.ChildB.m2m field will be common_childb_related and the reverse query name will be common_childbs.
  • Finally, the reverse name of the rare.ChildB.m2m field will be rare_childb_related and the reverse query name will be rare_childbs.

related_name&related_query_name요약



  1. related_name은 일대다 관계에서 1인 모델 인스턴스가 관계된 多 모델의 객체를 가져올 때 사용한다.
  2. related_name은 모델 인스턴스의 속성처럼 활용 가능하고, 따로 related_query_name을 지정하지 않을 경우 QuerySet의 kwarg로도 사용 가능하다.
  3. 만약 자식 클래스가 존재할 경우 %(app_label)s과 %(class)s를 활용해 고유한(unique) reverse name과 query name을 지정해 주어야 related_name 또는 related_query_name 속성값이 동일한 문제를 방지할 수 있다.

 

 

오늘 기분 나쁜 일 있어서 뒤지게 공부만 했더니 스트레스가 좀 풀렸다.

슬픈 감정이든 빡침이든 부정적인 감정이 올라올 때는 일부러 나를 바쁘게 만든다.

이런 점에서 가끔은 짜잘하게 나쁜 일이 있는 것도 나쁘지 않아~~

덕분에 영어 공부랑 일본어 공부도 하고 코딩 공부까지 하루에 다 할 수 있었다.

반응형
728x90
반응형
  • 코딩 테스트 문제 등을 풀다 보면, 최솟값을 저장하는 변수에 아주 큰 값을 할당해야 할 때가 있다.
  • inf는 어떤 숫자와 비교해도 무조건 크다고 판정된다.
  • inf에는 음수 기호를 붙이는 것도 가능하다.
  • 정수형(int)에는 적용 불가능. 따라서 float에 적용한 inf에 int()도 사용할 수 없다.
  • 비교하는 상황에서 최솟값을 찾을 때 용이하다(useful for finding lowest values for sth).
  • float 내장함수 말고 math 모듈을 사용해 표현할 수도 있다.
import math

max_float = math.inf
min_float = -math.inf
  • float(’-inf’)와 -math.inf는 음의 무한대. 무조건 작다고 판정된다.
  • 예시
min_val = 99999
min_val > 100000000 # ?
# 위 방법은 비교할 데이터가 아주 큰 경우, 정상 작동하지 않을 수 있다.

min_val = float('inf') # 무조건 크다고 판정된다.
min_val > 10000000000
반응형
728x90
반응형
  • 정의 : 특정 시각이나 정기적인 시간대에 작업이 실행되게끔 할 수 있다. → 작업 스케쥴링
  • 설치
    1. sudo apt install cron
    2. sudo service cron status : 크론탭이 실행 중인지 확인한다. 상태가 active면 그대로 두고, active가 아니면 아래 명령어 수행.
    3. pgrep cron을 입력했을 때 프로세스id의 출력 여부를 통해 확인할 수도 있다. (아무것도 출력하지 않으면 실행중이 아닌 것)
    4. sudo service cron start
    5. sudo service cron restart : 크론탭 재시작 (넘버링하긴 했지만 3 → 4는 이상하다)
  • 기본적인 크론탭 명령어
    1. crontab -e : 작업 할당 명령어. 첫 실행 시 nano와 vim 중 사용할 텍스트 편집기를 고르고, 이후에는 바로 편집기가 실행된다.
    2. 만약 nano 에디터로 설정돼있을 경우 export VISUAL=vim이나 export EDITOR=vim 명령어를 통해 에디터를 vim으로 변경할 수 있다.
    3. crontab -l : 할당된 작업 리스트 확인
  • 작업 할당 방법
    • 크론탭은 텍스트 입력을 통해 작업을 할당한다.
    • *은 반복 주기를 의미한다.
    • *은 순서대로 분(0-59), 시간(0-23), 일(1-31), 월(1-12), 요일(0-7) 설정에 해당한다.

    1. crontab -e
    2. * * * * * + 실행할 명령 텍스트 ex) 30 16 * * * env > /tmp/env.output : 매일 오후 4시 30분에 환경변수를 tmp/env.output에 저장하는 배치 작업
반응형
728x90
반응형
  1. 클래스 메소드와 스태틱 메소드
'''
1. 인스턴스 메소드 : 첫 번째 매개변수로 객체를 받는다 -> self
2. 클래스 메소드 : 첫 번째 매개변수로 자기 클래스를 받는다 -> cls
3. 스태틱 메소드 : 일반 함수와 거의 비슷해 클래스와 연관성이 있음을 나타내는 정도로 쓰인다/
4. 클래스 메소드 vs. 스태틱 메소드
    - 공통점 : 클래스 변수에 접근 가능하지만 생성자를 포함한 인스턴스 메소드 변수에는 접근 불가능하다.
    - 스태틱 메소드 : 부모 클래스에서 정의된 스태틱 메소드는 자식 클래스에서 호출할 수 있다.
    - 클래스 메소드 : 부모 클래스에서 정의된 클래스 변수와 클래스 메소드는 자식 클래스에서도 선언이 가능하다.
    - 상속할 때 차이점 : 자식 클래스가 존재할 때, 스태틱 메소드는 부모 자식 어디서 선언하든 클래스 변수를 모두 바꾸지만, 클래스 메소드에서는 부모 클래스 객체에서 선언해야만 자식 클래스의 클래스 변수까지 모두 바꿀 수 있다. 자식 클래스에서 선언하면 자식 클래스의 클래스 변수만 바뀐다.
'''

class Parent:
    name = 'Geumbin Lee'
    
    @staticmethod
    def change_name_with_static(new_name) :
        Parent.name = new_name
        
    @classmethod
    def change_name_with_class(cls, new_name) :
        cls.name = new_name
    
class Child(Parent) :
    pass

parent = Parent()
child = Child()

print('<<<<< 스태틱 메소드에 대해 배워봅시당 >>>>>')
parent.change_name_with_static('Robin Lee')
print(f'부모 클래스에서 선언 : {parent.name}, {child.name}') # Robin Lee, Robin Lee
child.change_name_with_static('Katy Lee')
print(f'자식 클래스에서 선언할 때 : {parent.name}, {child.name}') # Katy Lee, Katy Lee

print('-'*50)
print('<<<<< 클래스 메소드에 대해 배워봅시당 >>>>>')
parent.change_name_with_class('Robin Lee')
print(f'부모 클래스에서 선언 : {parent.name}, {child.name}') # Robin Lee, Robin Lee
child.change_name_with_class('Katy Lee')
print(f'자식 클래스에서 선언할 때 : {parent.name}, {child.name}') # Robin Lee, Katy Lee
  1. 프로그래머스 - 이분 탐색: 징검다리
def solution(distance, rocks, n):
    answer = 0
    rocks.sort()
    start, end = 0, distance
    
    while start <= end: 
        mid = (start + end) // 2
        del_rock = 0 # 제거 횟수 카운트
        stone = 0 # 기준점
        for rock in rocks:
            if rock - stone <  mid: # 거리가 mid보다 작으면 제거한다.
                del_rock += 1 
            else: # 돌 사이 거리가 mid보다 크면 기준을 바꾼다.
                stone = rock
             
            if del_rock > n: #제거된 돌이 문제 조건 보다 크면 for문을 나온다
                break
        
        if del_rock > n: # 제거할 바위 수(n)보다 많은 바위를 제거했을 시 범위를 줄인다.
            end = mid - 1
        else: # 그게 아니면 큰 쪽으로 줄인다.
            answer = mid
            start = mid + 1
        print(f"start : {start}, end : {end}, mid : {mid}, del_rock : {del_rock}, answer :{answer}")
            
    return answer

solution(25, [2, 14, 11, 21, 17], 2)
  1. ORM
    • 정의 : 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해준다.
    • SQL로 변환해서 들어가기 때문에 sql문을 잘 몰라도 작성할 수 있다. where를 filter로 가져오는 식
    • 특징
      1. Lazy Loading
        • 말 그대로 게을러서 실제로 데이터를 조작하는 순간에 DB를 hit한다.
        • 필요할 때마다, 필요한 횟수만큼만 db를 건드린다.
        • n + 1 문제를 발생시킬 수 있다.
      2. n + 1 문제
        • N건의 데이터를 가져오고(쿼리 +1), 특정 데이터를 위해 N건의 데이터를 순회(쿼리 +N)하는 문제
        • ORM은 필요할 때마다 쿼리문을 수행하기 때문에 조회할 데이터가 개수가 증가할수록 쿼리문 수행 개수도 증가한다 → 서버 부하 UP → 속도 DOWN
        • 해결책 : Eager Loading
      3. Eager Loading
        • 말 그대로 굉장히 열심(eager)이다. 지금 당장 안 필요한 데이터도 가져온다. → select_realted와 prefetch_related
        • select_realted
          • SQL의 JOIN을 사용하는 방법 → 외래키로 종속된 테이블의 데이터를 함께 들고 온다 (부지런하다)
          • One 객체를 참조하는 경우(one-to-one, many-to-one), 정참조 관계일 때(many-to-one(many에서 one 참조)) 사용 가능
          • 정참조와 역참조 모두 사용 가능한 prefetch_realted에 비해 범용성은 떨어지지만, 대개 성능이 더 좋기 때문에 가능한 상황에서는 select_related를 사용하는 것이 좋다.
        • prefetch_related
          • 공식 문서에서 ‘joining’이라고는 하나, 그 JOIN이 아니고, 테이블을 각각 불러들인 후 ORM 처리 단계에서 결합하는 방식
          • 따라서 항상 추가 쿼리가 발생한다. 그래서 대개 select_realted에 비해 성능이 떨어진다. (항상은 X)
          • 정참조 역참조 모두 사용 가능
      4. Caching
        • 캐싱을 활용해 이미 가져온 데이터를 쿼리문을 또 날리지 않고 그대로 재사용할 수 있다.
        • 핵심은 그대로!!! 가져온 데이터에 무언가 가공을 가하지 않은 상태여야 캐싱을 활용할 수 있다. ex) 슬라이싱이나 인덱싱하면 안됨
        • 당연히 많이 활용할수록 속도가 개선된다.
반응형
728x90
반응형

어제 공부했는데 갑자기 까무룩 잠들어서 til만 못 썼다.. 오늘은 그래서 두 개가 올라간다.

# rnage(시작, 끝, 간격)
range_tuple = tuple(range(10, 0, -2))
print(range_tuple)

# 튜플은 리스트처럼 요소를 일렬로 저장하지만, 안에 저장된 요소를 변경, 추가, 삭제할 수 없다. (튜플은 불변 객체라 아무래도...)
# 간단하게 읽기 전용 리스트라고 생각할 수 있다.
a = 'a', # 이렇게 튜플 맏들어도 됨
b = 'b', 'c', 
print(type(a), type(b))
print(a)
print(b)
'''
< 시퀀스 자료형 >
- list, tuple, range, string 등
- 공통점 : 값이 연속적(sequential)으로 이어져 있다.
- in/not in 사용 가능 -> True or False
- + 연산자 활용 가능
- * 연산자 활용 가능. 단, 0 또는 음수를 곱하면 빈 객체가 나오며 실수는 곱할 수 없다.
- range는 +/* 연산자로 객체 연결 불가능 -> list나 tuple로 만들어 연결/반복하면 됨
- str도 시퀀스 자료형이니까 len(사용 가능
- 시퀀스 객체의 요소는 순서가 정해져 있으므로 인덱스로 접근 가능하다.
- tuple은 요소 변경이 불가능하기 때문에 인덱스를 통한 요소 변경/삭제/추가가 불가능하다. str, range도 마찬가지
- 슬라이싱은 모두 활용 가능, 다만 불변 객체는 객체를 새로 만드는 방식
- 시퀀스 객체 중에서도 불변 객체는 슬라이싱을 활용해도 요소를 할당할 수 없다.
'''

print(len(range(0, 10, 2))) # 5
print(len('hello, world')) # 띄어쓰기도 카운트함

r = range(1, 11)
print(r[:7:2]) # range(1, 8, 2)라고 요소가 모두 표시되지 않고 생성 범위만 표시됨
print(list(r[:7:2])) # [1, 3, 5, 7] 리스트로 표시해주면 해결

# 슬라이싱을 활용해 리스트에 새로운 요소를 할당할 때, 할당할 요소의 개수가 슬라이싱된 요소의 개수보다 적으면 그만큼 리ㅡ트의 요소 개수도 줄어든다.
a = list(range(0, 10))
a[2:5] = ['2~4'] 
print(a) # [0, 1, '2~4', 5, 6, 7, 8, 9]

# 반대로 할당할 용소의 개수가 슬라이싱된 요소의 개수보다 많으면 그만큼 리스트의 요소 개수도 늘어난다.
a[2:5] = [2, 3, 4, 5, 6]
print(a) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 인덱스의 증가폭을 활용해 슬라이싱을 통한 재할당을 할 때는, 슬라이싱 범위 내 요소의 개수와 할당할 요소의 개수가 일치해야 한다.
b = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
b[2:8:2] = ['a', 'b', 'c'] # 개수 안 맞추면 ValueError 발생
print(b)
반응형
728x90
반응형
  • 추가 HTTP를 사용해 다른 출처에 있는 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제
  • Protocol + Host + Port 3가지가 같으면 동일 출처(Origin)라고 한다. 하나라도 다르면 교차 출처[다른 출처].
  • 요청하는 클라이언트와 요청받는 서버가 같은 출처에 있으면 동일 출처서로 다른 서버에 있으면 다른 출처 요청
  • 동일 출처 정책 (Same-origin policy)
    • 다른 출처로부터 조회된 자원들의 읽기 접근을 막아 다른 출처 공격을 예방한다.
  • 다른 출처 요청 정책 3가지 → 참고자료(이 분께서 잘 정리해 주셨다.)
    1. 단순 요청 (Simple Request)
    2. 프리 플라이트 (Preflight Request)
    3. 신용 요청 (Credentialed Request)
반응형
728x90
반응형

면접 직전에 굉장히 압축해서 적은 내용이다.

자세한 내용은 구글링하면 굉장히 잘 나온다.

블로그에 내용 정리한 거 올리면서 답변용으로 요약을 한 번 더 한다고 했는데, 이 정도 분량으로 압축하는 편이다.

자잘한 건 꼬리질문이 나왔을 때 대답할 수 있을 정도로만 걍 이해하고 넘어간다.

 

  1. HTTP는 암호화 과정이 없어 보안에 취약하다.
  2. HTTPS는 HTTP를 SSL 프로토콜 위에서 돌아가도록 해 클라이언트와 서버 간 텍스트를 암호화하는 방식으로 구현합니다.
  3. 즉 HTTPS는 HTTP 프로토콜 + SSL 프로토콜
  4. SSL 프로토콜 동작 원리 : SSL/TLS handshake
    • 클라이언트가 서버에 접속하면 서버는 클라이언트에게 SSL 인증서를 전달합니다.
    • 브라우저는 대부분의 검증된 민간 기업의 공개키를 보유하고 있으므로, 이를 통해 인증서를 복호화 합니다.
    • 복호화를 통해 인증서의 신뢰성을 확인했으면 클라이언트는 해당 공개키를 활용해 서버와 소통하며 대칭키인 ‘세션키’를 생성하고 이를 활용해 통신을 진행합니다.
반응형
728x90
반응형
  • 3줄 요약
    1. 만들어놓은 것 그대로 제공하는 리소스를 정적 리소스라 하고, 데이터 처리에 따라 값이 다를 수 있는 리소스를 동적 리소스라 한다.
    2. 웹 서버는 정적 리소스 처리를 담당하기 때문에 동적 리소스를 처리하기 위해 웹 어플리케이션을 사용한다.
    3. CGI는 웹 서버와 웹 어플리케이션 서버 간 통신을 위한 공통의 인터페이스이고, 매 요청 때마다 프로세스를 생성해야 한다는 CGI의 단점을 보완한 게 WSGI, 비동기에 취약하다는 WSGI의 단점을 보완한 게 ASGI이다.
  • 정적 리소스 (Static Resource) vs. 동적 리소스 (Dynamic Resource)
    1. 정적 리소스 (Static Resource)
      • 만들어놓은 것 그대로 제공하는 리소스
      • ex) 파일이나 이미지, HTML 페이지 등
    2. 동적 리소스 (Dynamic Resource)
      • 상호작용을 통한 데이터 처리가 필요한 리소스
      • 값이 그때그때 다를 수 있는 리소스
      • 대표적으로 데이터베이스의 처리가 필요한 경우 ‘동적’이라는 말이 붙는다.
      • → 서버가 사용자의 '요청(Request)'에 따라 데이터를 가공처리한 뒤에 생성되어진 웹 페이지를 보여주게 된다.
  • 웹 서버(Web Server) vs 웹 어플리케이션 서버(Web Application Server)
    1. Web Server 웹 서버
      • 정적인 리소스 요청을 처리하는 프로그램으로, 웹 서버의 종류에는 아파치(Apach)와 Nginx 등이 있다.
      • 동적 컨텐츠를 처리하기 위해 데이터 베이스 쿼리문 처리와 같은 동적 요청이 들어오면 웹 어플리케이션에 요청을 넣는다.
    2. Web Application 웹 어플리케이션 → 보통 WAS라고 부른다.
      • 웹 서버로부터 오는 동적인 요청을 처리하는 서버로, 로직을 수행한 뒤 웹 서버에 결과를 돌려준다.
      • 기능
        1. 프로그램 실행 환경과 데이터베이스 접속 기능을 제공
        2. 여러 개의 트랜잭션을 관리
        3. 업무를 처리하는 비즈니스 로직 수행
      • 종류에는 아파치 톰캣, 제우스, 제티(Jetty), 레진(Resin) 등이 있다.
      • 예시 : nginx가 웹 서버가 django가 백엔드에서 돌린 웹애플리케이션 서버에 해당한다
  • 💡 Web Server 는 다소 광범위한 용어라서 Hardware 로서의 의미와 Software 로서의 의미를 함께 가지고 있어 여기에서는 Software 로서의 의미에 집중한다.
  • CGI / WSGi / ASGI 개념 → 참고자료https://kangbk0120.github.io/articles/2022-02/cgi-wcgi-asgi
    1. CGI (Common Gateway Interface)
      • 웹 서버가 동적인 리소스를 처리하기 위해 웹 어플리케이션과 소통할 때 서버 간, 그리고 언어 간 요청을 공통의 형태로(→Common Gateway Interface) 처리하기 위해 만들어진 인터페이스
      • → 즉 한마디로 웹 서버와 웹 어플리케이션이 소통할 수 있는 인터페이스
      • 단점
        • 요청이 들어올 때마다 애플리케이션 프로세스를 다시 생성해 실행해야 한다.
        • C와 같은 컴파일 언어보다 파이썬과 같은 스크립트 언어에서 실행에 더 많은 시간이 필요하기 때문에 더욱 단점이 두드러진다.
      • 동작 원리
        1. Web Server 가 Client 로 부터 HTTP Request 를 받는다.
        2. Web Server 는 Request 에 대한 정보(Method, Url, Parameters, ...)를 환 경숭수오와 tanad rddIIut 을 통해 전달하면서 Script 를 실행한다.
        3. Script 는 비즈니스 로직을 수행하고 Standard Output 으로 결과를 Web Server 에게 전달한다.
        4. Web Server 는 이를 다시 Client 에게 전달한다.
    2. WSGI (Web Server Gateway Interface)
      • 이름과 달리 범용적이라기보다는 파이썬에서 사용되는 개념
      • CGI의 단점을 보완하기 위해 고안되었다.
      • CGI가 환경 변수나 STDIN 등으로 처리했지만 WSGI에서는 웹 서버가 요청에 대한 정보를 어플리케이션에 전달할 때 Callable object(호출 가능한 객체), 즉 함수나 객체로 처리한다.
      • → 서버에서 Callable object를 통해서 요청에 대한 정보와 Callback 함수를 전달하면 애플리케이션은 이 요청을 처리하고 Callback 함수를 실행한다.
      • 하나의 동기적인 callable이 요청을 받아 응답을 리턴하는 방식으로, 비동기 요청 처리에 취약하다.
      • WSGI compatible하다 : 앞서 설명한 인터페이스를 구현하는 서버나 어플리케이션을 설명하는 용어
      • WSGI application : WSGi 어플리케이션 지칭
      • WSGI Middleware : 중간에서 인증이나 쿠키 등을 관리하는 역할을 하며, WSGI application의 일종으로, gunicorn을 포함한다.
    3. WSGI Middleware
      • 인증, 라우팅, 세션, 쿠키, 에러 페이지 보여주기 등 공통적으로 필요한 기능들을 웹 어플리케이션 실행 전후에 추가해주는 역할을 하는 WSGI 어플리케이션의 일종.
      • gunicorn이 WSGI Middleware 기능을 가진 라이브러리 중 하나이다.
      • gunicorn은 WSGI Middleware의 기능 뿐 아니라 그 자체로도 웹 서버의 역할을 할 수도 있다. 그래서 WSGI Server 나 Stand alone WSGI Container 라고 불리기도 한다.
      • Nginx 는 주로 Buffering, Reverse Proxying, Load Balancing 등의 기능을 위해 Gunicorn 앞단에 배치하고, Gunicorn 은 Django 로 작성한 Web Application 에 HTTP 요청을 전달해주는 역할의 WSGI HTTP Server 로서 사용하는 것이다.
      • Gunicorn 을 사용할 땐 worker process 의 개수와 worker class(async 방식인 Gevent, Tornado, ...)를 설정하여 요청 처리 성능을 높일 수 있다.
    4. ASGI
      • 비동기에 취약한 WSGi를 보완하기 위해 고안되었다. ⇒ WSGI + 비동기
      • → WSGI는 하나의 동기적인 callable이 요청을 받아 응답을 리턴하는 방식으로, 길게 유지돼야 하는 연결(ex. long-poll HTTP나 Websocket)에는 적합 X
      • WSGI에 대한 호환성은 유지하면서 비동기적인 요청까지 처리할 수 있는 인터페이스
      • ASGI 서버로는 주로 uvicorn 등을 많이 사용한다.
  • 참고자료
반응형
728x90
반응형
  • 프록시 서버(proxy server)란
    • 프록시 서버(proxy server)란 클라이언트와 네트워크 서비스 사이에서 통신을 받아 중계해주는 서버입니다.
    • 프록시 서버를 사용하면 보안성, 성능, 안정성을 향상 시킬 수 있습니다.
    • 크게 포워드 프록시 서버(forward proxy server)와 리버스 프록시 서버(reverse proxy server)로 나눠집니다.
  • 포워드 프록시 서버(forward proxy server)란?
    • 흔히 말하는 ‘프록시 서버’란 포워드 포록시 서버를 의미합니다.
    • 프록시 서버는 아래 그림처럼 클라이언트 앞에 놓여 있습니다.
    • 클라이언트가 웹 서버에 요청을 보내면 중간에서 그 요청을 가로채 웹 서버로 보내고, 웹 서버에게 받은 응답을 다시 클라이언트에게 전달한다.
    • 활용
      • 해당 기관에 속한 사람들이 그들이 방문하고자 하는 웹사이트에 직접적으로(directly) 방문하는 것을 방지한다.
      • 즉 기관에 속한 유저가 특정 컨텐츠에 접근하는 것을 방지하는데 사용됩니다.
      • 예를 들어, 포워드 프록시 서버에 룰을 추가해서 특정 사이트에 접속하는 것을 막을 수 있습니다.
      • 포워드 프록시 서버를 사용하면 IP 주소를 역추적해도 프록시 서버만 보이기 때문에 유저의 정체를 숨겨주는 데 용이합니다.
  • 리버스 프록시 서버(reverse proxy server)란?
    • 포워드 프록시 서버는 클라이언트 앞에 놓여져 있는 반면, 리버스 프록시 서버는 아래 그림처럼 웹서버 앞에 놓여 있습니다.
    • 리버스 프록시 서버는 로드 밸런싱(load balancing)에 사용됩니다.
    • → 싱글 서버는 대량의 트래픽을 감당하기 어렵지만, 리버스 프록시 서버를 여러개의 서버 앞에 두면 특정 서버가 과부화 되지 않게 로드밸런싱이 가능합니다.
    • 리버스 프록시를 사용하면 보안에 좋습니다. 본래 서버의 IP 주소를 노출시킬 필요가 없어 DDoS 공격과 같은 공격을 막는데 유용합니다.
    • 대신 CDN과 같은 리버스 프록시 서버가 공격의 타겟이 될수는 있습니다.
    • 리버스 프록시 서버는 성능 향상을 위해 캐시 데이터를 저장할 수 있습니다. 그리고 캐싱되어 있는 데이터를 사용함으로써 더 빠른 성능을 보여줄 수 있다.
    • 마지막으로 SSL 암호화에 좋습니다. 원래는 비용이 많이 들지만, 리버스 프록시를 사용하면 들어오는 요청을 모두 복호화하고 나가는 응답을 암호화해주므로 클라이언트와 안전한 통신을 할수 있으며 본래 서버의 부담을 줄여줍니다.
  • 포워드 프록시 vs 리버스 프록시
    • 포워드 프록시 서버는 클라이언트 앞에 놓여져 있는 반면, 리버스 프록시 서버는 웹서버 앞에 놓여 있습니다.
    • 따라서 포워드 프록시 서버를 사용하면 클라이언트와 직접 통신하는 웹서버가 없습니다.
    • 반면 리버스 프록시 서버를 사용하면 웹서버와 직접 통신하는 클라이언트가 없습니다.
  • 프록시 서버(proxy server)란
    • 프록시 서버(proxy server)란 클라이언트와 네트워크 서비스 사이에서 통신을 받아 중계해주는 서버입니다.
    • 프록시 서버를 사용하면 보안성, 성능, 안정성을 향상 시킬 수 있습니다.
    • 크게 포워드 프록시 서버(forward proxy server)와 리버스 프록시 서버(reverse proxy server)로 나눠집니다.
  • 포워드 프록시 서버(forward proxy server)란?
    • 흔히 말하는 ‘프록시 서버’란 포워드 포록시 서버를 의미합니다.
    • 프록시 서버는 아래 그림처럼 클라이언트 앞에 놓여 있습니다.
    • 클라이언트가 웹 서버에 요청을 보내면 중간에서 그 요청을 가로채 웹 서버로 보내고, 웹 서버에게 받은 응답을 다시 클라이언트에게 전달한다.
    • 활용
      • 해당 기관에 속한 사람들이 그들이 방문하고자 하는 웹사이트에 직접적으로(directly) 방문하는 것을 방지한다.
      • 즉 기관에 속한 유저가 특정 컨텐츠에 접근하는 것을 방지하는데 사용됩니다.
      • 예를 들어, 포워드 프록시 서버에 룰을 추가해서 특정 사이트에 접속하는 것을 막을 수 있습니다.
      • 포워드 프록시 서버를 사용하면 IP 주소를 역추적해도 프록시 서버만 보이기 때문에 유저의 정체를 숨겨주는 데 용이합니다.
  • 리버스 프록시 서버(reverse proxy server)란?
    • 포워드 프록시 서버는 클라이언트 앞에 놓여져 있는 반면, 리버스 프록시 서버는 아래 그림처럼 웹서버 앞에 놓여 있습니다.
    • 리버스 프록시 서버는 로드 밸런싱(load balancing)에 사용됩니다.
    • → 싱글 서버는 대량의 트래픽을 감당하기 어렵지만, 리버스 프록시 서버를 여러개의 서버 앞에 두면 특정 서버가 과부화 되지 않게 로드밸런싱이 가능합니다.
    • 리버스 프록시를 사용하면 보안에 좋습니다. 본래 서버의 IP 주소를 노출시킬 필요가 없어 DDoS 공격과 같은 공격을 막는데 유용합니다.
    • 대신 CDN과 같은 리버스 프록시 서버가 공격의 타겟이 될수는 있습니다.
    • 리버스 프록시 서버는 성능 향상을 위해 캐시 데이터를 저장할 수 있습니다. 그리고 캐싱되어 있는 데이터를 사용함으로써 더 빠른 성능을 보여줄 수 있다.
    • 마지막으로 SSL 암호화에 좋습니다. 원래는 비용이 많이 들지만, 리버스 프록시를 사용하면 들어오는 요청을 모두 복호화하고 나가는 응답을 암호화해주므로 클라이언트와 안전한 통신을 할수 있으며 본래 서버의 부담을 줄여줍니다.
  • 포워드 프록시 vs 리버스 프록시
    • 포워드 프록시 서버는 클라이언트 앞에 놓여져 있는 반면, 리버스 프록시 서버는 웹서버 앞에 놓여 있습니다.
    • 따라서 포워드 프록시 서버를 사용하면 클라이언트와 직접 통신하는 웹서버가 없습니다.
    • 반면 리버스 프록시 서버를 사용하면 웹서버와 직접 통신하는 클라이언트가 없습니다.
반응형
728x90
반응형

오늘 푼 알고리즘 문제는 답이 틀려서…ㅜㅜㅜ 낼 다시 풀어야 된다..

오늘 소설 퇴고하고 포폴 만든다고 새벽에 잠을 못 잤다.. 피곤… 저녁에 결국 자버렷구~

RDBMS랑 NoSQL도 공부했는데 아직 지식들이 머리에 산재해있는 느낌!

내일 한 번 더 공부해서 요약 정리하고 올려야겠다 싶더라

요약은 총 두 번 한다. 공부용 요약 하나, 대답용 요약 하나… 그리고 막상 면젖ㅂ 보면 머리가 새하얘져서 대답을 못하지…^^

스키마


  • 정의 : 데이터베이스에서 자료의 구조, 자료의 표현 방법, 자료 간의 관계를 형식 언어로 정의한 구조로, 데이터베이스의 구조와 제약조건에 관해 전반적인 명세를 기술한다.
  • 잘 설계된 스키마는 데이터 중복을 최소화하고, 테이블이 되지 않는 것을 방지한다.

인덱스


  • 추가적인 쓰기 작업과 저장 공간을 활용해 데이터베이스 테이블에 대한 검색 속도를 높여주는 자료 구조
  • 데이터와 데이터의 위치를 포함한 자료구조를 생성해 데이터를 빠르게 조회할 수 있다.
  • 데이터들에게 인덱스를 지정하면 지정한 인덱스 번호로 빠르게 데이터를 찾을 수 있도록 되어 있다.
  • 인덱스를 활용하면 데이터를 조회하는 SELECT 외에도 UPDATE나 DELETE의 성능이 함께 향상된다. ← 수정이나 삭제를 하려면 먼저 조회를 해야 하니까.
  • 관리
    1. INSERT : 새로운 데이터에 대한 인덱스를 추가
    2. DELETE: 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업을 진행
    3. UPDATE: 기존의 인덱스를 사용안함 처리하고, 갱신된 데이터에 대해 인덱스를 추가
  • 장점
    1. 테이블을 조회하는 속도와 그에 따른 성능 향상
    2. 전반적인 시스템 부하 감소
  • 단점
    1. 인덱스 관리를 위해 DB의 약 10%에 해당하는 저장공간 필요
    2. 인덱스를 관리하기 위해 추가 작업 필요
    3. 잘못 사용할 경우 오히려 성능 저하
    4. → CREATE, DELETE, UPDATE가 빈번한 속성에 인덱스를 걸게 되면 인덱스의 크기가 비대해져서 성능이 오히려 저하되는 역효과가 발생할 수 있다. UPDATE와 DELETE는 기존의 인덱스를 삭제하지 않고 '사용하지 않음' 처리를 해준다고 하였다. 만약 어떤 테이블에 UPDATE와 DELETE가 빈번하게 발생된다면 실제 데이터는 10만건이지만 인덱스는 100만 건이 넘어가게 되어, SQL문 처리 시 비대해진 인덱스에 의해 오히려 성능이 떨어지게 될 것이다.
  • 모든 요소에 인덱스를 걸지 않는 이유
  • → 인덱스 테이블이 생성되므로 메모리를 많이 소모하게 되고 Select를 제외한 Insert, Update, Delete에 대한 성능 저하 가능성이 있기 때문에 PK같은 컬럼들을 인덱싱 하도록 하는 것이 좋다.

수직적 확장과 수평적 확장


  • I/O란?
    • 입력(Input)/출력(Output)의 약자로, 컴퓨터 및 주변장치에 대하여 데이터를 전송하는 프로그램, 운영 혹은 장치를 일컫는 말
  • 데이터베이스에 데이터 요청시 문제점
    • CPU가 RAM 메모리에 데이터를 요청할 때 RAM에 적재되어 있는 데이터를 가져올 경우 I/O가 발생하지 않지만 하드디스크에서 데이터를 가져와야할 경우 I/O가 발생한다. 이를 페이지 교체가 일어난다고 하는데 속도가 현저히 떨어진다.
    • 해결방법 : 수직적 확장과 수평적 확장
  • 수직적 확장 : 서버 성능 향상
    • 장점
      1. 하나의 컴퓨터에서 데이터를 관리하기 때문에 데이터 쓰기(추가, 수정, 삭제)를 할 때 한번에 할 수 있다.
      2. 컴퓨터가 분산되어 있지 않아 동기화가 필요없어 데이터의 일관성이 유지된다.
    • 단점
      1. 하나의 컴퓨터에서 데이터를 관리하게 되면 RAM의 공간에 한계가 있으므로 결국에는 하드웨어에서 데이터를 가져오게 되는데 이 과정에서 I/O가 일어나기 때문에 데이터 읽기에서 성능이 떨어질 수 밖에 없다.
    • 활용
      1. 데이터 테이블이 서로 연계되어 있어 데이터 쓰기를 할 때 한번에 할 수 있는 RDB 방식의 데이터 모델에 적합하다.
      2. 주로 데이터 쓰기가 자주 일어나고 데이터의 정확성이 요구되는 정형화된 프로그램에서 도입된다.
  • 수평적 확장 : 서버 분산
    • 분산이란 데이터를 나누어 가지는 것이 아니라 같은 데이터를 복제하는 것을 의미한다.
    • 라우터에서는 각각의 레플리카의 가동 상태를 확인하여 최소한의 시간으로 데이터를 요청받을 수 있는 곳으로 보낸다.
    • 단점 : 은 데이터를 공유하고 있는 레플리카에서 데이터 쓰기가 일어날 경우 레플리카 간의 동기화로 데이터를 업데이트하는데 이는 동기화하는 과정에서 여러번 쓰기를 해야하고 동기화되는 시점에 따라 딜레이가 생겨 일관성이 유지되기 어려워진다.
    • 장점 : 하지만 동일한 데이터를 각각의 레플리카가 가지고 있기 때문에 읽기 속도는 매우 빨라진다.
    • 활용
      1. 데이터 테이블이 서로 연계되어 있는 RDB에서는 적합하지 않지만 컬렉션 사이의 관계가 없고 중복된 데이터를 가질 수 있는 NoSQL 방식의 데이터 모델에 적합하다.
      2. 주로 데이터의 정확성 보다 읽기 속도가 요구되고 쓰기보다 읽기가 자주 읽어나는 소셜 네트워크 서비스(SNS) 등에 도입된다.
반응형

+ Recent posts