오늘의 교재와 키워드

교재

  • 운영체제(공룡책) : 1,2장
  • 가상 면접 사례로 배우는 대규모 시스템 설계 기초 : 1장 사용자 수에 따른 규모 확장성키워드캐시, 메모리, 커널, NoSQL, 로드밸런서, 데이터베이스 다중화, 메세지큐, 고가용성

스터디 내용

운영체제

  1. 레지스터와 캐시와 램의 차이?
    • 레지스터 : flip-flop(1bit)의 집합. 데이터와 명령어 저장. 최대 처리 용량은 CPU의 처리 용량을 따라간다.
    • 캐시 : CPU 내부에 존재하는 저장공간. 명령어를 저장하는 공간과 데이터를 저장하는 공간 둘로 구분. 또는 레벨별로 구분(L1,L2...)
    • 램 : CPU 외부에 존재하는 메모리, 버퍼의 역할(느린 저장장치를 보조), 여기까지가 주기억장치이고 휘발성.
  2. 커널의 정의
    시스템의 모든 것을 제어한다. 특징으로 보안, 자원관리, 그리고 추상화를 담당하고 있다. 커널의 종류는 위키피디아를 참조.
  3. Interface란?
    • 사전적인 정의
      • 전기 신호의 변환으로 중앙 처리 장치와 그 주변 장치를 서로 잇는 부분. 또는, 그 접속 장치.
      • 키보드나 디스플레이 등등 사람과 컴퓨터를 연결하는 장치
      • 소프트웨어끼리 접촉,공통되는 부분. 순화어는 '접속'
      • 위키피디아
        • 인터페이스, 또는 접속기는 서로 다른 두 개 이상의 독립된 컴퓨터 시스템 구성 요소 간에 정보를 교환하는 공유 경계(shared boundary)이다. 컴퓨터와 사용자 간의 통신이 가능하게 하는 장치나 프로그램을 의미하기도 한다.
  4. Runtime Environment란?
    컴퓨터가 실행되는 동안 프로세스나 프로그램을 위한 소프트웨어 서비스를 제공하는 가상 머신의 상태이다. 운영 체제 자체에 속하는 경우도 있고 운영 체제에서 작동하는 소프트웨어를 뜻할 수도 있다.
    => 프로그램을 실행시키기 위해 필요한 환경 혹은 상태
  5. (심화) JAVA의 정체성, 인터프리터와 컴파일러
    • 인터프리터의 정의 : 프로그래밍 언어의 소스 코드를 해석함과 동시에 실행시키는 프로그램 혹은 환경. OS종속적
    • 컴파일러의 정의 : 순화어 해석기, 번역기, 특정 프로그래밍 언어로 쓰여 있는 문서를 다른 언어로 옮기는 언어 번역 프로그램. (위키피디아). 흔하게 프로그래밍 언어를 컴퓨터가 이해하기 쉽게 기계어로 바꾸는 행위도 컴파일에 해당.
    • 자바는 인터프리터를 쓸까요, 컴파일러를 쓸까요?**
      • 정답 : 둘 다.
      • 설명 : .javac -> .class로 컴파일을 하고, class파일(byte코드)을 프로그램 실행 환경에 맞게 변환하면서 인터프리터를 사용한다.
      • 장점 : .class로 컴파일하면서 보안을 지킬 수 있고, 인터프리터를 사용하면서 그게 리눅스가 되었던, 맥이 되었던, 윈도우가 되었던 프로그램을 실행시킬 수 있다.(물론, 외부 코드에 의존성이 없다고 가정하면)
      • 단점 : 속도가 느리다

