티스토리 뷰
[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 책에 대해 디프만 16기에서 스터디에서 정리하며 남기는 글입니다.
스터디 GitHub : https://github.com/depromeet/16th-study-system-design-interview
GitHub - depromeet/16th-study-system-design-interview: :book: 가상 면접 사례로 배우는 대규모 시스템 설계 기
:book: 가상 면접 사례로 배우는 대규모 시스템 설계 기초 스터디 저장소. Contribute to depromeet/16th-study-system-design-interview development by creating an account on GitHub.
github.com
1장. 사용자 수에 따른 규모 확장성
클라가 요청하면 DNS 서버에서 IP 주소를 받아서 HTTP 요청을 하게 됨.
요청을 받은 웹 서버는 HTML 페이지나 JSON 형태의 응답을 반환함.
RDBMS는 자료를 테이블과 열, 칼럼으로 표현해 SQL을 사용해 데이터를 관계에 따라 join해 합칠 수 있다.
비관계형 데이터베이스 NoSQL은 여러가지가 있음.
그 중에서도 Key-Value Store, Document Store, Column Family Store, Graph Database가 있음.
비 관계형 DB가 적합한 경우
- 아주 낮은 응답 지연시간이 요구될 때
- 다루는 데이터가 비정형이랑 관계형 데이터가 아닐 때
- 데이터(JSON, XML, yaml)를 직렬화하거나 역직렬화 할 수 있기만 하면 될 때
- 아주 많은 양의 데이터를 저장할 필요가 있을 때
Q) 로그 같은 것들을 저장할 때 로그 파일을 관리하는 것과 NoSQL로 저장하는 것에서 각각의 장단점은?
- 파일 관리
- 파일로 관리하기 때문에 수정에 자유롭지가 않다.
- 여러 클라이언트가 접근할 때 문제가 생길 수 있다.
- 데이터 정합성 등
- NoSQL
- 속도가 매우 빠르다
- 여러 클라이언트가 접근에 문제가 없다.
- 파일 관리에 비해서 CRUD에서 자유롭다
- 키바나 등을 사용할 수 있어서 시각화 하는 데 유리하다.
- 중앙 집중화하기 편리해진다.
- 다양한 도메인과 서버에서 오는 로그들을 관리하고 체크하기 편리해진다.
스케일 업 : 수직적 확장
- 고사양 자원을 추가(더 좋은 CPU, 더 좋은 RAM 등)
스케일 아웃 : 수평적 확장
- 서버를 추가해 성능 개선
스케일 업은 단순해서 엄청 큰 장점임
단점
- 한 대의 서버에 CPU나 메모리를 무한대로 증설할 방법 X
- 장애에 대한 자동 복구 방안이나 다중화 방안을 제시하지 않음.
- 서버 장애 시 웹 사이트/앱이 완전 중단됨
로드밸런서
직접 서버로 들어가는 것이 아니라 로드밸런서 주소를 사용하고, 로드밸런서가 서버에 접근한다.
이때 보안을 위해 서버 통신에서는 private 주소를 사용할 수 있다.
DB 다중화
- Master-Slave 구조
Q) Slave 서버에 최신화 되기 전 읽을 수 있지 않나?
- 클러스터링 (active-stanby or active-active)
- 여러 DB를 수평적 구조로 구성해 시스템을 구축
- 동기 방식으로 노드들 간의 데이터를 동기화
- 동기화 시간으로 인해 리플리케이션에 비해 쓰기 성능이 낮음
- 리플리케이션 (master-slave)
- master
- DML(INSERT, UPDATE, DELETE) 쿼리를 처리
- Write-only
- slave
- Read-only
- 비동기 방식으로 노드들 간의 데이터를 동기화
- 지연 시간이 거의 없음
- 데이터 동기화가 보장되지 않아 일관성 있는 데이터를 얻지 못할 수 있음
- 데이터 양이 많으면 찾는 데 오래 걸림
- 마스터 노드 장애 시 복구&대처가 까다로움
- master
- 복제 지연의 원인과 해결
- 장기 실행 쿼리
- SBR(Statement Based Replication, SQL을 전송해 복제하는 방식)
- 복제본에서 replay 되는 시간으로 인해 지연시간이 2배가 된다
- 해결 방법
- RBR(Row Based Replication, 변경된 결과를 복제하는 방식)
- MBR(Mixed Based Replication, 비결정적 동작(Unsafed Statement)의 경우에만 RBR로 동작)
- SBR(Statement Based Replication, SQL을 전송해 복제하는 방식)
- 쓰기 쿼리량 증가
- 해결 방법
- Multi-Threaded Replication 설정을 통해 복제를 적용하는 worker 스레드 개수를 늘려 처리 속도 향상 가능
- 샤딩이나 도메인 자체를 분리해 경량화하는 것도 도움이 됨
- 해결 방법
- slave의 로드 증가
- 읽기 트래픽 증가로 인한 복제 지연
- 해결 방법
- 복제본을 추가해 해결
- 장기 실행 쿼리
- Semi-Sync Replication + MHA(Master High Availability)
- 반동기 복제 방식
- MHA(Master High Availability)를 통해 마스터 노드 장애 시 대처 가능
DB slave 서버가 master를 대체하기엔 최신 상태가 아닐 수 있음.
이때 없는 데이터는 복구 스크립트를 돌려서 추가해야함.
다중 마스터나 원형 다중화 방식을 도입하면 해결 가능하지만, 훨씬 복잡해진다.
응답 시간 개선
캐시를 붙이고 정적 파일을 CDN에 올려서 응답 시간을 개선할 수 있다.
Content Delivery Network(CDN)은 전 세계에 분산된 서버에 캐시를 저장해 두고, 사용자가 요청하면 가장 가까운 서버에서 응답을 받을 수 있게 해준다.
캐시는 비용이 높은 연산 결과나 자주 참조되는 데이터를 메모리 안에 두고 빠르게 처리될 수 있게 하는 저장소다.
요청을 받으면 우선 캐시에 있는지 확인함. 없을 경우 DB에서 읽어서 캐시에 저장한 뒤 반환함.
-> 읽기 주도형 캐시 전략
캐시는 데이터 갱신이 자주 일어나지 않으며 참조는 빈번한 경우에 고려해볼 만 하다.
영속적으로 저장해야할 데이터를 캐시에 두는 것도 바람직하지 않다.
캐시에 보관된 데이터에 대한 만료 정책도 마련해둬야 한다.
저장소의 원본을 갱신하는 연산과 캐시를 갱신하는 연산이 단일 트랜잭션으로 처리되지 않는 경우 일관성이 깨질 수 있다.
CDN을 통해서 정적 파일을 제공하면 응답 시간을 개선할 수 있다.
CDN은 전 세계에 분산된 서버에 캐시를 저장해 두고, 사용자가 요청하면 가장 가까운 서버에서 응답을 받을 수 있게 해준다.
클라는 CDN에 정적 파일을 요청하게 되고, CDN에 없을 경우 서버에서 CDN에 저장한 후 반환한다.
비용과 적절한 만료 시한 설정, CDN 장애, 컨텐츠 무효화에 대한 대처 방안 등을 고민해봐야 한다.
Stateless 웹 계층
수평적으로 확장할 경우 사용자 세션 데이터와 같은 상태 정보를 웹 계층에서 제거해야한다.
상태 정보를 RDMS나 NoSQL에 저장하고, 필요할 때만 가져오도록 해야한다. -> 무상태 웹 계층
-> 상태 정보에 의존적이게 돼서 기존 연결을 받던 서버에 종속됨.
-> 로드 밸런서로 고정 세션이라는 기능을 사용해서 설정할 수 있지만,
다중 데이터센터 아키텍처
- 트래픽 우회 : 올바른 데이터 센터로 트래픽을 보내는 효과적인 방법을 찾아야함. GeoDNS는 사용자에게서 가장 가까운 데이터 센터로 트래픽을 보내야함.
- 데이터 동기화 : 데이터 센터 간의 데이터가 동기화 되어야 함. 장애가 자동으로 복구되어 트래픽이 다른 DB로 우회되어도 데이터가 존재해야 함.
- 테스트와 배포 : 여러 위치에서 시스템이 구성됐을 때엔 웹 사이트 또는 애플리케이션을 여러 위치에서 정상 동작하는지 확인해야함. 자동화된 배포 도구로 모든 데이터 센터에 동일하게 서비스가 설치되도록 해야함.
메시지 큐
메시지 무손실을 보장하는 비동기 통신을 지원하는 컴포넌트. 메시지의 버퍼 역할을 하며, 비동기적으로 전송함.
메시지 큐는 생산자나 발생자라고 불리는 입력 서비스가 메시지를 만들어 메시지 큐에 발행하고, 소비자나 구독자라 불리는 서비스나 서버가 메시지를 받아서 그에 맞는 동작을 수행한다.
로그, 메트릭 그리고 자동화
- 로그 : 에러 로그를 모니터링하는 것은 중요한데, 단일 서비스로 모아주면 더욱 활용하기 편리할 것임.
- 메트릭 : 메트릭을 통해 사업 현황에 대한 유용한 정보를 얻거나, 시스템의 현제 상태를 쉽게 파악할 수 있음.
- 호스트 단위 메트릭 : CPU, 메모리, 디스크 I/O
- 종합 메트릭 : DB 계층의 성능, 캐시 계층의 성능 등
- 핵심 비즈니스 메트릭 : 일별 능동 사용자, 수익, 재방문 등
- 자동화 : CI/CD와 같은 도구를 사용하면 문제를 쉽게 감지할 수 있음.
- e.g) CI 과정에서 테스트를 거치게 하여 문제를 발견할 수 있게 함.
DB의 규모 확장
- 수직적 확장
- CPU나 RAM 등의 성능을 높임.
- 단일 서버의 한계에 도달하면 수평적 확장을 고려해야 함.
- SPOF(Single Point of Failure)가 발생할 수 있음.
- 수평적 확장, 샤딩
- 샤드는 같은 스키마를 사용하지만, 데이터의 중복은 없다.
- 샤딩 시에는 샤딩 키(파티션 키)를 어떻게 정하는지가 중요하다.
- 샤딩 도입 시 풀어야할 문제
- 데이터 재샤딩
- 샤드 하나로 감당이 어려울 때
- 특정 샤드에 할당된 공간 소모가 다른 샤드에 비해 빠를 때
- 유명인사(celebrity) 문제(핫스팟 키)
- 특정 샤드에 질의가 집중되어 서버에 과부하가 걸리는 문제
- 조인과 비정규화
- 여러 샤드에 걸친 데이터를 조인하기 힘들어짐
- 비정규화를 해 하나의 테이블에서 질의가 수행되도록하는 해결방법 등이 있다
- 여러 샤드에 걸친 데이터를 조인하기 힘들어짐
- 데이터 재샤딩
- 웹 계층은 무상태 계층으로
- 모든 계층에 다중화 도입
- 가능한 많은 데이터를 캐시
- 여러 데이터 센터 지원
- 정적 콘텐츠는 CDN을 통해 서비스
- 데이터 계층은 샤딩을 이용
- 각 계층은 독립적 서비스로 분할
- 시스템은 지속적으로 모니터링하고, 자동화 도구를 활용
Q) 단일 서버를 사용할 정도의 서비스라면 데이터 정합성이 발생하지 않을 것이라고 생각했음. 발생할 수 있는 데이터 정합성 문제가 있는가?
- 현재는 기억이 나지 않음.
- 다만, 이러한 질문을 면접에서 받는 다고 하면 100% 데이터 정합성 문제가 발생하지 않는 다고 보장할 수 있는지 먼저 재질의할 것 같음.
- 이후 데이터 정합성과 같은 문제점이 발생할 수 있다고 가정 후 좋은 해결 방법을 찾아볼 것 같음.
- 문제가 발생하더라도 바로 해결할 수 있도록
2장 - 개략적인 규모 추정
- 메모리는 빠르지만 디스크는 아직 느리다.
- 디스크 탐색은 가능한 피해야 한다.
- 단순한 압축 알고리즘은 빠르다.
- 데이터 전송 전 가능하면 압축해라
- 데이터 센터들 간의 데이터를 주고받는 데에는 시간이 걸린다.
QPS(Query Per Second) 추정치
- 가정
- 월간 능동 사용자(MAU) : 3억
- 50% 사용자가 트위터에 매일 접속
- 평균적으로 2회의 트윗을 올림.
- 10%는 미디어가 포함
- 데이터는 5년 간 보관
- 추정, QPS(Query Per Second) 추정치
- DAU = 3억 * 50% = 1.5억
- QPS = 1.5억 * 2 트윗 / 24시간 / 60분 / 60초 = 약 3500
- 최대 QPS = 2 * QPS = 약 7000
- 미디어 저장을 위한 저장소 요구량
- 평균 트윗 크기
- tweet_id에 64바이트
- 텍스트에 140바이트
- 미디어에 1MB
- 미디어 저장소 요구량 : 1.5억 * 2 * 10% * 1MB = 30TB / 일
- 5년간 미디어 보관을 위한 저장소 요구량 : 30TB * 365일 * 5년 = 55PB
- 평균 트윗 크기
팁
- 추정치를 계산할 때엔 정확한 값보다는 사고의 과정이 중요하다.
- 올바른 절차를 밟아가고 문제 해결 능력을 보여줘야함.
- 복잡한 계산은 어느정도 근사치를 활용해서 계산하라.
- 99987/9.1 같은 경우 100000/10 으로 해버려도 괜찮다.
- 가정을 적어둬라
- kb, mb 같은 단위를 작성해둬라
- QPS, 최대 QPS, 저장소 요구량, 캐시 요구량, 서버 수 같은 추정은 미리 연습해둬라.
추가적인 나의 의견
- 실무에서도 중요한 역량이라는 생각이 듦
- 특정 피크 상황에서 발생할 수 있는 트래픽이나 대비도 해야하기 때문에 개략적인 규모를 추정하는 것도 중요하다고 생각이 듦
- auto scaling도 만능은 아님.
- 인스턴스가 준비되는 데에도 시간이 걸리고, 이 지연 시간동안에 문제가 발생할 수 있음.
- 따라서 개략적인 규모를 예측하고 이를 대비해서 미리 인스턴스를 추가해두는 등의 작업이 필요함.
- 도움이 되는 지표
- 회사마다 다름
- 리퀘스트 요청 건 수를 체크
- 트랜잭션 수
- 과거 기록을 참고
- 작년 명절 등
3장 - 시스템 설계 면접 공략법
시스템 설계는 두 명의 동료가 모호한 문제를 풀기 위해 협력해 해결책을 찾아내는 과정에 대한 시뮬레이션이다.
- 시스템 설계 면접은 기술적 측면을 평가하는 것 이상이다.
- 협력에 적합한 사람인지
- 압박이 심한 상황도 잘 헤쳐 나갈 자질이 있는지
- 모호한 문제를 건설적으로 해결할 능력이 있는지
- 좋은 질문을 던질 능력이 있는지
- 부정적인 신호
- 설계의 순수성에 집착해 타협적 결정(tradeoff)를 고려하지 않아 over-engineering 하지 않았는지 등
- 시스템 전반의 비용이 올라간다.
- 완고함
- 편협함
면접을 위한 효과적인 4단계 접근법
1단계 문제 이해 및 설계 범위 확정
- 문제를 듣고 생각 없이 바로 답을 내지 말자.
- 요구 사항을 완전히 이해하지 않고 답을 내놓는 행위는 엄청난 부정적 신호다.
- 어려운 문제를 풀고 최종 설계를 바로 내 놓고 싶을 수 있지만, 잘못된 시스템을 설계하게 될 수 있다.
- 이를 위해서 올바른 질문을 하는 것이 중요하다.
- 적절한 가정
- 시스템 구축에 필요한 정보
- 구체적으로 어떤 기능을 만들어야 하는가?
- 제품의 사용자 수는 얼마나 되는가?
- 회사의 규모가 얼마나 빨리 커질 것이라 예상하는가?
- 3달, 6달, 1년 뒤 회사의 규모를 얼마 정도로 예측하는가?
- 회사가 사용하는 기술 스택은?
- 설계를 단순화하기 위해 활용할 수 있는 기존 서비스는 어떤 것이 있는가?
- 뉴스 피드 설계 시 피드가 역순으로 설계되어야 하나요? 특별한 정렬 기준이 있나요?
- 특별한 정렬 기준이 있을 경우 피드에 올라갈 포스트마다 다른 가중치가 부여되어야 하는가?
- 가까운 친구의 포스트가 사용자 그룹에 올라가는 포스트보다 더 중요하다거나 등
- 요구사항을 이해하고 모호함을 없애는 게 이 단계에서 가장 중요하다.
2단계 개략적인 설계안 제시 및 동의 구하기
- 개략적인 설계안을 제시하고 면접관의 동의를 얻는 것이 중요함.
- 면접관과 협력하며 진행하면 좋다.
- 설계안에 대한 최초 청사진을 제시하고 의견을 구하기.
- 면접관을 팀원처럼 대하고, 함께 설계하기.
- 화이트보드나 종이에 핵심 컴포넌트를 포함하는 다이어그램을 그리기.
- 클라이언트(모바일/웹), API, 웹 서버, 데이터 저장소, 캐시 CDN, 메시지 큐 등
- 이 설계안이 시스템 규모와 관련된 제약사항들을 만족하는지 개략적으로 계산해보기.
- 이러한 개략적 추정이 필요한지 면접관에게 미리 물어보기
- API 엔드포인트나 DB 스키마도 보여야하는가?
- 상황에 따라 다르다.
-'구글 검색 엔진을 설계하라'
- 상황에 따라 다르다.
3단계 상세 설계
- 달성한 목표
- 시스템에서 전반적으로 달성해야 할 목표와 기능 범위 확인
- 전체 설계의 개략적 청사진 마련
- 해당 청사진에 대한 면접관의 의견 청취
- 상세 설계에서 집중해야 할 영역들 확인
- 해야할 일
- 설계 대상 컴포넌트 사이의 우선순위를 면접관과 정해야 함
- 단축 url 생성기
- 해시 함수를 구체적으로 설명하는 것을 듣고 싶을 것임
- 채팅 시스템
- 지연시간 줄이는 방안
- 사용자 온/오프라인 상태 표시 등
- 단축 url 생성기
- 시간 관리도 주의할 것
- 불필요한 세부 사항에 너무 많은 시간을 사용하지 말 것
- 페이스북에서 뉴스 피드 순위를 매기는 알고리즘 등
- 불필요한 세부 사항에 너무 많은 시간을 사용하지 말 것
- 설계 대상 컴포넌트 사이의 우선순위를 면접관과 정해야 함
4단계 마무리
- 개선할 곳은 언제나 존재한다는 생각을 갖고 준비하도록 하라
- 만든 설계를 다시 요약해주는 것이 도움이 될 수도 있다.
- 오류(서버 오류, 네트워크 장애 등)가 발생했을 때 무슨 일이 생기는지 따져보라
- 운영 이슈에 대한 논의도 좋다
- 메트릭 수집, 모니터링, 로그, 어떻게 배포(roll-out)할 것인지 등
- 미래 규모 확장 요구에 대한 대처
- 시간 이슈로 다루지 못 한 세부적 개선 사항을 제안할 수 있다
해야할 것
- 질문을 통해 확인하기
- 문제의 요구 사항을 이해하기
- 정답이나 최선의 답은 없다는 것을 명심할 것
- 스타트 업과 중견 기업의 설계가 같을 리가 없다
- 면접관이 우리의 사고 흐름을 이해할 수 있게 소통하라
- 가능하다면 여러 해법을 함께 제시하라
- 개략적 설계에 면접관이 동의하면 세부 사항을 설명해라
- 중요한 컨포넌트부터 진행해라
- 면접관의 아이디어를 이끌어 내라
- 포기하지 마라
하지 말아야 할 것
- 전형적인 면접 문제도 대비하지 않고 면접장에 가지 마라
- 요구사항이나 가정들이 분명하지 않은 상태에서 설계를 제시하지 마라
- 처음부터 특정 컴포넌트의 세부사항을 너무 깊이 설명하지 마라
- 개략적인 설계를 마친 후 세부사항으로 나아가라
- 진행 중 막힐 경우 힌트를 청하기를 주저하지 마라
- 소통을 주저하지마라
- 침묵 속에서 설계를 진행하지 마라
- 설계를 내놓는 순간 면접이 끝난다고 생각하지 마라
- 의견을 일찍, 자주 구하라
시간 배분
- 시스템 설계 면접은 보통 45 ~ 1시간 정도로 충분하지 않을 수 있다.
- 대략적인 시간 분배 추정치
- 1단계 문제 이해 및 설계 범위 확정
- 3분 ~ 10분
- 2단계 개략적인 설계안 제시 및 동의 구하기
- 10분 ~ 15분
- 3단계 상세 설계
- 10분 ~ 25분
- 4단계 마무리
- 3분 ~ 5분
- 1단계 문제 이해 및 설계 범위 확정
가장 궁금한 능력은?
- 설득과 설명하는 능력이 가장 궁금한 것 같다.
- 설계를 잘 못 했더라도, 왜 그렇게 했는지 명확한 근거가 있으면 좋을 것 같음.
- 내가 설계한 게 있다면 그에 따른 이유가 존재할 것임.
- 무조건적인 수용보다는 자신감 있고 근거 있는 선택을 하면 좋을 것 같음.
'개발 > 개발 기타' 카테고리의 다른 글
[백엔드 로그, 모니터링 환경 구축] Grafana, Prometheus, Loki (0) | 2024.11.05 |
---|---|
바이너리 vs 바이트 차이점 (0) | 2023.09.19 |
[IntelliJ] intellij 단축키 정리 (0) | 2023.02.02 |
윈도우 포트 죽이기 (1) | 2022.09.21 |
Git Bash 명령어 - terminal(linux/mac) 기반의 명령어 (0) | 2022.08.24 |
- Total
- Today
- Yesterday
- 연합 동아리
- 후기
- server
- 알고리즘
- 디프만
- 15기
- 육지행
- 인프런
- 파이썬
- 10기
- 스터디
- 리빙랩
- it 동아리
- 육.지.행
- 회고
- 글또
- 1주차
- test
- 6팀
- 서버
- tdd
- AWS
- 해커톤
- python
- spring boot
- 중간발표
- 16기
- 글로컬
- 백엔드
- 프로그래머스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |