본문 바로가기
실습/[스프링 부트] 채팅 웹 사이트 만들기

[Spring Boot/JAVA] 익명 채팅 웹 사이트 만들기 (1/3)

by 이민우 2025. 3. 19.
728x90
반응형


옛날부터 웹 소켓을 직접 구현해보고 싶었고 웹 소켓의 대표적인 예시인 채팅 웹 어플리케이션을 하나 만들어보고 싶었다.

 

채팅 어플리케이션과 웹 소켓이 무슨 상관인가?

많이 사용되는 HTTP의 경우는 사용자가 Request를 보내야만 서버에서 Response를 보내는 방식이다.

그에 반해 채팅은 서버가 Request가 없어도 사용자에게 데이터를 보내는데,
한 번 성립된 연결을 누군가 끊기 전까지 계속 유지하는 웹 소켓의 특성상 이러한 채팅을 구현하기에 적합하다.


그래서 해당 프로그램을 만드는 과정을 기재할 게시판도 만들어놓았으나 솔직히 귀찮아서 미루고 또 미루고 있었다.


그런데 요즘 주말만 되면 그냥 낮잠을 자거나 유튜브를 보는 것 외에 하는 것도 없는 내 모습을 보며 이 이상 게을러지면 안되겠다는 생각이 들었고, 미루었던 일들을 하나씩 처리하는 김에 채팅 웹 어플리케이션 개발도 한 번 해볼까 한다.

 

 

개요

주제는 앞서 설명헀듯 "채팅 웹 어플리케이션"이다.


전체적인 요구사항는 아래와 같이 잡아볼까 한다.
우선 큰 분류의 기능은 두 가지이다.

  • 사용자 기능
  • 채팅 기능


그리고 세세하게 아래와 같이 요구사항을 잡아보았다.

  • 사용자 기능
    • 사용자 생성
      • 기본적으로 "익명 프로그램"이기에 회원가입/로그인 등 기능은 존재하지 않는다.
      • 사용자는 웹 페이지 진입 시 자동으로 생성된다.
      • 사용자가 생성될 때 랜덤한 닉네임을 부여받는다.
      • 동일한 닉네임은 존재하지 않으며, 세션이 유지되는 동안 닉네임은 유지된다.
    • 사용자 삭제
      • 브라우저가 종료되면 해당 사용자는 삭제된다.
      • 사용자가 삭제되면 사용하던 닉네임은 다른 사용자에게 부여될 수 있다.
  • 채팅 기능
    • 채팅방 생성
      • 사용자는 "채팅방 생성" 기능을 통해 새로운 채팅방을 생성할 수 있다.
      • 채팅방 생성 시 랜덤한 8자리 코드를 부여받는다.
    • 채팅방 참가
      • 사용자는 "채팅방 참가" 기능을 통해 채팅방에 진입할 수 있고, 채팅방에 부여된 랜덤한 8자리 코드를 입력해 해당 채팅방에 진입한다.
      • "채팅방 참가"로 채팅방에 참가했을 때 참가 전 나누었던 기존 대화 내역이 전부 출력된다.
      • 존재하지 않는 코드를 입력했을 경우 에러 메시지를 출력한다.
    • 채팅 보내기
      • 유저는 텍스트 기반으로 채팅을 전송할 수 있다.
      • 전송된 채팅은 채팅에 참가한 모든 사용자의 화면에 출력된다.
    • 채팅방 나가기
      • "채팅방 나가기" 버튼을 클릭할 경우 해당 채팅방에서 나가진다.
      • 만약 모든 사용자가 채팅방에서 나갔을 경우 해당 채팅방은 사라지며, 기존 대화내역은 전부 삭제된다.
      • 브라우저가 종료되거나 새로고침 등의 이벤트가 일어났을 경우에도 "채팅방 나가기"를 한 것으로 처리한다.

 

 

 

설계


요구 사항을 잡았으니 설계를 진행해보자. 

가장 먼저 화면을 설계해보겠다.

화면은 크게 메인 페이지와 채팅 페이지로 나뉜다.