가상 면접 사례로 배우는 대규모 시스템 설계 기초

  1. RDBMS에서 지켜야 할 4가지 요소는?
    • Atomicity, Consistency, Isolation, Durability
  2. NoSQL의 종류는?
    • key-value : redis
    • graph : Neo4j
    • document store : MongGo DB
    • column store : Kassandra
  3. NoSQL에서 key-value방식과 문서저장소, 컬럼저장소의 차이는?
    • 문서저장소 : key-value 형식인데, 이제 이 value를 문서 타입으로 저장(json, xml 등의 표준들 또는 스키마가 정의된 구조가 존재하는 value)
    • Column store : Column store 그림 설명한 자료 row 내에 key(column)-value 데이터의 쌍이 있다고 생각하면 된다. 각 row는 key(column)의 수가 동일하지 않아도 된다. => 데이터 압축이 가능, 데이터 쓰는 데 용이
  4. NoSQL의 각 종류별 유리한 상황
    • key-value : 데이터 캐싱, 이미지와 오디오 파일 등 비정형 데이터 저장
    • document store : 속성 단위로 객체가 관리될 때, value에 json과 같은 계층을 가진 schema를 사용할 때(key-value에서 좀 더 나아가서)
    • Column store : 데이터 수정 작업이 많을 때, 디스크의 I/O 속도를 올릴 때 사용. RDBMS보다 메모리 사용에 이점이 있다.
  5. 로드밸런서의 역할은?
    • 트래픽을 다수의 서버에 분산시키는 장치이다.
    • 트래픽의 균등 배분과 고가용성 담당
    • 웹 서버 다중화와 연결된다.
    • Scale-out과는 다른 개념.
  6. 데이터베이스 다중화란? 샤딩이랑 같은 건가?
    서버 여러대를 중복 구성해서 일부가 장애가 되었을 때 시스템의 가용성을 유지하는 방법. 샤딩은 데이터 덩어리를 나누어서 저장하는 방법. 트래픽을 나누는 데 사용할 수 있다. 데이터베이스 다중화에는 replication을 사용한다.
  7. 메세지큐의 프로토콜은?
    • MQTT : Message Queue Telemetry Transport. Publisher-Subscriber 사이에 broker 존재. publisher와 subscriber는 topic을 공유한다.
    • AMQP : Advanced Message Queue Protocal. 중간에 Exchange라는 라우터가 존재(분배) Exchange와 message queue간의 매핑 룰을 binding이라 한다.
  8. 메세지큐의 특징은?
    • Asynchronous : Queue에 메시지 넣기 때문(우편 시스템을 생각해보라)
    • Decoupling : 양 끝 단과 분리 가능.
    • Resilience(탄력성) : 일부가 실패해도 전체는 영향을 받지 않는다
    • Redundancy(과잉) : 실패 시 반복 가능
    • Scalable : 다수의 프로세스들이 큐에 메세지를 보낼 수 있다
    • Guarantees : 작업이 처리된 것을 확인 가능
  9. Kafka와 RabbitMQ의 차이는?
    • RabbitMQ : 여러 소스에서 스트리밍 데이터를 수집하고 처리를 위해 다른 대상으로 라우팅하는 분산 메시지 브로커
    • Kafka : 실시간 데이터 파이프라인 및 스트리밍 애플리케이션을 구축하는 데 사용되는 스트리밍 플랫폼. 높은 처리량을 요구하는 실시간 데이터 피드 처리 혹은 대기 시간이 짧은 플랫폼 운영을 목표. 빅데이터, 스트리밍, 대용량.
    • 둘 다 사용처가 달라서 설계가 다르다. RabbitMQ의 경우 AMQP, Kafka는 MQTT방식을 채택하고 있다. 그리고 RabbitMQ는 메시지의 우선순위를 지원하나 Kafka는 그렇지 않다. 스트리밍이 메시지의 동등 취급에서 오는 말인가...
    • 차이점을 상세히 설명해둔 페이지AWS
  10. 메시지 큐의 장점 : 메세지큐의 특징을 읽어보세요
  11. 메시지 큐의 단점 : 큐를 사용하면서 큐 운영 규칙을 정해야 하고 지원이 필요하며, 큐에 메시지를 I/O하면서 오는 오버헤드가 발생할 수 있다. (좋은 것이 있다면 그에서 오는 나쁜 것이 있지...)
  12. 고가용성이란?
    시스템을 오랜 시간 동안 중단 없이 유지할 수 있는 능력

소감

  • 책을_미리미리_읽어_옵시다
  • 공룡책을 버리지 맙시다

20201231

 

글쓰기 시간, git에 대해서 배우는 시간, python jupyter notebook을 접한 날.

오후에는 git에 대해서 간략하게 내가 설명하는 시간을 가졌다. 내가 누구에게 설명할 자격이 있을까. 

 

20210104

 

오전시간 : fundamental node 수행 시간

 

파이썬의 기초에 대해서 다루는 노드였는데, 의외로 어려운 개념들이 있었다. 

 

