옛날부터 웹 소켓을 직접 구현해보고 싶었고 웹 소켓의 대표적인 예시인 채팅 웹 어플리케이션을 하나 만들어보고 싶었다.
채팅 어플리케이션과 웹 소켓이 무슨 상관인가?
많이 사용되는 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로 표현한다면 아래와 같이 구성될 것이다.
마지막으로 각 기능별로 상세한 플로우 차트를 그려보자.
우선 요구사항 중 가장 애매한 부분은 아래 부분이다.
- 브라우저가 종료되면 해당 유저가 삭제된다.
이 부분은 SSE를 통해 브라우저와 웹 서버가 주기적으로 통신하며 사용자의 접속 상태와 채팅방 유지 상태를 확인하는 방안으로 처리하면 될 것 같다.
SSE에 대한 설명과 구현법은 아래 포스팅에 적어두었다.https://123okk2.tistory.com/529
SSE를 사용해 알람 구현
비슷하지만 다른 웹 어플리케이션 두 개를 우리 팀과 다른 팀에서 각자 구현중이다. 정말 상세하게 요구사항을 하나 하나 짚어보면 엄연히 다른 웹 어플리케이션이지만, 어느정도 비슷한 어플
123okk2.tistory.com
그리고 나머지 부분은 그냥 일반적인 로직을 짜면 될 것 같다.
그러면 이제 기능별 상세 동작 순서를 정하고 이를 토대로 플로우 차트 그려보자.
- 사용자 기능
- 사용자 등록
- 사용자가 웹 페이지에 진입한다.
- 브라우저 세션에 저장된 사용자 식별자와 닉네임을 확인한다.
- 저장된 정보가 없을 경우 랜덤한 식별자와 사용자명을 생성해서 부여한다.
- 생성된 사용자명을 저장하고 브라우저 세션에 저장한다.
- SSE 통신을 체결해 해당 사용자가 접속 중임을 지속적으로 확인한다.
- 저장된 정보가 존재할 경우
- 식별자를 통해 현재 부여된 사용자명을 다른 이가 사용중인지 확인한다.
- 다른 사용자가 사용중일 경우 새로운 사용자명을 부여한다.
- 다른 사용자가 사용중이 아닐 경우 해당 사용자명을 계속 사용한다.
- SSE 통신을 체해 해당 사용자가 접속 중임을 지속적으로 확인한다.
- 식별자를 통해 현재 부여된 사용자명을 다른 이가 사용중인지 확인한다.
- 저장된 정보가 없을 경우 랜덤한 식별자와 사용자명을 생성해서 부여한다.
- 사용자 삭제
- 브라우저 종료, 뒤로가기 등 이벤트로 사용자가 웹 페이지에서 나가고 SSE 통신이 끊긴다.
- 사용자 정보의 "접속 종료 시간"을 현재 시간으로 지정한다.
- "접속 종료 시간" 이후 5분 (분 기준, 초 제외) 간 대기한다.
- 5분 내 재접속 시 "접속 종료 시간"을 NULL로 변경한다.
- 5분 경과 시 사용자 정보를 서버에서 삭제한다.
- 사용자 등록
- 채팅 기능
- 채팅방 생성
- 사용자가 "채팅방 생성" 버튼을 누른다.
- 기존에 저장된 코드와 겹치지 않고, 영소문자와 숫자로 이루어진 랜덤한 8자리 코드를 생성한다.
- 채팅방이 생성되며 사용자 화면이 채팅방 화면으로 전환된다.
- 채팅방 참가
- 사용자가 8자리 코드를 입력하고 "채팅방 참가" 버튼을 누른다.
- 존재하지 않는 코드일 경우
- 에러 메시지를 출력한다.
- 존재하는 코드일 경우
- 사용자가 채팅방에 참가되며, 채팅방 참여자 수가 1 증가한다.
- 채팅방에 참여중인 모든 사용자 화면에 출력되는 참여자 수가 1 증가한다.
- 존재하지 않는 코드일 경우
- 사용자가 8자리 코드를 입력하고 "채팅방 참가" 버튼을 누른다.
- 채팅 보내기
- 사용자가 채팅을 입력하고 엔터 혹은 "전송" 버튼을 눌러 채팅을 전송한다.
- 전송된 채팅이 저장되고, 채팅 방에 접속중인 모든 사용자에게 전송된다.
- 채팅방 나가기
- 사용자가 "나가기" 버튼을 클릭하거나 페이지를 닫거나 혹은 새로고침 하는 등 이벤트를 발생시킨다.
- 채팅방에서 사용자가 퇴장하며, 채팅방 테이블의 참여자 수가 1 감소한다.
- 채팅방에 참여중인 모든 사용자 화면에 출력되는 참여자 수가 1 감소한다.
- 만약 참여자 수가 0이 되면 채팅방이 삭제된다.
- 채팅방 생성
이제 이를 토대로 플로우 차트를 간단하게 그려보자.
플로우 차트는 https://app.diagrams.net/ 에서 그렸다.
1-1. 사용자 등록
1-2. 사용자 삭제
2-1. 채팅방 생성
2-2. 채팅방 참가
2-3. 채팅 보내기
2-4. 채팅방 나가기
모든 설계가 끝이 났으니, 이제 다음 포스팅에서부터 직접 프로그램을 만들어보자.
'실습 > [스프링 부트] 채팅 웹 사이트 만들기' 카테고리의 다른 글
[Thymeleaf] Lang 설정을 통한 다국어 페이지 제공 (0) | 2024.06.10 |
---|---|
[JAVA] OpenCSV를 사용한 CSV 파일 만들기 (1) | 2024.04.01 |