2월 한 달동안 팀 프로젝트에 참여했다! 5명의 팀원들과 기획, 설계, 구현하며 다양한 것들을 배울 수 있었다. 이번 게시글에서는 초기에 팀 프로젝트를 맡으며 어떤 고민과 결정을 경험했는지 기록하려고 한다!
참고 사이트: 네이버 e-sport
Legends of League 프로젝트는 리그 오브 레전드(LoL)과 관련된 종합 커뮤니트 사이트이다. 이 프로젝트는 LoL 시즌 게임의 요약 결과를 제공하고, 게임에 참가한 프로그래머(플레이어들)들에 대한 투표 기능을 포함하고 있다. 또한, Lol과 관련된 상품을 구매할 수 있는 쇼핑몰과, 간단한 채팅 기능도 지원한다.
참조한 플렛폼: 네이버 e-sport 오픈톡
이번 프로젝트에서 내가 맡은 도메인은 채팅이었다. 비전공자로 국비 교육을 통해 개발을 접하면서, 게시판 CRUD만 반복적으로 수행했기에 직접 채팅을 설계하고 구현하면서 새로운 분야에 대해 학습할 수 있을 것이라 기대했다.
나는 LoL이라는 게임을 잘 모르고, LoL을 기반으로 이뤄지는 LCK(League of Legends Champions Korea)에 대한 이해도도 떨어졌다.. 그래서 내가 주도적으로 채팅과 관련된 기획을 맡기 보다, 프로젝트 아이디어를 제안한 분의 의견을 반영하려고 노력했다.
- 여러 사용자가 동시에 접속하여 경기에 대해 자유롭게 토론할 수 있는 채팅방.
- 자신의 채팅과 다른 사용자의 채팅을 구분할 수 있으면 좋겠다.
- 일정기간 채팅 기록이 저장되었으면 좋겠다.
기획을 기반으로 정리해 본 세부 구현 사항은 아래와 같았다.
실시간, 다중, 양방향...? 세부 구현 사항에 나열된 단어들을 보고 완전 멘붕이었다. 지금까지 게시판 CRUD 프로젝트만 진행해오던 내게 생소하고 무서운 요구사항이었다.
네트워크와 관련된 배경 지식이 HTTP 프로토콜에만 제한되어 있어 발생한 의문점이었다. HTTP 프로토콜은 무상태(Stateless), 비연결성(connectionless), 단방향의 특성을 가지고 있다. 또한 하나의 request에 대해 하나의 response가 반환되면 두 통신 주체간의 연결이 끊기게 된다. HTTP가 아닌 다른 통신 프로토콜에 대한 지식이 없었던 나는, 실제로 채팅을 어떤 방식으로 구현해야 할지 전혀 짐작이 되지 않았다.
📖 학습 키워드: 소켓, TCP 프로토콜
소켓 프로그래밍을 통해 클라이언트와 서버가 연결을 유지하면서 양방향 통신을 할 수 있다. 따라서 클라이언트의 요청 없이도 서버에서 클라이언트로 메시지를 보내는 것이 가능해진다.
웹 게시판 프로젝트를 구현하며 동시에 접속하는 사용자에 대해 고민해본적 없었다. 웹 서비스에서는 WAS(Web Application Server)가 내부적으로 쓰레드 풀을 통해 동시 접속이 처리한다. 따라서 개발자는 싱글 쓰레드 프로그래밍을 하듯 코드를 개발할 수 있다. 그러나 채팅을 구현하기 위해서는 직접 여러 명의 사용자를 수용할 수 있는 멀티 쓰레드 코드를 직접 작성해야 한다. 따라서 피상적으로 이해하고 넘어갔던 멀티 쓰레드 개념을 학습 및 구현해야 했다.
📖 학습 키워드: 멀티쓰레딩
멀티스레딩을 이용해 서버에서 여러 클라이언트의 요청을 동시에 처리할 수 있다. 자바의 Thread 클래스를 통해 구현할 수 있다.
일시적으로 채팅을 보관할 저장소가 필요했는데, 전통적인 데이터베이스(DB)에 저장한다는 선택지가 매력적으로 느껴지지 않았다. 채팅은 대량의 중요도가 낮은 데이터들이고, 따라서 조금 더 가볍게 다룰 수 있어 보였다. 채팅을 보낼때마다 DB에 입력 쿼리가 들어가 데이터가 저장된다면 서버에 큰 부담이 될 것이다. 따라서 그동안 사용해오던 DB가 아니라 일시적으로 자료를 저장할 수 있는 다른 방법이 없는지 궁금했다.
📖 학습 키워드: Redis, 메모리 기반 데이터 저장소
redis와 같은 메모리 기반 데이터 저장소를 사용해 서버의 부담을 줄여줄 수 있다.
채팅 구현을 결심하고 찾아본 선택지를 대략적으로 정리해보면 아래와 같았다.
가장 기본적인 네트워크 통신을 위해 자바의 소켓 프로그래밍을 활용할 수 있다.
java.net.Socket
클래스와 java.net.ServerSocket
클래스를 사용해 구현할 수 있다.소켓을 웹 환경에 특화시킨 기술인 WebSocket은 HTML5 스펙의 일부로 더 쉬운 실시간, 양방향, 전이중 통신(Full-Duplex) 통신이 가능하도록 설계되었다.
STOMP는 WebSocket위에서 동작하는 메시징 프로토콜로, 헤더와 바디를 명확하게 구분하여 메시지를 단순화한 형태로 전송한다.
Redis는 다양한 데이터 구조를 지원하는 고성능 인메모리 데이터베이스다.
프로젝트가 React와 Spring을 기반으로 진행되고 있는 상황이었고, 이를 기반으로 채팅 프로젝트를 구현하기 위해 정보를 찾아보았다. 대부분의 채팅 프로젝트들이 WebSocket과 STOMP를 함께 사용하고 있었다. 스프링에서 WebSockt 위에 STOMP를 함께 사용하는 방식을 지원하기 때문인 것 같았다.
참고: Spring 공식문서에서 관련 내용을 확인할 수 있다.
직접 자바를 기반으로 채팅을 구현하는 것이 심도 깊은 학습에 도움이 될 것이다. 그러나 기간 내 팀 프로젝트를 성공적으로 마무리하기에 Spring에서 제공하는 WebSocket + STOMP API를 학습하고 활용하는 것이 더 좋다고 판단되었다. 또한 팀 내에 프론트엔드 개발자가 없어 프론트도 직접 해야 하는 상황을 고려해야 했다.
Spring과 React 프로젝트에서는 Spring에서 지원하는 WebSocket + STOMP를 사용하자!
네트워크 통신 및 다중 접속등의 개념을 다루면서 자바로 별도의 채팅을 구현해보자!