1. 부동소수점 표현방식

IEEE의 표준을 따라서 bias를 채택해서 부동소수점을 표현하는 방식을 사용하면 다음과 같이 부동소수점을 bit에 담게 된다. 

1비트는 부호, 8비트는 지수, 32비트는 가수부에 사용된다. 

그리고 지수값을 저장할 때, 지수값을 2의 보수법으로 바꾸고 거기에 bias(127)을 더한다. bias는 2^8-1의 값. 

thrillfighter.tistory.com/349

2. 0.1 + 0.2 == 0.3 의 결과

놀랍게도 false였다. 왜냐면 1의 부동소수점 표현방식 때문에 처음에는 literal type으로 선언된 float이

계산하면서 0.3의 근접한 값을 가지게 되면서 literal 0.3과 값이 달라지게 되는 것이다.

여기에서 실제로 저 값을 계산하게 되면 0.300000000004쯤의 값을 보게 된다. 

 

 

오후 시간 : C231N 3강 ~54p

2강에 대해서 복습하고 있는 시간. 

 

C231N 3강

 

저번에는 함수 f(x) -> y를 다룰 때, f에 W가 사용된다는 것 까지 도출함. 

그렇다면 구한 W가 적합한지 아닌지 스코어를 어떻게 구해내는가?

Loss-function에 대한 소개를 할 것이다. 

임의의 값 W가 적합한지를 찾고 싶은데, 이 과정을 최적화 과정이라고 한다.

 

Loss function은 이 W를 가지고 학습했을 때 라벨과 학습 결과를 비교하고 distance를 구해서,

각 경우의 값들을 모두 합해서 평균을 내는 일을 한다. Loss function의 결과를 줄이는 것이 목표. 

 

multi-class SVM : 여러 class를 다루기 위한 SVM 

어떻게 loss를 구하는가?

 

Loss function은 이 W를 가지고 학습했을 때 라벨과 학습 결과를 비교하고 distance를 구해서,

각 경우의 값들을 모두 합해서 평균을 내는 일을 한다. Loss function의 결과를 줄이는 것이 목표. 

 

정답이 아닌 클래스 스코어에 대해서

sum(max( 해당 클래스의 스코어 - 원래 클래스의 스코어 + 1 , 0 ))

 

근데 safety margin이 왜 1인가?

정답 스코어가 다른 스코어에 비해 얼마나 더 높은 값을 가지고 있느냐에 관심을 가지고 있기 때문에

(loss값이 얼마나 되는가), 

1은 별로 상관없어지고, W 행렬곱을 하기 때문에 나중에 사라진다. 

Q. 1을 주는 이유가 값을 보정하기 위해서 주는 걸까...?

Q. 정답 스코어는 왜 빠지는데요? 

A. loss function에 영향을 줄 수도 있기 때문에. 

 

L이 0이 나오더라도 W는 하나가 아닐수 있다. 2W도 답이 될 수 있다. 

최종적으로 test data에서 L이 적게 나오는 W을 구해야 한다. 

 

Regularization : L이 단순한 값을 가질 수 있도록 정리하는 역할. => 모델이 복잡해 지는 것을 막고, 복잡한 모델에 패널티를 부여하는 역할

가정 : 더 단순한 가정이 미래에 일어날 현상을 잘 설명할 수 있기 때문에, 단순한 가정을 택하는 것이 좋다. 

overfitting을 막을 수 있다. 

이 항이 있으면 저차원 모델 + soft penalty(복잡하게 나오는 모델 계속 쓰게 되면, 불리하게 된다..?)를 추가하는 것이 된다. 

 

L2 regularization : 선형 함수를 유도하기 위한 패널티

L1 regularization : -> 단순한 모델에 적합하다. 

 

cf) softmax도 자주 쓰인다. (Multinomial Logistic Regression) -> loss값에 의미를 부여하게 된다. 

loss값을 확률 분포로 구하게 된다. 정확히 예측했다면 L이 1이 나오겠지. 

exponential -> normalize과정을 거쳐 loss값을 구하게 된다. 

softmax의 최소값은 0이고 최대값은 무한대이다. 하지만 최대값이 무한대가 나올 일이 없는게, 그러면 L값이 0에 근접해야 한다. 

 