그리고 HTML 내에서 JQuery와 AJax를 통해 서버와 상호작용하며, 단일 페이지 내에서, 즉 한 HTML내에서 모든 동작을 수행할 수 있도록 설계하고자 한다.

이를 러프하게 그려보면 아래와 같은 화면이 구성될 것이다.

좌/메인 페이지 우/채팅 페이지




다음으로 테이블을 설계해보았다.

 

처음에는 Cache에 모든 걸 넣어서 동작하도록 설계하려고 했지만, "익명"이라는 프로그램의 특징 탓에 데이터의 Create, Delete가 너무 빈번하게 발생해 Cache에 넣으면 오히려 비효율적일 것 같다는 생각이 들었다.

 

고로 DB를 설계했고, DB는 MariaDB를 사용했다.

 

필요한 도메인은 (채팅방, 사용자, 채팅)으로 총 세 개 이고, 필요한 컬럼은 아래와 같다.

 

  • 채팅방
    • 채팅방 코드 : 채팅방 생성 시 생성되며, 참여에 사용되는 코드
    • 참여자 : 현재 채팅에 참여한 인원 수
  • 사용자
    • 사용자 식별자 : 사용자에게 부여된 고유 식별자 (새로고침 등으로 재접속 시 동일한 사용자인지 확인하기 위한 변수)
    • 닉네임 : 사용자에게 부여된 닉네임
    • 접속 종료 시간 : 사용자가 채팅 사이트에서 접속이 종료된 시간
  • 채팅
    • 채팅방 코드 : 채팅방 코드
    • 채팅 시간 : 채팅을 보낸 시간
    • 닉네임 : 채팅을 보낸 사용자 (사용자는 웹 사이트에서 나가면 계속해서 삭제되기에 식별자 말고 닉네임을 저장)
    • 메시지 : 채팅 메시지

 

이제 위 정보를 기반으로 DDL 쿼리를 만들자.

CREATE TABLE IF NOT EXISTS CHAT_ROOM (
  CHAT_ROOM_CODE VARCHAR(8) PRIMARY KEY,
  PARTICIPANT_COUNT INTEGER DEFAULT 0
);

CREATE TABLE IF NOT EXISTS USER (
  USER_ID VARCHAR(36) PRIMARY KEY,
  NICKNAME VARCHAR(20) NOT NULL,
  DISCONNECTED_TIME DATETIME(3)
);

CREATE TABLE IF NOT EXISTS CHAT_MSG(
  CHAT_ROOM_CODE VARCHAR(8),
  CHAT_TIME DATETIME(3) DEFAULT NOW(),
  NICKNAME VARCHAR(20) NOT NULL,
  MESSAGE TEXT NOT NULL,
  PRIMARY KEY (CHAT_ROOM_CODE, CHAT_TIME),
  FOREIGN KEY (CHAT_ROOM_CODE) REFERENCES CHAT_ROOM(CHAT_ROOM_CODE) ON DELETE CASCADE
);

* 닉네임은 USER 테이블에서는 계속 삭제가 일어나지만 CHAT_MSG에서는 유지가 될 예정이므로 Foreign Key를 걸지 않았다.

 

이를 ERD로 표현한다면 아래와 같이 구성될 것이다.

https://dbdiagram.io/d


마지막으로 각 기능별로 상세한 플로우 차트를 그려보자.

 

우선 요구사항 중 가장 애매한 부분은 아래 부분이다.

  • 브라우저가 종료되면 해당 유저가 삭제된다.

이 부분은 SSE를 통해 브라우저와 웹 서버가 주기적으로 통신하며 사용자의 접속 상태와 채팅방 유지 상태를 확인하는 방안으로 처리하면 될 것 같다.

 

SSE에 대한 설명과 구현법은 아래 포스팅에 적어두었다.https://123okk2.tistory.com/529

 

SSE를 사용해 알람 구현

비슷하지만 다른 웹 어플리케이션 두 개를 우리 팀과 다른 팀에서 각자 구현중이다. 정말 상세하게 요구사항을 하나 하나 짚어보면 엄연히 다른 웹 어플리케이션이지만, 어느정도 비슷한 어플

