TL;DR

  1. 채팅 예제를 만들어 본 후기
  2. 문서, 코드? 흥미 driven 개발.
  3. 채팅 예제 만들기 2 기대 요망.

채팅 예제 만들기

왜 와이

실력에 대한 고민을 하면서

저는 스스로를 반쪽짜리라고 생각해 왔습니다. 경험도, 지식도 부족한 반쪽짜리 개발자. 그래서 고민을 오래한 것 같습니다. 과연 잘하는 개발자란 무엇인가. 업무적으로 장애를 만나 수정할 기회가 없는 상황이라면, 성장하기 위해 무엇을 할 수 있을까. 고민 끝에 나온 결과는 ‘하고 싶은 걸, 하고 있을 때, 하고 싶은 형식으로 개발할 수 있는 능력’을 갖춰야 한다고 생각하게 되었습니다.

채팅을 하기로 했습니다.

하고 싶은 걸 정리해보다 보니, 채팅이 떠올랐습니다. 그동안 개발하면서 채팅을 개발하는 경험은 없었습니다. 그렇게 가벼운 마음으로 채팅을 만들어 보자고 결정했습니다.

디자인

처음에는 간단하게

처음에는 websocket을 이용해서 간단하게 채팅을 구현하는 걸 생각하였습니다. 언어는 익숙한 Javascript를 골랐고, 사용할 수 있는 library로 room등 편의 기능이 있는 socket.io로 선정했습니다. 그리고는 스펙을 아래와 같이 간단하게 정리하였습니다.

  1. 채팅룸 만들기
  2. 채팅룸 참여하기
  3. 채팅룸 떠나기
  4. 채팅하기

돌아보니 간략한 4개 스펙이네요. 바로 실행했다면 빠르게 만들어 볼 수 있었겠다는 생각이 듭니다. 하지만 저는 만족하지 못했습니다. 프론트를 한번 짜두고 뒷단만 고쳐쓰고 싶다는 생각에 아키텍처를 검색하기 시작했죠. 아키텍처 문서들에서는 대규모 채팅서버를 설계하는 예시를 다루고 있었습니다. 네, 저는 혼자 쓸 서버에 대규모 시스템 설계를 접목하였습니다.

그렇게 문서를 찾아보다 제가 꽃힌 것은 디스코드를 Next13으로 클론하는 유튜브 영상이었습니다. 영상에서는 채팅 서버를 외부 서비스를 사용했기 때문에 바로 따라할 수는 없었습니다. 하지만 디스코드를 클론한다는 아이디어가 처음 채팅 서비스를 개발한다는 입장에서 매력적으로 느껴졌습니다. 그렇게 결국 디스코드를 클론을 하기로 결정하였습니다.

결국은 클론

저는 디스코드의 완벽한 클론이 아닌, 기능만 대충 따라 만든 가벼운 클론을 만들자는 목표를 세웠습니다. 시간과 흥미라는 자원을 고려해 내린 결정이었습니다.

결정 직후 디스코드 화면 ui를 참고해 가볍게 db와 스펙을 설계하였습니다. chat_example_1_db

만들어 놓고 나니 채팅보다 기타 스펙이 엄청 커지게 되었습니다. 다행이도 향상심을 기반 삼아 진행을 할 수 있었습니다.

개발은 새발

javascript로 서버를 구현

repo: javascript-socketio

일단 javascript로 빠르게 구현하기로 한 만큼, 서버를 express로 개발하기 시작했습니다. 레포지터리의 구조는 다음 레포에서 따와서 개발을 시작했습니다. 스택은 Javascript, NodeJS, Express, Redis, PostgreSQL을 사용하였습니다. redis와 postgreSQL은 docker compose로 띄워서 사용했습니다.

간단한 스크립팅 외에 Javascript만을 이용한 개발은 처음이었습니다. 이렇게 까지 불편할 줄 몰랐고, 평소 사용하는 Typescript나 타입 추론을 해주는 강타입 언어들에 새삼 감사함을 느낄 수 있었습니다. 개발 경험이 안 좋았던 것과는 별개로 기능은 정말 빨리 낸 것 같습니다. 결과적으로 web socket과 redis pub/sub을 이용한 채팅까지 빠르게 구현해볼 수 있었습니다.

React + vite로 프론트를 구현

repo: client-socketio

프론트는 디스코드 ui를 대충 벗겨서 만들었습니다. 스택은 React + vite를 이용해 보았습니다. 다행이도 typescript를 기반해서 개발했기 때문에 서버를 짤때보다는 편하게 개발을 할 수 있었습니다. 개발의 편함과 별개로, 개발 결과물의 스타일은 많이 모자라다는 느낌을 받았습니다. 다시만들때는 dribble에서 영감을 먼저 받고 만들어야 겠다고 생각했습니다.

개발하고 남은 것

얻은 것

  1. 일단 채팅 서버를 만들어보는 경험을 얻었습니다.
  2. 원하는 기능의 개발을 빠르게 할 수 있다는 자신감을 얻었습니다.

못해본 것들

  1. 다중 클라이언트 실험
    1. 제가 만든 JWT 인증 서비스가 정상 동작을 하지 않아 크롬으로 다중 클라이언트 실험을 진행하지 못했습니다.
    2. safari와 firefox의 cookie 설정 제한을 만나며, 다중 브라우저를 이용한 다중 클라이언트 실험도 진행하지 못했습니다.
  2. 채팅 메세지 저장
    1. 실시간 통신만 해보고 메세지를 저장하는 것을 해보지 못했습니다.
  3. 저장된 메세지 불러오기
    1. 디스코드 채팅방 참여했을때 볼 수 있는 것 처럼 메세지를 불러오는 기능을 구현하지 못했습니다.
  4. 테스트 하기
    1. 단위 테스트를 추가하지 않았습니다.
    2. load 테스트를 해보지 못했습니다.
    3. stress 테스트를 해보지 못했습니다.
  5. 문서의 작성
    1. 제대로 정의된 스펙 문서 없이 흥미 본위로 개발을 이어갔습니다.

다음에 해볼 것들

  1. 다중 클라이언트 로그인
    1. 제대로 인증을 구현해 볼겁니다.
    2. 크롬의 시크릿 모드에서 실험하고, safari/firefox에서 localhost가 cookie setting할 수 있게 해보려 합니다.
  2. 완성된 채팅 서비스의 구현
    1. 채팅, 메세지 저장, 메세지 조회, 동기화 등을 해보려 합니다.
    2. redis의 pub/sub을 이용해 web socket에서 동기화 하는 걸 알았으니, 저장할때 queue를 이용해 보려 합니다.
  3. plain web socket을 이용해 구현
    1. 이번에 구현하면서 socket io기능을 사용하지 않았습니다. 다음에는 그냥 websocket을 이용해 보려 합니다.
  4. 정확한 문서화
    1. 이번에 문서화를 대충하면서 느낀게 정확한 문서화가 되어있어야 개발이 빠르다는 것입니다.
    2. 스펙을 문서화 하는 방법을 검색해 먼저 문서화 하고 개발해보려 합니다.
  5. 재사용 가능한 프론트 만들기
    1. 이쁘게 만들어 보려 합니다.

이상 채팅 예제를 만들어본 경험을 정리한 글이었습니다.

읽어 주셔서 감사합니다.