SVM에서는 정답 스코어와 아닌 값의 차이에 대해 다루고, softmax는 -log(정답 클래스)을 도출해서 해당 클래스로 분류될 확률값을 다루게 된다. softmax의 경우 정답 클래스의 결과를 최대한 높이고, 나머지 클래스의 결과를 최대한 낮추려고 한다. 

SVM은 일정 마진을 넘으면 ok인데 softmax의 경우는 계속해서 최적화하는 방향으로 나아갈 것이다. 

 

그렇다면 실제로 어떻게 W를 구할 것인가? 

=> Optimization 

 

(추후 보강 예정)

 

 

 

 

 

 

 

 

 

'Technology > AIFFEL 대전' 카테고리의 다른 글

[AIFFEL] DAY 3  (9) 2020.12.30
[AIFFEL] DAY 1-2  (6) 2020.12.30

20201230

 

오늘은 Fundamental node 1을 진행하는 시간!

 

운영체제란 무엇일까? 에 대해서 먼저 학습하고 진행하는 시간을 가졌다.

선생님이 말씀하시는 운영체제의 정의는 다음과 같다.

 

<운영체제란>

 

1. 컴퓨터의 하드웨어를 관리하는 역할

2. 작업 , 데이터, 프로그램 관리 및 제어 등 모든 컴퓨터가 공통적으로 수행해야 할 복잡하고 다양한 기능들을 모아 만든 소프트웨어이다.  (모든 컴퓨터가 공통적으로 수행해야 할...? 이게 좀 애매하긴 하다. 컴퓨터의 수준에 따라 기대되는 기능들이 다르기 때문이다.)

3. 컴퓨터의 구조와 동작원리를 몰라도 컴퓨터 자원을 사용하도록 도와주는 프로그램이다.

 

-언어의 특징에 대해서 알아보자..!

 

www.youtube.com/watch?v=j5ogDOuqXqg&feature=emb_title

연봉이 높은 프로그래밍 언어의 특징 :

함수형 언어, parallelism(병렬성), concurrency(병행성)에 능하다..!

 

-리눅스 명령어

whoami

pwd

 

-'ls -al'을 입력했을 때 어떤 정보가 출력되는가?

www.leafcats.com/137

 

- conda cheet sheet

docs.conda.io/projects/conda/en/4.6.0/_downloads/52a95608c49671267e40c689e0bc00ca/conda-cheatsheet.pdf

오후에는 cs231n Image Classification

 

Numpy -> vecterization computing.

 

<How to classifiy Image?>

시스템에 우리가 미리 정해놓은 카테고리 존재 -> 컴퓨터는 이미지를 보고 어떤 카테고리에 이미지를 분류할지 고름

 

컴퓨터가 이미지를 인식하는 방법과 이미지 인식에서 고려해야 할 점들. Sementic Gap

1. 컴퓨터는 픽셀을 RGB를 각각 채널로 받아들여 숫자값(0-255)으로 분류한다. 이러면 고려해야 할 값들의 갯수는 800x600x3으로 채널이 생성되게 된다.

2. 이때 주의해야 할 점 : View point variation, Illumination, Deformation(모양이 달라짐), Occlusion, background clutter(배경과 객체가 비슷함), Intraclass variation(여러가지 고양이의 종) 등이 있다.

 

 

<An image classifier>

-사람들이 해왔던 시도 : 이미지에서 경계선 잡음 -> corner를 찾음 -> ...? 이거 좀 비효율적인데? 확장성도 없어!

-Data-Driven Approach : 일단 표본을 수집한다(이미 구분이 되는 이미지). ->  ML classifier를 학습시킨다.

=> Training과 Test 단계가 생긴다.

 

<Nearest Neighbor on Image Classification>

Nearest Neighbor : 모든 데이터 및 레이블들을 기억한다 -> Test 데이터가 들어오면 데이터들과 비교해서 분류한다.

 

사용 데이터 : www.cs.toronto.edu/~kriz/cifar.html

Distance Metric : 이미지를 비교하기 위해 픽셀의 매트릭스 간의 차이를 비교한다.

L1 distance도 꽤 잘 작동한다.

 

cf)

원래 L1 distance가 좌표계에서 등장하는 용어인데요, 쉽게 생각해서 거리를 측정하는 방법이구요, 맨해튼 거리는 맨해튼 거리가 격자 모양으로 조성이 되어 있고, 두 지점간의 거리를 잴 때 가로 세로 막대기만 사용해서 측정하는 것을 의미합니다. L2는 우리가 아는 두 지점 사이의 직선 거리를 재는 방식이 됩니다.

 