123okk2.tistory.com

 

그리고 나머지 부분은 그냥 일반적인 로직을 짜면 될 것 같다.

그러면 이제 기능별 상세 동작 순서를 정하고 이를 토대로 플로우 차트 그려보자.

 

  1. 사용자 기능
    1. 사용자 등록
      1. 사용자가 웹 페이지에 진입한다.
      2. 브라우저 세션에 저장된 사용자 식별자와 닉네임을 확인한다.
        1. 저장된 정보가 없을 경우 랜덤한 식별자와 사용자명을 생성해서 부여한다.
          1. 생성된 사용자명을 저장하고 브라우저 세션에 저장한다.
          2. SSE 통신을 체결해 해당 사용자가 접속 중임을 지속적으로 확인한다.
        2. 저장된 정보가 존재할 경우
          1. 식별자를 통해 현재 부여된 사용자명을 다른 이가 사용중인지 확인한다.
            1. 다른 사용자가 사용중일 경우 새로운 사용자명을 부여한다.
            2. 다른 사용자가 사용중이 아닐 경우 해당 사용자명을 계속 사용한다.
          2. SSE 통신을 체해 해당 사용자가 접속 중임을 지속적으로 확인한다.
    2. 사용자 삭제
      1. 브라우저 종료, 뒤로가기 등 이벤트로 사용자가 웹 페이지에서 나가고 SSE 통신이 끊긴다.
      2. 사용자 정보의 "접속 종료 시간"을 현재 시간으로 지정한다.
      3. "접속 종료 시간" 이후 5분 (분 기준, 초 제외) 간 대기한다.
        1. 5분 내 재접속 시 "접속 종료 시간"을 NULL로 변경한다.
        2. 5분 경과 시 사용자 정보를 서버에서 삭제한다.
  2. 채팅 기능
    1. 채팅방 생성
      1. 사용자가 "채팅방 생성" 버튼을 누른다.
      2. 기존에 저장된 코드와 겹치지 않고, 영소문자와 숫자로 이루어진 랜덤한 8자리 코드를 생성한다.
      3. 채팅방이 생성되며 사용자 화면이 채팅방 화면으로 전환된다.
    2. 채팅방 참가
      1. 사용자가 8자리 코드를 입력하고 "채팅방 참가" 버튼을 누른다.
        1. 존재하지 않는 코드일 경우
          1. 에러 메시지를 출력한다.
        2. 존재하는 코드일 경우
          1. 사용자가 채팅방에 참가되며, 채팅방 참여자 수가 1 증가한다.
          2. 채팅방에 참여중인 모든 사용자 화면에 출력되는 참여자 수가 1 증가한다.
    3. 채팅 보내기
      1. 사용자가 채팅을 입력하고 엔터 혹은 "전송" 버튼을 눌러 채팅을 전송한다.
      2. 전송된 채팅이 저장되고, 채팅 방에 접속중인 모든 사용자에게 전송된다.
    4. 채팅방 나가기
      1. 사용자가 "나가기" 버튼을 클릭하거나 페이지를 닫거나 혹은 새로고침 하는 등 이벤트를 발생시킨다.
      2. 채팅방에서 사용자가 퇴장하며, 채팅방 테이블의 참여자 수가 1 감소한다.
        1. 채팅방에 참여중인 모든 사용자 화면에 출력되는 참여자 수가 1 감소한다.
        2. 만약 참여자 수가 0이 되면 채팅방이 삭제된다.

 

이제 이를 토대로 플로우 차트를 간단하게 그려보자.

플로우 차트는 https://app.diagrams.net/ 에서 그렸다.


1-1. 사용자 등록


1-2. 사용자 삭제


2-1. 채팅방 생성


2-2. 채팅방 참가


2-3. 채팅 보내기


2-4. 채팅방 나가기



모든 설계가 끝이 났으니, 이제 다음 포스팅에서부터 직접 프로그램을 만들어보자.

728x90
반응형