목차

  1. 서론
  2. 개요
  3. 설계 과정
  4. 결론

서론

여러가지 요소들이 상호작용을 해서 동작하는 시스템을 작성하기 위해서 가장 먼저 해야 할 일들이 무엇인지에 대해 계획을 짜야합니다. 목표가 무엇인지부터 명확하게 정의하지 않으면, 어느 곳에도 도달하지 못하고 표류하게 될 것이기 때문입니다. 이런 목표를 달성하기 위해 계획을 세우는 시스템 설계 방법 중의 제가 사용하고 있는 설계 과정에 대해 이야기해보려고 합니다.

최근에 채팅 어플리케이션 프로젝트를 진행하면서 ‘일단 시작하고 보자’라는 생각으로 프로그램을 작성하기 시작한 적이 있습니다. 그랬더니 한발짝 나아갈 때마다 내가 지금 이 프로그램을 작성하는 것이 나중에 시스템이 다 구성됐을 때 목표한 대로 작동할 지에 대해서 확신할 수 없었습니다. 이 때문에 뭔가를 작성할 때마다 그것이 옳은지 검토하는 과정을 거쳐야만 했습니다. 그리고 이에 따라 구상도 변경되면서 지속적인 수정이 필요했습니다.

이러한 경험을 통해 프로그램을 작성하기 전에 시스템을 좀 더 체계적으로 설계하는 경험을 들어볼 기회가 있으면 비교적 적은 시행착오를 통해 목표한 시스템을 구현할 수 있을 것이라고 생각했습니다. 마침 이 때 추천받은 책이 “가상 면접 사례로 배우는 대규모 시스템 설계 기초”였습니다.

읽다보니 이를 제가 진행중인 프로젝트에 적용하는 방식을 정리하는 것이 좋겠다는 생각이 들었고, 되도록 다른 사람과 공유하고 싶다는 생각이 들어 이렇게 글을 작성하게 되었습니다. 이 글이 저와 비슷한 고민을 하며 답을 찾는 분들에게 도움이 되었으면 좋겠습니다.


개요

5가지 단계로 나눈 설계 과정을 제가 작성중인 ChatApplication의 예시를 들어 설명하고 있습니다. 해당 과정은 ‘요구사항 분석’, ‘설계 범위 결정’, ‘개략적인 설계’, ‘상세 설계’, ‘검토’로 나눌 수 있습니다.


설계 과정

시스템을 설계하는 과정은 크게 5가지로 나눌 수 있습니다.

1. 요구사항 분석.
2. 설계 범위 결정.
3. 개략적인 설계.
4. 상세 설계.
5. 검토.

요구사항 분석

요구사항을 분석할 때는 우선 문제를 정의해야 합니다. 제가 작성중인 채팅 어플리케이션을 예시로 들자면 다음과 같은 질문을 해볼 수 있습니다.

* 구체적으로 어떤 기능을 제공해야 하는가?
* 목표로 하는 수용 가능 제품 사용자 수는 얼마나 되는가?
* 주로 사용하는 기술 스택은 무엇인가?

이에 대해 저는 다음과 같은 답을 생각해냈습니다.

* 로그인, 채팅방 개설, 채팅방 입장, 메시지 전송, 메시지 수신, 채팅방 삭제 등의 기능을 제공해야 합니다.
* 사용자 수는 채팅방 당 최대 15,000명이라고 가정합니다.
* 주로 사용하는 기술 스택은 go, postgresql, redis, docker, azure 등입니다.

기능들 같은 경우는 다른 채팅방에서 일반적으로 제공하는 기능들을 기준으로 가장 기본적이라고 생각하는 것들을 작성했습니다. 사용자 수는 steam 인기 게임 기준으로 100위에 드는 게임의 동시접속자가 15,000여 명인 것을 기준으로 잡았습니다. 기술 스택은 동시성, 안정성, 확장성과 같은 부분들을 고려해서 선택했습니다.


설계 범위 결정

설계 범위를 결정할 때는 우선 설계의 목표를 설정해야 합니다. 제가 작성중인 채팅 어플리케이션을 예시로 들자면 다음과 같은 질문을 해볼 수 있습니다.