근데 NN에서 Big O Notation 등장. Training에서는 O(1), Predict에서는 O(N)이 걸린다. O(1)은 그냥 기억하면 되니까, O(N)은 이미지를 분류하기 위해서 모든 이미지랑 비교해야 하기 때문에 이렇게 걸린다..!

cf) 정확하게 얘기하면 O(A), O(BN) (A, B는 상수) 인데, A는 한 이미지를 기억하는데에 걸리는 시간, B는 한 이미지를 대조하는데에 걸리는 시간. Big O 표기법에서는 상수를 생략한다.

 

K-NN : K개의 가까운 이웃을 찾는다. 그리고 majority vote를 실시한다! K 값은 1보다 커야...

2차원에서 커버하지 못한 지역이 생긴다면 어떻게 처리하는가? : 분류를 하지 않거나, 다른 규정방법이 있겠지.

 

L1 distance와 L2 distance 모두 Distance Metric이다.

여기서는 좌표계에서의 L1과 L2 distance의 정의를 언급함.

좌표계 중요(회전하면 값이 바뀐다.), 요소간의 실질적인 의미를 안다 -> L1

좌표계 변해도 영향을 받지 않는다. 요소간의 실질적인 의미를 잘 모르겠다 -> L2 <= 얘를 더 자주 쓴다.

 

KNN 쓸려면 L1 쓸건지 L2쓸건지만 정해주기.

 

Hyperparameters : 알고리즘이 학습으로 정하는 것이 아니라, 우리가 미리 정해서 알고리즘에 입력하는 파라미터

데이터 집합 마다 다르다.

 

물론 train set에서 학습시킬 수도 있지만...이렇게 되면 train set에 overfitting이 될 수 있어 test set에서의 성능을 보장할 수 없다.

- 일반적인 방법 : training, validation, test 이렇게 셋으로.

train에서 학습 > validation에서 검증 > 검증 결과가 좋은 모델을 가지고 test에서 성능 측정을 한다.

모든 데이터 셋이 그렇듯, train > validation > test set으로 갈수록 공평성을 요구한다.

 

cross validation : 데이터 셋을 여러 그룹으로 나누고, training - validation을 번갈아가면서 한다.

 

training set 과 validation set의 차이!! : training에서는 레이블 학습, validation에서는 정확도를 확인한다. 그러니까 알고리즘이 얼마나 잘 작동하는지 검증하는 set.

 

validation 과정에서 k-fold cross validation이 도움이 될 수 있다.

근데 KNN은 이미지 분류에서 잘 안 쓴다.

1. test 시간이 너무 오래 걸린다.

2. pixel에 대해 Distance metrics를 적용한 결과가 썩 의미있진 않다.이건 이미지가 가지는 특징때문이다.(위에서 이미지를 학습할 때 고려할 사항 참고)

 

-Curse of dimensionality : 속성 하나 하나를 차원의 수에 매칭할 때, 차원을 커버하려면 그 차원을 채울 수 있는 수의 데이터를 가져와야 한다.

https://datapedia.tistory.com/15

 

[빅데이터] 차원의 저주(The curse of dimensionality)

차원의 저주란, *데이터 학습을 위해 차원이 증가하면서 학습데이터 수가 차원의 수보다 적어져 성능이 저하되는 현상. *차원이 증가할 수록 개별 차원 내 학습할 데이터 수가 적어지는(sparse) 현

datapedia.tistory.com

<Linear Classification on Image Classification>

Linear Classification들을 쌓아서 CNN을 만들수도 있다.

예시 : Image Captioni -> 이미지가 입력, 사진의 설명이 출력.

 

image -> f(x,W) -> 각각의 카테고리가 내놓은 score

W : parameters 또는 weight

 

Linear classification에서는 데이터와 가중치를 곱해버려서 융합한다.

Wx + b => bias를 주어서 어느 class에 가중치를 준다. W은 class 수만큼의 열을 가지는 행렬이다.

 

나중에 neural network를 구축할 때, W를 구하는 방향으로 가게 된다.

x -> y일 때, f는 뭘까? 이를 학습을 통해 개선하면 된다.

 

