위 코드는 클래스 내부에 Meta 애트리뷰트가 있는지 확인하는 코드이다. 이를 메타클래스로 검증하는 코드를 짜보자
class ModelSerializerMetaclass(SerializerMetaclass):
def __new__(mcs, *args, **kwargs):
name, bases, namespace = args
if name not in ("ModelSerializer","HyperlinkedModelSerializer"):
mcs._check_meta(name,namespace)
return super().__new__(mcs, *args, **kwargs)
def _check_meta(name,namespace):
if not namespace.get("Meta", None):
raise Exception(f'Class {name} missing "Meta" attribute')
return
class ModelSerializer(Serializer, metaclass=ModelSerializerMetaclass):
pass
확장의 용이성MongoDB의 데이터 모델과 지속성 전략은 높은 읽기/쓰기 효율과 자동 장애조치를 통한 확장의 용이성을 염두에 두고 만들어졌다.
MongoDB는 웹 애플리케이션과 인터넷 기반을 위해 설계된 데이터베이스 관리 시스템이다.
직관적인 데이터 모델예를 들자면 아래에 사용자에 대한 정보를 몇 개의 필드로 저장한 도큐먼트가 있다.만약 하나의 사용자가 여러개의 이메일을 가질 수 있다면 어떻게 해야할까?하지만 MongoDB는 아래와 같이 사용하면 된다.예시와 같이 MongoDB는 한명의 사람 정보를 얻기 위해서 하나의 도큐먼트로 표현할 수 있다.
만약 RDBMS였다면 여러개의 테이블에 나눠져 있는 정보를 조인 연산으로 가득찬 SQL 쿼리를 만들어 표현했어야 할 것이다.
Web RTC는 웹, 앱 애플리케이션이 별도의 소프트웨어 없이 음성, 영상 미디어 혹은 텍스트, 파일같은 데이터를 브라우저 끼리 주고 받을 수 있게 만든 기술이다. WebRTC로 구성된 프로그램들은 별도의 플러그인이나 소프트웨어 없이 p2p 화상회의 및 데이터 공유를 한다.
→ 웹 브라우저 상에서 어떤 플러그인 없이 음성채팅은 물론이며 화상채팅, 데이터 교환까지고 가능하게 하는 기술
WebRTC 기술은 p2p 통신에 최적화 되어있다.
STUN
NAT 환경 클라이언트는 자기가 누구인지(내 공인 IP가 무엇인지) 모르기 때문에 라우터에 연결된 공인 IP를 알아내는 과정이 필요한데, 이를 STUN이 한다.
사설 IP를 가진 PC에서 요청을 보내면 라우터를 통해 인터넷 망으로 나온다. 이때는 라우터의 공인 IP로 변환되어 나오고ㅡ STUN 서버로 도착하면 패킷의 헤더를 읽어 IP와 포트를 테이블에 저장하는 동시에 응답으로 보냅니다. 이로써 PC는 자신이 속한 라우터의 공인 IP를 알게 되고 자신을 구별하는 포트번호를 알 수 있게 됩니다.
NAT(네트워크 주소 변환) 란
IP 패킷에 있는 출발지 및 목적지의 IP주소와 TCP/UDP 포트 숫자등을 바꿔 재기록하면서 네트워크 트래픽을 주고 받게 하는 기술
NAT를 쓰는 이유는
여러 대의 호스트가 하나의 공인 IP 주소를 사용하여 인터넷에 접속 할 수 있도록 하는데, 이런 방식을 사용하면
공인 IP 주소를 절약할 수 있으며
공개된 인터넷과 사설망 사이에 방화벽을 설치하여 외부 공격으로부터 사용자의 통신망을 보호할 수 있다.
시그널링 이란
RTC PeerConnection 통신에 사용할 프로토콜, 채널, 미디어 코덱 및 형식, 데이터 전송 방법, 라우팅 정보와 NAT 통과 방법을 포함한 통신 규격을 교환하기 위해 두 장치의 제어 정보를 교환하는 과정을 의미한다.
시그널링은 WebRTC 자체에서 지원하는 기능이 아니라, WebRTC 연결 전 미리 준비해야 하는 과정이다. WebRTC 자체의 스펙도 아니기 때문에, 한 가지로 딱 정해진 방법이 없다.
정해진 방법이 없는 이유는 알 수 없는 두 장치가 언제 어떤 방식으로 연결 될 수 있는 지의 모든 경우를 예측하는 것이 불가능하기 때문이다. 따라서 개발자는 자신에게 맞는 최적의 방법을 선택적으로 적용할 수 있다.
일반적으로 두 개의 장치를 연결 할 수 있는 시그널링 서버를 직접 구축하거나, 시그널링 서버를 제공해주는 외부 솔루션을 적용할 수 있다.
만약 직접 구축한다면 웹 소켓이나 서버 전송 이벤트 방법을 적용할 수 있다.
시그널링 정보를 조회할 수 있는 API를 만든 후 브라우저 단에서 주기적으로 XHR을 요청하는 폴링 기법을 쓸 수도 있다.
→ 웹 브라우저 상에서 어떤 플러그인 없이 음성채팅은 물론이며 화상채팅, 데이터 교환까지고 가능하게 하는 기술
WebRTC 기술은 p2p 통신에 최적화 되어있다.
P2P 통신이란?
P2P 연결방식
Peer to Peer 라는 뜻으로, 서버 없이 각 단말들이 서로 동등한 입장에서 통신을 하는 네트워크를 말한다.
하지만 여러명의 사용자가 접속하는 상황이 생겼다면, 접속중인 사용자 PC에게 엄청난 과부하를 줄 수 있다.
그렇기 때문에 1:N, M:N 통신에 최적화 되어있는 SFU 와 MCU를 사용한다.
SFU (Selective Forwording Unit)
SFU 연결방식
SFU는 1:N 연결에 최적화 되어 있다. 중앙 서버를 두고 클라이언트를 1명씩 중개해주는 역할을 한다.
PostgreSQL에서는 동시성 제어를 위해 여러가지 모드의 lock을 제공합니다. 이런 lock에도 여러가지 종류가 있고, 명시적으로 사용되는 경우/묵시적으로 사용되는 경우가 있는데, 자세히 알아보도록 합시다.
시작하기 전 3줄요약
Lock이 미치는 범위를 level로 나눈다
Lock 모드별로 충돌하는 관계가 존재한다
Lock은 트랜잭션 종료 시 혹은 롤백시에 풀린다.
lock이 미치는 범위를 Level로 나누는데, Table-Level Lock, Row-Level Lock, Page-Level Lock, Database-Level Lock 까지 다양하게 존재합니다. 해당 글에서는 Table-Level Lock과 Row-Level Lock 에 대해서만 설명하겠습니다.
Table-Level Lock
Table Level Lock은 테이블 수준에 락을 거는 방법입니다. 만약 테이블 내에 100개의 로우가 있다고 하면 하나의 로우에 접근하는 동안 나머지 99개의 로우에 접근 할 수 없기 때문에, 다중 사용자 환경에서는 사용하지 않는 편이 좋습니다. *(보통 테이블 전체 로우의 변경이 있는 DDL 구문과 함께 사용됩니다. (ex) TRUNCATE, ALTER)) *
이런 Table Level Lock은 LOCK 명령어를 이용해서 명시적으로 걸어줄 수도 있지만, 우리가 특정 쿼리문을 사용할 때 마다 암묵적으로 걸리게 됩니다. 어느 상황에 어느 락이 걸리는 지는 해당 문서를 보면 알 수 있습니다.
Row-Level Lock
Row-Level Lock은 row 수준에 락을 거는 방법입니다.
SELECT ~ FOR SHARE과 같은 DML 구문과 함께 가장 자주 사용되는 Lock입니다.
만약 이런 Lock 종류가 하나밖에 없다면, 여러 종류의 트랜잭션에서 lock을 알맞게 사용하기 어려워지는데요, 이런 상황을 처리하기 위해 Lock에는 Lock모드라는 것이 존재합니다.
Lock 모드?
Lock 모드 별로 서로 충돌하는 Lock 모드가 있으며, 충돌한다면 해당 리소스(table, row)에 동시에 접근할 수 없게 됩니다. ex)
ACCESS SHARE락은 ACCESS EXCLUSIVE 락과 충돌한다,
ROW SHARE락은 EXCLUSIVE, ACCESS EXCLUSIVE 락과 충돌한다
Table-Level Lock에는ACCESS SHARE, ROW SHARE 등, Row-Level Lock에는 FOR UPDATE, FOR UPDATE 등 여러가지 Lock 모드가 존재합니다. 이런 모드들의 이름은 일반적으로 사용되는 경우를 나타내지만, 모드마다 기능적으로 다른 점은 없습니다.
각 모드마다 차이점은 오직 "어떤 모드의 lock과 충돌하는가" 입니다. 부연설명하자면 충돌하는 lock 모드의 종류가 다른 것이 차이점이라고 볼 수 있겠습니다.
현재 재직중인 엘리스에서 이루고자 한 1분기 목적은 "내가 개발하는 서비스 플로우에 대한 완벽한 이해" 였다.
엘리스에서 내가 개발하는 서비스는 크게 3가지로 나뉜다.
엘리스 과목, 수업 자료, 계정 정보를 관리하는 Elice Core
외부 기관과 학습 관리 서비스 연동을 지원하는 LMS
채용 서비스를 제공하는 Elice Works
이 서비스들에 대한 이해도는 순서대로 30% 50% 80% 정도라고 생각한다. 측정 기준은 "각 엔드포인트가 어떤 로직으로 동작하는지 아는가" 이다.
이전에는 복잡한 엔드포인트들은 전혀 몰랐는데
WebSocket 메세지 타입 모듈화 작업
Worker api call 비동기 작업
두 작업을 진행하면서 이해하게 되었다.
진행했던 재밌던 일은, 아래와 같다
데이터 추출 자동화
운영팀에서 주기적으로 요청하는 데이터가 있는데, 이를 파이썬 schedule 라이브러리로 자동화했다. 이거에 대해서 아파치의 airflow같은 툴 혹은 프레임워크를 만들어볼까 생각을 했는데, 바빠져서 pending되었다. 내 할일 창고에 쌓아두고 빠른 시일내에 개발해야겠다.
🚧 개발
개발쪽 목표는 딱히 없었다. OKR에는 알고리즘 공부가 적혀있었지만 전혀 진행되지 않았다. 반성한다.
알고리즘 공부를 포기하고 내 분야에 대한 생각을 좀 더 하게 되었다. 내가 백엔드를 선택한 이유는
도달할 수 있는 한계점이 높다
성과에 따른 지표가 뚜렷하다
복잡한 아키텍처를 설계하고 구현해내면 항상 짜릿하다
이에 대해서 첨언하자면 실무에서 쿼리 튜닝을 진행해본 경험이 있었는데, 약 7배 정도 성능이 향상되는 것을 보고 백엔드는 성과 지표를 뚜렷히 나타낼 수 있구나라는걸 다시한번 느끼게 되었다.
그 외에도 몇가지 활동을 했다.
질문 아카이브
모르는 기술적인 문제가 있을 때마다 사수님들을 찾아가서 물어보는 것이 팀의 생산성을 떨어뜨리는 행위라고 생각했다. 그렇기 때문에 먼저 문제을 제대로 정의하고, 최대한 스스로 해결하기 위해 나만의 질문 템플릿을 만들어야 겠다고 생각했다.