개요
특정 시스템의 요구사항을 명세하고, 해당 시스템을 지원자에게 설계해보라고 하는 질문은 지원자의 커뮤니케이션 능력과 기본적인 CS지식의 깊이를 동시에 확인할 수 있는 질문입니다. 큰 종이 한 장을 주며 시스템의 전체적인 아키텍처를 그리라고 하는 질문을 받았을 때 꽤나 난감하기도 합니다.
시스템 설계에 대한 질문에서 중요한 포인트는 두 가지입니다.
- 지원자의 커뮤니케이션 능력
- 전체적인 아키텍처 지식
물론 더 중요한 것을 꼽으라면 지원자의 커뮤니케이션 능력이 더 중요하다고 볼 수 있겠네요. 지원자는 요구사항에 대해 끊임없이 질문자와 소통하며 시스템을 하나하나 구성해야 합니다. 주어진 요구사항은 설계하기에 충분하지 않을 가능성이 높습니다. 나머지 확실하지 않은 부분은 질문자와 계속해서 소통하며 채워 나아가야 합니다.
예시 질문
가장 기본적인 게시판 기능을 구현할 것입니다. 누구나 글을 쓰고 수정할 수 있는 게시판을 설계해주세요. 요구사항은 아래와 같습니다.
- 게시글은 누구나 쓸 수 있습니다. 로그인이 필요하지 않고, 글을 쓸 때 비밀번호를 입력하여 해당 글에 대한 접근(수정, 삭제)을 제한할 수 있습니다.
- 모든 게시글은 누구나 조회할 수 있습니다.
- 누구나 댓글을 작성할 수 있습니다. 댓글 또한 비밀번호로 수정과 삭제를 제한할 수 있습니다.
커뮤니케이션
시스템에 대한 설계를 요구하는 질문자는 특정 요구사항 명세를 지원자에게 전달할 것입니다. 이 요구사항은 설계를 진행하기에 충분하지 않을 가능성이 높습니다. 동시에 몇 명이 이용할 수 있어야 하는지, 특정 시간대에 몇 명이 몰리는지, 장비는 어떤 것을 사용할 수 있는지, 데이터의 정확도는 얼마나 높아야 하는지 등등은 계속해서 질문하며 알아내야 할 숙제입니다.
요구사항 재확인
요구사항을 전달받았다면 일단 자신이 이해한 요구사항이 맞는지 다시 확인해야 합니다. 특정 요구사항에 대해 자신도 모르는 사이에 '아 이거는 이 정도면 되겠지'라고 가정하는 것을 주의해야 합니다. 특정 부분에 대해 가정하게 되는 순간 이로 인해 전체적인 요구사항이 틀어질 수도 있습니다. 면접관에게 자신이 이해한 것이 맞는지 끊임없이 질문하고 확인하세요.
1. 게시판에 이미지를 저장해야 하나요?
2. 댓글에 대댓글 기능이 존재하나요? 그렇다면 몇 뎁스까지 허용하나요?
요구사항의 범위 한정시키기
해당 시스템이 어느 정도의 규모를 가져야 하는지 명확하게 한정시켜야 합니다. 동시에 10명이 접속하는 시스템과 동시에 10만 명이 접속하는 시스템은 당연하게도 전혀 다른 설계가 나옵니다. 시스템이 보장해야 하는 부분의 범위를 질문하고 한정시키세요. 아래와 같은 부분을 질문하면 좋습니다. 위 예시 질문을 받았을 때는 이런 질문을 할 수 있겠네요.
1. 동시에 몇 명이 이용하는 시스템인가요?
2. 확장이 필요한 시스템인가요?
3. 최근 데이터와 몇 분 이상의 오차까지 허용할 수 있나요?
4. 응답 시간은 얼마나 빨라야 하나요?
5. 사용 가능한 비용은 어느 정도인가요?
시스템의 흐름 그리기
종이 또는 화이트보드에 시스템 주요 부분을 그리는 것도 좋은 방법입니다. 해당 시스템이 어떤 흐름을 가지고 있는지 다이어그램을 그리는 것도 좋겠네요. 특정 사용자가 접속해서 게시글을 쓸 때 어떤 흐름을 가지고 진행할지 그려보세요.
위에서 한 질문을 토대로, 하나의 웹 서버와 여러 대의 WAS를 가진 서버를 설계하고 이 서버는 하나의 RDB와 하나의 Cache Server를 사용한다고 가정하고 그려보았습니다. 우선 대략적인 구조는 아래와 같겠네요. 색이 빨간색일수록 많은 Request를 받고 있다는 뜻입니다. 이러한 요구사항도 질문자와 커뮤니케이션을 통해 정해야 합니다.
해당 시스템 흐름을 그리면서도 계속해서 커뮤니케이션을 해야 합니다. 게시글에 답글 기능이 필요한지, 댓글에 대댓글을 달 수 있는지, 대댓글을 달 수 있다면 상위 댓글을 지웠을 때 하위 댓글이 모두 지워지는지 아니면 해당 댓글이 삭제 표시만 되는지 등을 확인할 수 있을 것입니다.
핵심 문제점 잡기
시스템 설계에 있어서 정답은 없습니다. 시스템 설계 시 고려할 수 있는 여러 사항중 하나를 높이면 나머지 사항이 부족해지는 경우가 적지 않습니다. 특히 비용(Cost)을 항상 고려하세요. 필요한 수준이 아닌 너무 완벽한 시스템을 설계하려고 한다면 엄청난 비용이 들 가능성이 생깁니다.
설계를 할 때 해결할 핵심적인 키워드를 잡으세요. 모두를 다 만족하기는 쉽지 않습니다. 예를 들어 Scalability를 높인다면, Cost 또한 올라갑니다. Availability를 높이면 Manageablility는 낮아질 수도 있습니다. 해당 시스템에서 어떤 특성을 중요시하는지 파악할 필요가 있습니다.
시스템에 대한 전체적인 윤곽이 잡혔다면 핵심적인 문제점을 잡아야 합니다. 게시판 서비스에 접속량과 게시글, 댓글 조회 서비스의 트래픽은 매우 많은 수준입니다. 우선 이 트래픽 문제를 짚어 봅시다.
확장성 (Scalability)
이 서비스의 트래픽이 특정 시간에만 몰린다면 그 시간대에 서비스를 잠시 확장하고, 나머지 시간에는 서버 규모를 조금 작게 운용해도 괜찮을 것입니다. 확장과 축소가 용이한 구조를 만드는 것을 고려해보세요.
확장성을 고려할 때 보통 두 가지 방법을 이야기합니다. 서버의 성능을 높이는 scale up과 서버를 분산시키는 scale out이 그 방법입니다. 사용자가 유동적이라면 서버를 언제든지 늘리고 줄일 수 있도록 scalability 한 구조로 만드세요.
scale up은 간단하고 효과적입니다. 그저 CPU를 추가하고 메모리를 늘려주면 되니까요. 하지만 일정 수준 이상으로 가면 추가할 장비는 점점 비싸지고 '가성비'가 안 나오는 시점이 옵니다.
scale out은 애플리케이션을 수평 확장합니다. 서버의 성능을 높이는 것이 아니라 서버를 여러 대로 늘립니다. 관리할 서버가 많아지니 관리 비용이 증가할 것이고, scale up보다 더 비싼 비용이 들 수도 있습니다.
요구사항을 파악하며 어떤 방식이 효과적일지 판단하고, 그 과정을 공유하세요.
가용성 (Availability)
해당 서비스가 항상 가용성을 유지하는지 파악해야 합니다. Google이나 Amazon과 같은 서비스들은 잠시라도 서비스가 멈추면 엄청난 손실을 입습니다. 해당 서비스도 높은 수준의 가용성을 요구할까요? 무중단 배포가 필요한 서비스인가요?
Queue
서버가 감당할 수 없는 많은 트래픽이 들어온다면 사용할 수 있는 방식 중 하나는 Queue를 사용하는 것입니다. 요청에 대해 Queue에 담아둔 후 서버가 감당할 수 있는 만큼만 꺼내서 요청 처리를 합니다. 서버가 요청을 감당할 수 없어서 돌연사하는 것을 막아주는 좋은 방법 중 하나입니다. 이를 처리하는 Queue를 MQ(Message Queue)라고 부르고 한 번쯤은 들어봤을 Kafka, Rabbit MQ 등이 이를 구현한 소스입니다. MQ에 대한 조금 더 자세한 내용은 여기를 참고해주세요.
Kubernetes
서비스의 가용성을 높이는 방법 중 최근 트렌드는 쿠버네티스를 도입하는 것입니다. 쿠버네티스는 애플리케이션이 멈췄을 때 빠르게 파악하여 애플리케이션을 되살려줍니다. 배포할 때도 멈추지 않고 배포하는 무중단 배포를 지원하고 여러 배포 전략을 사용할 수 있습니다. 물론 이 방법이 무조건 통하는 무적의 방법은 아닙니다. 쿠버네티스 자체를 관리하는 것도 높은 비용이 들고 인프라를 갖추는것도 쉽지 않습니다. 그러니 시스템 설계시 제안할 수 있는 하나의 수단 정도로 생각해주세요. 간단한 쿠버네티스 소개는 여기를 참고해주세요.
신뢰성 (Reliability)
애플리케이션에서 제공하는 정보가 항상 실시간 정보이고, 같은 요청에 같은 응답을 항상 줘야 하는지 파악해야 합니다. 신뢰성이 높다는 것은 데이터의 업데이트가 발생했을 때 바로 업데이트가 반영되어야 하고 저장된 데이터가 유실되지 않아야 합니다.
신뢰성을 높이기 위해 고려할만한 사항은 서버의 이중화입니다. 하나의 서버에 모든 데이터를 저장하다가 해당 서버에 장애가 발생한다면 신뢰 있는 서비스를 제공하기 어려울 것입니다. 여러 서버에 분산하여 백업 데이터를 저장하고 서버에 장애가 발생하거나 데이터가 유실된다면 백업된 데이터를 통해 복구할 수 있을 것입니다.
성능 (Performance)
성능에 대한 이야기를 한다면 웹 사이트를 조회할 때 얼마나 빠른 응답 시간을 가지고 있는지, 얼마나 많은 동시 접속자를 허용할 지에 대한 이야기가 될 수 있습니다. 현제 해당 시스템은 조회에 대한 트래픽이 높은 상태입니다. 고려할 수 있는 것은 scale up, scale out, cache, proxy, loadbalance 등이 있고 이중 어떤 방법을 적용할지, 어떤 것을 적용하지 않을지 고민해야 합니다.
캐싱을 한다면 데이터에 대한 정합성은 어느 정도 떨어지게 됩니다. 캐시 데이터를 조회하고 캐시에 저장한 후, 다음 캐시 데이터를 조회할 때까지 해당 데이터는 실시간으로 업데이트되는 신뢰성 있는 데이터라고 보기 어렵기 때문입니다. 대신 미리 캐싱해 둔 데이터를 반환함으로써 DB, 애플리케이션단의 부하를 줄일 수 있을 것이고 이는 더 많은 연산을 처리할 수 있게 됨을 뜻합니다.
마치며
시스템 설계에 대한 질문은 정답이 존재하지 않습니다. 특정 강점을 어떤 것을 가져갈지 정하고, 요구사항을 추출하며 시스템 설계를 요구한 질문자와 끊임없이 소통해야 합니다. 이 글에서 소개한 내용도 정답이 아닐 수 있습니다. 여러 가지 방법을 미리 알아두고 질문자에게 계속해서 질문하세요. 필요하다면 화이트보드와 종이를 활용하여 그리고, 서비스의 흐름을 파악한 후 어떤 문제점을 해결하는 것이 목표인지 잡고 가야 합니다.
References
'Web > Infra' 카테고리의 다른 글
도커와 가상머신, 그리고 OS (1) | 2020.08.29 |
---|---|
CI/CD 의 개념, 적용해본 후기 (5) | 2020.06.21 |
Kubernetes(쿠버네티스)를 소개합니다 (4) | 2020.05.31 |
Docker를 소개합니다 (2) | 2020.05.23 |
동기/비동기와 블로킹/논블로킹 (7) | 2020.05.08 |
댓글