이론 정리/대규모 시스템 설계

대규모 시스템 설계 공부 003

철매존 2022. 5. 1. 22:21
728x90

시스템 설계 면접 공략법

일단 시스템 설계 면접은

  • 면접에서 실제 서버에서 쓰이는 만큼 복잡하고 어려운 설계를 요구하지 않는다.
  • 설계 기술을 시연하고, 그 과정에서 결정들에 대한 방어 능력을 보이고, 면접관의 피드백을 건설적인 방법으로 처리할 자질이 있음을 보이는 자리이다.

따라서 해당 시스템 설계 면접에서 면접관이 찾고자 하는 것은

  1. 기술적 측면의 평가
  2. 지원자가 협력에 적합한 사람인지 평가
  3. 압박이 심한 상황도 잘 헤쳐나갈 자질이 있는지, 모호한 문제를 건설적으로 해결할 능력이 있는지 평가
  4. 좋은 질문을 던질 능력이 있는지 평가

이라고 한다.

또 한가지 중요한 것은 설계의 순수성(purity)에 집착한 나머지 타협적 결정(tradeoff)를 도외시하고 과도한 엔지니어링(over-engineering)을 하게 되는 엔지니어의 성형을 가지고 있는지를 파악하려 한다.

효과적 면접을 위한 4단계 접근법

시스템 설계 면접은 정해진 결말이나 정답이 없지만, 그 절차나 범위에는 공통적인 부분이 있다.

  1. 문제 이해 및 설계 범위 확정
  2. 개략적인 설계안 제시 및 동의 구하기
  3. 상세 설계
  4. 마무리

1. 문제 이해 및 설계 범위 확정

시스템 설계 면접을 볼 때에는 바로 답을 내놓아서는 안된다.
요구사항을 완전히 이해하지 않고 답을 내놓은 행위는 아주 엄청난 부정적 신호이다.
그러니까 답부터 내놓지 말고 깊이 생각하고 질문하여 요구사항과 가정을 분명히 해야 한다.

그럼 무슨 질문을 해야하나?

  • 구체적으로 어떤 기능을 만들어야 하나?
  • 제품 사용자 수는 얼마나 되나?
  • 회사의 규모는 얼마나 빨리 커지려나?
  • 회사의 주 기술 스택은 무엇인가?
  • 설계 단순화를 위하 활용 가능한 기존 서비스는 어떤 것들이 있나?

예를 들면 뉴스 피드 시스템을 설계하라는 요구를 받는다면?

 Q) 모바일 웹과 웹 앱 가운데 무엇을 지원해야 하는지?
 A) 둘 다

 Q) 가장 중요한 기능은?
 A) 새로운 포스트를 올리고, 다른 친구의 뉴스 피드를 볼 수 있도록 하는 기능

 Q) 정렬 기준은?
 A) 일단은 시간 역순으로

 Q) 한 사용자의 최대 친구 수
 A) 5000명

 Q) 트래픽 규모는?
 A) DAU(Daily Active User) 천만 명

 Q) 피드에 이미지나 비디오도 올라올 수 있는지? 아니면 그냥 텍스트인지?
 A) 미디어 파일도 포함

이런 식으로 모호함을 없애주어야 할 것이다.

2. 개략적인 설계안 제시 및 동의 구하기

2단계에서 중요한 것은 개략적인 설계안을 제시하고 면접관의 동의를 얻는 것이다.
2단계는 면접관과 협력하며 진행하면 좋다.

  • 설계안에 관한 최초 청사진을 제시하고 의견 구하기
    • 면접관을 마치 팀원인것처럼 대하라
  • 화이트보드나 종이에 핵심 컴포넌트를 포함하는 다이어그램 그리기
    • 클라이언트(모바일/웹), API, 웹 서버, DB, 캐시, CDN, 메시지 큐 등등
  • 이 최초 설계안이 시스템 규모에 관계된 제약사항들을 만족하는지 개략적으로 계산하기
    • 계산 과정은 소리내어 설명하고 이 추정이 필요한지 미리 질문하기
  • 가능하다면 시스템의 구체적 사용 사례도 몇 가지 살펴보기
    • 개략적 설계안을 잡는 대에 도움이 된다.
    • 또 고려하지 못한 edge case를 발견하는 데에도 도움이 된다.
  • 설계안 제시에서 API엔드포인트나 DB스키마를 보여줘야 하는지...
    • 큰 규모의 설계면 이걸 여기서 다루기는 지나치게 세부적일 것이다.
    • 작은 규모의 설계면 ㄱㅊ

이전 단계에서 설계 범위 이해를 마친 뉴스 피드 시스템 설게 질문을 그대로 활용하여, 개략적 설계를 만들어내는 방법을 살펴본다.