Linear classifier는 각 클래스에 대해 하나의 템플릿만을 학습해서 도출한다. 다양한 속성을 반영할 수가 없다.

ex) 말 그림을 학습시키는데, 말이 항상 풀밭에 서있으리라고 기대할 수가 없다.

 

선형 분류기는 각 클래스 간을 선형으로 구분한다. 하지만 클래스를 선형으로 구분하지 못하는 문제가 존재할 수 있다.

parity problem(홀/짝 구분)

mutimodel problem(한 클래스가 좌표계 내에서 다양한 공간에 분포하는 경우)

 

후기

 

학부때 막연히 주입식으로 들었던 내용들을 '왜'라는 질문과 함께 듣게 되니 훨씬 더 지식이 풍부해지는 느낌이다.

근데 이거 더 효율적으로 진행하려면 죽이 되던 밥이 되던 한번 듣고 와야할듯...

내가 모르는 내용들이 나오면 즉석에서 이해 못하고 넘어갈것 같아서 좀 걱정된다.

지금은 내가 아는 내용이 대부분이고 진짜 궁금한게 한두개라서 질문에 집중할 수 있어서 좋지만... 

'Technology > AIFFEL 대전' 카테고리의 다른 글

[AIFFEL] DAY 4,5  (0) 2021.01.05
[AIFFEL] DAY 1-2  (6) 2020.12.30

6개월간 AIFFEL 대전에서 수업을 듣게 됬다. 

원래는 깃헙 블로그를 구축하려고 했는데, 체력이 도저히 되지 않아서 

당분간은 티스토리에 정리할 예정이다. 

 

20201228

 

원래 이 교육은 오프라인으로 진행되지만, 코로나의 여파로 온라인으로 진행하게 되었다. 

언제 전환될지 모른다. 

코로나. 힘든 시기에 전직을 위해 이 길을 선택했다. 잘 할수 있을까. 

 

첫 날은 그래서 대전으로 가서 노트북과 교재를 수령했다. 

노트북은 한달 뒤에 새 모델로 교체 예정. 

교재는 '파이썬 알고리즘 인터뷰 95가지 알고리즘 문제 풀이로 완성하는 코딩 테스트'를 받았다.

 

날이 맑다. 퍼실님들도 선생님들도 잘 부탁드립니다. 

 

20201229

 

해당 교육은 LMS(Learning Management System)을 통해서 이루어진다. 

Fundamental 과정과 Expert과정이 같이 진행된다고 한다. 

오늘은 Fundamental node 0(한 학습 과정을 노드라고 부른다.)에서 환경 설정을 했다. 

강의 순서가 좀 독특하다. '지금 하라는 데로 실행하면 안될거에요. 그럼 왜 그런지 알아볼까요~'의 연속이기 때문에, 

무턱대고 실행하면 안되는 경우가 있다. 그러니 각 페이지를 찬찬히 읽어보고 진행하는게 중요할 듯 하다. 

오늘은 아나콘다를 깔고, 가상 환경을 만들고, 앞으로의 학습에 필요한 패키지들을 설치하는 과정이었기에 간략하게 쓴다.

- 패키지에서 tensorflow와 tenworflow-gpu는 다르고, 의존성 또한 다르기 때문에 환경에 맞게 둘 중 하나를 신중하게 고를 것. 

- 로컬에 구축한 가상 환경에서 서버를 띄우고, LMS는 이 로컬 서버에 접속해서 자원을 사용하는 방식을 택하였다. 

 

언제나 느끼지만, 모든 과정에서 환경 설정은 어렵다. 

그리고 오늘 사용했던 명령어들이 왜 이런 옵션을 함께 사용하는지 파악한다면 많은 것을 얻어갈 수 있을 것이다. 

 

내일은 또 어떤 과정들이 기다리고 있을까.

아까 OT때 들어보니까 제일 처음 열린 아이펠 강남의 졸업률이 생각보다 낮아서 놀랐다. 다들 AI에 대해서 어느정도 알던, 모르던, 잘 화합하면서 참가했으면 한다.  

 

 

 

 

 

'Technology > AIFFEL 대전' 카테고리의 다른 글

[AIFFEL] DAY 4,5  (0) 2021.01.05
[AIFFEL] DAY 3  (9) 2020.12.30

+ Recent posts