* 당장 작성하기 시작할 수 있는 기능은 무엇인가?
* 어떤 기능을 먼저 작성해야 하는가?
* 그 중요도는 무엇을 기준으로 선정해야 하는가?

이에 대해 저는 다음과 같은 답을 생각해냈습니다.

* 유저의 CRUD 기능을 먼저 작성하기 시작할 수 있습니다.
* 채팅방에서 공용으로 사용하게 될 모듈인 DBManager, SessionManager 등을 먼저 작성해야 합니다.
* 중요도는 이후에 변경이 있을 때 이를 검증할 수 있는 시스템과 다른 사람의 협업을 위한 시스템을 먼저 작성해야 합니다.

이래서 현재 가장 먼저 작성한 것은 User CRUD API인 login, logout, signup, delete 등의 기능입니다.

채팅방에서 공용으로 사용할 모듈은 재활용도가 높기 때문에 우선도가 높다고 판단해서 DBManager, SessionManager, PasswordManager을 작성했습니다.

unittest들을 작성하고, 이들을 자동으로 검증하기 위한 시스템으로 github action을 사용했습니다. 현재 github action은 소스 코드의 unittest 및 빌드를 자동으로 검증하고 있습니다.

또한 서버에 올려서 동작을 확인하기위한 containerizationorchestrization에 대한 작업을 진행하는 중입니다.


개략적인 설계

개략적인 설계는 일단 시작하기 위한 prototype이라 생각합니다. 제가 ChatApplication 프로젝트 readme에 작성한 개요와 같습니다. 제가 익숙한 기술스택 내에서 기능들에 어울린다고 가장 먼저 떠오르는 것들을 이용해서 작성했습니다.

이에 따른 최초 제 ChatApplication의 개략적인 설계는 다음과 같습니다.

메인 서버: go, gin
유저 관리 DB: postgresql
세션 관리: redis
메시지 큐: redis
채팅 데이터 DB: MongoDB
사용 서버: Azure

이에 대한 설계는 현재 진행중이며, 이를 통해 어떤 문제가 발생하는지, 어떤 문제를 해결해야 하는지에 대한 경험을 쌓고 있습니다. 현재 메시지 큐redis를 사용하는 것이 적절하지 않아 kafka를 사용하는 부분에 대해 고민하고 있으며, 클라우드 서비스 같은 경우도 gcp로 이전을 고민하고 있습니다.


상세 설계 및 검토

상세 설계는 개략적인 설계를 바탕으로 구체적인 기능들을 작성하는 것입니다. 이를 위해선 먼저 개략적인 설계를 바탕으로 작성한 기능들을 검토해야 합니다. 이를 위해선 다음과 같은 질문을 해볼 수 있습니다.

* 15,000명이라는 사용자를 넘어선 인원이 채팅방에 들어왔을 때 어떤 일이 일어나야 하는가?
* 유저 세션은 몇초 단위로 유지되어야 하고, 없어지는 경우에는 어떤 일이 일어나야 하는가?
* 채팅방에 유저가 들어왔을 때 어느 정도까지 이전의 메시지를 볼 수 있어야 하는가?

이에 대한 부분들은 아직 명확하게 답을 내리지 못했고, 검토의 과정을 포함해서 다른 사람의 의견을 참고하고자 해서 현재는 책을 읽고 다른 팀원을 모집해서 프로젝트를 진행하는 중입니다.


결론

시스템을 설계하는 과정은 크게 다음 5가지로 나눌 수 있습니다. 요구사항 분석, 설계 범위 결정, 개략적인 설계, 상세 설계, 검토입니다.

저는 해당 과정을 적용해서 진행하려는 채팅 어플리케이션을 설계하고 있는 중이며, 이를 통해 모자란 부분이 많지만 현재 프로젝트를 진행하고 있는 중입니다. 방향성이 틀린 부분이 있을 수 있지만, 방향을 일단 잡았기 때문에 이를 수정하는 것이 용이하고 앞으로도 계속해서 덜 틀린 방향으로 나아갈 수 있을 것이라 믿습니다. 그리고 그것이 설계 과정을 거치는 이유라고 생각합니다.


2024-03-12
다음 글: Docker를 이용한 유용한 빌드 방법 → 카테고리로 돌아가기 ↩