이 단계에서 시스템이 실제로 어덯게 동작하는지 이해할 필요는 없다.

개략적으로 보자면 이 설계는 두 가지 처리 flow로 나눠 생각해 볼 수 있다.

  • 피드 발행
    • 사용자가 포스트를 올리면 관련된 데이터가 캐시/데이터베이스에 기록되고, 해당 사용자의 친구 뉴스 피드에 뜨게 된다.
  • 피드 생성
    • 어떤 사용자의 뉴스 피드는 해당 사용자 친구들의 포스트를 시간 역순으로 정렬해서 만든다.

그림으로 나타내면 이런 식이다.

그림 3-1에서는 피드 발생이 일어나게 되는데,

  1. 사용자 단말에서 피드 발행을 보낸다.
  2. 로드 밸런서를 통해서 트래픽 분산을 해주면서 특정 웹 서버에 서비스 요청한다.
  3. 포스팅 저장 서비스에서는 DB에 포스트를 저장하고, 자주 사용되거나 무거운 정보를 캐시해준다.
  4. 포스팅 전송 서비스를 통해 새 포스팅을 친구의 뉴스 피드에 푸시한다..
  5. 알림 서비스를 통해 친구에게 보여준다.

11장을 보면 친구의 뉴스 피드에 새 포스팅을 푸시한다고 하는데, 최대 친구 수 5000명에 대해서 포스팅이 올라갈 때마다 푸시하는게 맞나 싶다....
일단 이런 방식으로 하는 이유는 최신글부터 보여주는 식으로 피드가 진행되기 때문에 새 글이 올라올 때마다 캐시로 보내주면 알아서 최신부터 되니까? 일것같기는 하다.

그림 3-2는 피드 생성이 일어난다.

  1. 사용자 단말에서 피드를 보려고 접속한다.
  2. 로드 밸런서를 통해서 트래픽 분산을 해주면서 특정 웹 서버에 서비스 요청한다.
  3. 3-1쪽에서 친구 쪽에 캐시된 뉴스 피드 캐시들을 가져와서 최신 포스트부터 정렬해서 피드를 생성한다.

스터디를 통해 의견을 나누어 보니 최신 글부터 보여주는 식이 아니여도 해당 방법을 사용하는 것이 낫다.
그 이유는 피드의 경우 모든 포스트의 데이터를 가지고 있는 것이 아니기 때문에 이미 이 자체가 데이터를 최적화 할 수 있기 때문.

3. 상세 설계

이전 단계에서까지 완성된 목표는 일단

  • 시스템에서 전반적으로 달성해야 할 목표와 기능 범위 확인
  • 전체 설계의 개략적 청사진 마련
  • 해당 청사진에 대한 면접관의 의견 청취
  • 상세 설계에서집중해야 할 영역등 확인

그러면 면접관과 해야 할 일은, 설계대상 컴포넌트 사이의 우선순위를 전하는 것이다.
예를 들어 면접관의 성향에 따라

  • 시스템의 성능 특성에 대한 질문을 던지고
    • 시스템의 병목 구간이나 자원 요구량 추정치에 초점이 맞추어져 있다.
  • 특정 컴포넌트의 세부사항에 대한 설명을 요구한다.
    • 단축 URL생성기 설계에 관한 질문의 경우
      • 해시 함수의 설계를 구체적으로 설명하는 것을 원할 것이다.
    • 채팅 시스템에 관한 문제의 경우
      • 지연시간을 줄이는 법과 사용자의 온/오프라인 상태의 표시 방법에 대해 듣고 싶을 것이다.

또, 시간 관리에도 주의를 기울여야 한다.
사소한 세부사항을 설명하느라 필요한 기술 설명을 말할 기회를 놓칠 수 있기 때문

다시 뉴스 피드로 되돌아와서, 이전까지의 개략적 설계를 마친 상태이다.

면접관이 이 설계에 만족하고 있다면, 이제 두 가지 중요한 용례를 보다 깊이 탐구해야 한다.

  1. 피드 발생

  1. 그래프 데이터베이스에서 친구 ID목록 가져오기. 그래프DB는 친구 관계나 친구 추천 관리에 적합하다.
  2. 사용자 정보 캐시에서 친구들의 정보 가져오기. 그리고 나를 차단했거나 피드를 받지 않기로 한 친구에게는 뉴스 피드가 보이지 않도록 해야 할 것이다.
  3. 친구 목록과 새 스토리의 포스팅 ID를 메시지 큐에 넣는다.
  4. 팬아웃 작업 서버가 메시지 큐에서 데이터를 꺼내어 뉴스 피드 데이터를 뉴스 피드 캐시에 넣는다.
    뉴스 피드 서버는 <포스팅ID, 사용자 ID>의 순서쌍을 보장하는 매핑 테이블이라 볼 수 있다. 따라서 새로운 포스팅이 만들어질 때마다 레코드가 추가된다.
    메모리 요구량을 줄이기 위해 필요한 정보들만 저장하고, 개시 크기를 제한한다.

그래프DB가 친구 관계나 추천 관리에 적합한 이유는
내가 알기로 RDB는 join이 발생할 때 마다 지수함수의 형태로 시간 복잡도가 늘어나고, GraphDB는 로그함수의 형태로 시간 복잡도가 늘어난다.
이는 GraphDB는 Data간의 관계를 직접 생성하고 이 관계를 그냥 횡단해서 필요한 데이터를 조회하기 때문이다.

  1. 뉴스 피드 가져오기

일단 미디어 컨텐츠는 CDN에 저장해서 바로바로 읽어올 수 있도록 해준다.

  1. 사용자가 피드를 읽기 위해 요청 생성
  2. 로드밸런서가 트래픽에 따라 특정 웹 서비스로 요청 전송
  3. 피드 로드를 위한 뉴스 피드 서비스 호출
  4. 뉴스 피드 서비스가 뉴스 피드 캐시에서 포스팅 ID목록을 가져옴
  5. 뉴스 피드에서 사용자 이름, 사진, 포스팅, 이미지 등을 사용자 캐시와 포스팅 캐시에서 가져와서 완전한 뉴스 피드 생성
  6. 생성된 뉴스 피드를 JSON형태로 클라이언트에 보낸다. 클라이언트는 해당 피드 렌더링

4. 마무리

이제 면접관이 후속 질문을 던질 수 있고, 혹은 스스로가 더 논의를 진행할 수 있는데, 이 때는 몇 가지 지침이 있다.

  1. 면접관이 시스템 병목구간이나, 더 개선 가능한 지점을 찾아내 달라 할 수 있음.

-> 당연하겠지만 아 완벽합니다~ 개선 필요 없습니다~ 이런 대답은 하지 말기
2. 만든 설계의 재요약 또한 도움이 될 수 있다.
-> 이는 여러 해결책을 제시한 경우에는 특히 중요하다. 여러 해결책을 제시하는 경우 당연히 시간이 오래 걸렸을 텐데, 이전의 내용들을 다시 환기시켜 주는 데에 도움이 된다.
3. 오류 발생 시 생길 문제(서버 오류, 네트워크 장애 등)를 따져보면 흥미로울 것이다.
4. 운영 이슈도 있다.
-> 메트릭 수집과 모니터링, 로그, 시스템 배포 등등..
5. 규모 확장 요구의 대처 방안도 생각하면 좋다.
-> 지금 설계가 100만명까지 감당 가능한데, 1000만명으로 늘어난다면?
6. 세부 개선사항의 제안도 괜찮다.

면접 세션에서 해야 할 것

  • 질문을 통해 확인한다.
    • 스스로 내린 가정이 옳다고 생각하지 말자.
  • 문제의 요구사항을 이해한다.
  • 정답이나 최선의 답안이 없다는 것을 명심한다.
  • 요구사항을 정확히 이해했는지 재확인한다.
  • 면접관이 내 사고 흐름을 이해할 수 있도록 한다.
  • 면접관과 소통하기
  • 가능하다면 여러 해법을 함께 제시한다.
  • 개략적 설계에 면접관이 동의하면 각 컴포넌트의 세부사항을 설명한다.
    • 컴포넌트 설명은 가장 중요한 것부터 진행하기
  • 면접관의 아이디어를 이끌어 낸다.
  • 포기하지 말쟈

면접 세션에서 하지 말아야 할 것

  • 아무 대비 없이 면접장에 가지 말기
  • 요구사항이나 가정을 분명히 하지 않은 상태로 설계 제시하지 말기
  • 처음에는 개략적 설계를 진행하기
    • 처음부터 특정 컴포넌트 설명을 진행하지 말기
  • 진행 중에 막혔다면 힌트를 청하기를 주저하지 말자
  • 소통을 주저하지 말자..
  • 설계안을 내놓는 순간이 면접 끝이 아니라 면접관이 끝났다고 해야 끝난거다.

시간 배분

그러면 만약에 45분 정도 주어지면...위의 1~4단계는 어떻게 시간을 배분하는게 좋을까?
대략적 추정치는 아래와 같다고 한다.

1단계 - 문제 이해 및 설계 범위 확정 : 3~10분
2단계 - 개략적 설계안 제시 및 동의 구하기 : 10~15분
3단계 - 상세 설계 : 10~25분
4단계 - 마무리 : 3~5분