๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Lect & Tip/node, Angular, React

๋ฆฌ์•กํŠธ์™€ ์›น์†Œ์ผ“ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๋ฐ ๋ฉ”์‹œ์ง€ ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ ์˜ˆ์‹œ

by ๊น€๋ฌด์•ผํ˜ธ3ํ˜ธ 2025. 8. 29.
๋ฐ˜์‘ํ˜•

๋ฆฌ์•กํŠธ์™€ ์›น์†Œ์ผ“ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๋ฐ ๋ฉ”์‹œ์ง€ ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ ์˜ˆ์‹œ

ํ˜„๋Œ€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‹ค์‹œ๊ฐ„ ์†Œํ†ต ๊ธฐ๋Šฅ์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜(UX)์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ์ค‘์š”ํ•œ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ํŠนํžˆ, ์ฑ„ํŒ… ์‹œ์Šคํ…œ์ด๋‚˜ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์›น ์„œ๋น„์Šค๋ฅผ ๋ณด๋‹ค ์ง๊ด€์ ์ด๊ณ  ์ฆ‰๊ฐ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ์›น์†Œ์ผ“(WebSocket)๊ณผ ๋ฆฌ์•กํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ ๋ฐ ๋ฉ”์‹œ์ง€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ UI ๊ตฌ์„ฑ ์‚ฌ๋ก€์— ๋Œ€ํ•ด ์ƒ์„ธํžˆ ์„ค๋ช…๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์‹ค์‹œ๊ฐ„ ํ†ต์‹ ์˜ ํ•„์š”์„ฑ๊ณผ ์›น์†Œ์ผ“ ๊ฐœ์š”

์ „ํ†ต์ ์ธ HTTP ์š”์ฒญ ๋ฐฉ์‹์€ ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‘๋‹ต์„ ๋ฐ›์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด ์›น์†Œ์ผ“์€ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„์— ์ง€์†์ ์ธ ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๋ฉฐ, ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋Š” ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€๋‚˜ ์•Œ๋ฆผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์›น์†Œ์ผ“์˜ ์ฃผ์š” ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์–‘๋ฐฉํ–ฅ ํ†ต์‹ : ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์„œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…์ด๋‚˜ ์•Œ๋ฆผ ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ฎ์€ ์ง€์—ฐ ์‹œ๊ฐ„: ์—ฐ๊ฒฐ์ด ์œ ์ง€๋˜๋Š” ๋™์•ˆ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์ „์†กํ•˜๋ฏ€๋กœ, ์‘๋‹ต ์†๋„๊ฐ€ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
  • ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ: ์„œ๋ฒ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ฆ‰๊ฐ์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด, ์‚ฌ์šฉ์ž์—๊ฒŒ ์ตœ์‹  ์ •๋ณด๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ์™€ ์›น์†Œ์ผ“์„ ํ™œ์šฉํ•œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ ์„ค๊ณ„

๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ๊ฐ ๊ธฐ๋Šฅ์„ ๋…๋ฆฝ์ ์ธ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ชจ๋“ˆํ™”ํ•˜์—ฌ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ ๊ตฌํ˜„์— ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ์€ ๋ณดํ†ต ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

  • ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ: ์‚ฌ์šฉ์ž๊ฐ€ ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ „์†กํ•  ์ˆ˜ ์žˆ๋Š” ํผ ์š”์†Œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฉ”์‹œ์ง€ ๋ฆฌ์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ: ์„œ๋ฒ„๋‚˜ ์›น์†Œ์ผ“์„ ํ†ตํ•ด ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
  • ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ ๊ด€๋ฆฌ: ์›น์†Œ์ผ“ ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ์„ ์ƒ์„ฑ, ์œ ์ง€, ์ข…๋ฃŒํ•˜๋Š” ๋กœ์ง์„ ํฌํ•จํ•˜๋ฉฐ, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹ ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์•Œ๋ฆผ ๋ฐ ์ƒํƒœ ํ‘œ์‹œ: ์ƒˆ๋กœ์šด ๋ฉ”์‹œ์ง€ ๋„์ฐฉ ์‹œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹œ๊ฐ์  ํ˜น์€ ์ฒญ๊ฐ์  ์•Œ๋ฆผ์„ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐœ๋ฐœํ•˜๋ฉด, ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋†’์•„์ง€๋ฉฐ, ๊ธฐ๋Šฅ ํ™•์žฅ ๋˜ํ•œ ์šฉ์ดํ•ด์ง‘๋‹ˆ๋‹ค.

UI ์ปดํฌ๋„ŒํŠธ ๊ตฌ์„ฑ ๋ฐ ๋””์ž์ธ ํŒจํ„ด

์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ์˜ UI๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์‰ฝ๊ฒŒ ์ž…๋ ฅํ•˜๊ณ , ๋น ๋ฅด๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์ง๊ด€์ ์ธ ๋””์ž์ธ์„ ๊ฐ–์ถ”์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์š” ๋””์ž์ธ ๊ณ ๋ ค ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋ฐ˜์‘ํ˜• ๋””์ž์ธ: ๋ฐ์Šคํฌํƒ‘๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ๋„ ์ฑ„ํŒ… ๊ธฐ๋Šฅ์ด ์›ํ™œํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋„๋ก ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ์ฐฝ์€ ํ™”๋ฉด ํ•˜๋‹จ์— ๊ณ ์ •์‹œํ‚ค๊ณ , ๋ฉ”์‹œ์ง€ ๋ฆฌ์ŠคํŠธ๋Š” ์ž๋™ ์Šคํฌ๋กค ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ์ตœ์‹  ๋ฉ”์‹œ์ง€๊ฐ€ ํ•ญ์ƒ ๋ณด์ด๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ช…ํ™•ํ•œ ์‹œ๊ฐ์  ํ”ผ๋“œ๋ฐฑ: ์‚ฌ์šฉ์ž๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๋ฉด, ๋ฒ„ํŠผ ํด๋ฆญ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด๋‚˜ ์ž…๋ ฅ์ฐฝ์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€ ์ „์†ก์ด ์ •์ƒ์ ์œผ๋กœ ์ด๋ฃจ์–ด์กŒ์Œ์„ ์ง๊ด€์ ์œผ๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž ์‹๋ณ„: ์ฑ„ํŒ… ์ฐธ์—ฌ์ž์˜ ์ด๋ฆ„์ด๋‚˜ ํ”„๋กœํ•„ ์‚ฌ์ง„์„ ํ•จ๊ป˜ ํ‘œ์‹œํ•˜์—ฌ, ๋Œ€ํ™”์˜ ํ๋ฆ„๊ณผ ์ฐธ์—ฌ์ž๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ์Šคํฌ๋กค ๊ด€๋ฆฌ: ์ƒˆ๋กœ์šด ๋ฉ”์‹œ์ง€๊ฐ€ ๋„์ฐฉํ•  ๋•Œ ์ž๋™์œผ๋กœ ์Šคํฌ๋กค์ด ์ตœ์‹  ๋ฉ”์‹œ์ง€๋กœ ์ด๋™ํ•˜๋„๋ก ํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กค์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ ์›น์†Œ์ผ“์„ ํ™œ์šฉํ•œ ์ฑ„ํŒ… ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

์•„๋ž˜๋Š” ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์†Œ์ผ“์„ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” useEffect์™€ useState ํ›…์„ ํ™œ์šฉํ•˜์—ฌ ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•˜๊ณ , ๋ฉ”์‹œ์ง€๋ฅผ ์†ก์ˆ˜์‹ ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

// ChatRoom.jsx
import React, { useState, useEffect, useRef } from 'react';
import styled from 'styled-components';

// ์Šคํƒ€์ผ๋ง ์ปดํฌ๋„ŒํŠธ
const ChatContainer = styled.div`
  width: 100%;
  max-width: 800px;
  margin: 20px auto;
  border: 1px solid #ddd;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  height: 500px;
`;

const MessageList = styled.ul`
  list-style: none;
  padding: 20px;
  margin: 0;
  flex: 1;
  overflow-y: auto;
  background: #f9f9f9;
`;

const MessageItem = styled.li`
  margin-bottom: 15px;
  padding: 10px;
  border-radius: 4px;
  background: ${props => (props.isOwn ? '#d1e7dd' : '#fff')};
  align-self: ${props => (props.isOwn ? 'flex-end' : 'flex-start')};
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
`;

const InputContainer = styled.div`
  padding: 10px;
  border-top: 1px solid #ddd;
  display: flex;
`;

const TextInput = styled.input`
  flex: 1;
  padding: 10px;
  font-size: 1rem;
  border: 1px solid #ccc;
  border-radius: 4px;
`;

const SendButton = styled.button`
  padding: 0 20px;
  margin-left: 10px;
  font-size: 1rem;
  border: none;
  border-radius: 4px;
  background-color: #1976d2;
  color: #fff;
  cursor: pointer;

  &:hover {
    background-color: #1565c0;
  }
`;

const ChatRoom = () => {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const ws = useRef(null);
  const messageListRef = useRef(null);

  useEffect(() => {
    // ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ ์ƒ์„ฑ (์˜ˆ: ws://localhost:8080)
    ws.current = new WebSocket('ws://localhost:8080');

    // ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ ์„ฑ๊ณต ์‹œ
    ws.current.onopen = () => {
      console.log('WebSocket ์—ฐ๊ฒฐ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์—ด๋ ธ์Šต๋‹ˆ๋‹ค.');
    };

    // ์„œ๋ฒ„์—์„œ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹  ์‹œ ์ฒ˜๋ฆฌ
    ws.current.onmessage = (event) => {
      const newMessage = JSON.parse(event.data);
      setMessages(prevMessages => [...prevMessages, newMessage]);
    };

    // ์—ฐ๊ฒฐ ์ข…๋ฃŒ ๋ฐ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ
    ws.current.onerror = (error) => console.error('WebSocket ์˜ค๋ฅ˜:', error);
    ws.current.onclose = () => console.log('WebSocket ์—ฐ๊ฒฐ์ด ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');

    // ์ปดํฌ๋„ŒํŠธ ์–ธ๋งˆ์šดํŠธ ์‹œ ์—ฐ๊ฒฐ ์ข…๋ฃŒ
    return () => {
      ws.current.close();
    };
  }, []);

  // ์ƒˆ๋กœ์šด ๋ฉ”์‹œ์ง€๊ฐ€ ์ถ”๊ฐ€๋  ๋•Œ๋งˆ๋‹ค ์Šคํฌ๋กค์„ ์ตœํ•˜๋‹จ์œผ๋กœ ์ด๋™
  useEffect(() => {
    if (messageListRef.current) {
      messageListRef.current.scrollTop = messageListRef.current.scrollHeight;
    }
  }, [messages]);

  const handleSend = () => {
    if (input.trim() !== '') {
      const message = { text: input, sender: 'me', timestamp: new Date().toISOString() };
      ws.current.send(JSON.stringify(message));
      setMessages(prevMessages => [...prevMessages, message]);
      setInput('');
    }
  };

  const handleInputKeyPress = (e) => {
    if (e.key === 'Enter') {
      handleSend();
    }
  };

  return (
    <ChatContainer>
      <MessageList ref={messageListRef}>
        {messages.map((msg, index) => (
          <MessageItem key={index} isOwn={msg.sender === 'me'}>
            <div>{msg.text}</div>
            <small>{new Date(msg.timestamp).toLocaleTimeString()}</small>
          </MessageItem>
        ))}
      </MessageList>
      <InputContainer>
        <TextInput
          type="text"
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyPress={handleInputKeyPress}
          placeholder="๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”..."
        />
        <SendButton onClick={handleSend}>์ „์†ก</SendButton>
      </InputContainer>
    </ChatContainer>
  );
};

export default ChatRoom;

์ฝ”๋“œ ์„ค๋ช…

  • ์›น์†Œ์ผ“ ์—ฐ๊ฒฐ ๊ด€๋ฆฌ: useRef๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›น์†Œ์ผ“ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ ๋ฐ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ ์‹œ ์—ฐ๊ฒฐ์„ ์—ด๊ณ  ์–ธ๋งˆ์šดํŠธ ์‹œ ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ค์‹œ๊ฐ„ ๋ฉ”์‹œ์ง€ ์—…๋ฐ์ดํŠธ: ์„œ๋ฒ„์—์„œ ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€๋Š” JSON ํŒŒ์‹ฑ ํ›„ ์ƒํƒœ ๋ฐฐ์—ด์— ์ถ”๊ฐ€๋˜๋ฉฐ, ์ƒˆ๋กœ์šด ๋ฉ”์‹œ์ง€๊ฐ€ ์ˆ˜์‹ ๋  ๋•Œ๋งˆ๋‹ค ๋ฉ”์‹œ์ง€ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์Šคํฌ๋กค๋˜์–ด ์ตœ์‹  ๋ฉ”์‹œ์ง€๊ฐ€ ๋ณด์ž…๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ฒ˜๋ฆฌ: ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๋ฉ”์‹œ์ง€๋Š” ์—”ํ„ฐํ‚ค๋‚˜ ์ „์†ก ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์›น์†Œ์ผ“์„ ํ†ตํ•ด ์„œ๋ฒ„๋กœ ์ „์†ก๋˜๊ณ , ๋™์‹œ์— ๋กœ์ปฌ ์ƒํƒœ์—๋„ ๋ฐ˜์˜๋˜์–ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… UI๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • UI ๊ตฌ์„ฑ: ๋ฐ˜์‘ํ˜• ๋””์ž์ธ์„ ๊ณ ๋ คํ•œ ์ฑ„ํŒ…์ฐฝ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ, ๋ฉ”์‹œ์ง€ ๋ฆฌ์ŠคํŠธ์™€ ์ž…๋ ฅ์ฐฝ์ด ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„๋˜์–ด ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ฉ”์‹œ์ง€ ํ•ญ๋ชฉ์€ ์ „์†ก์ž์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์Šคํƒ€์ผ๋ง๋ฉ๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ๊ณ ๋ ค์‚ฌํ•ญ: ์•Œ๋ฆผ ๊ธฐ๋Šฅ ๋ฐ ํ™•์žฅ์„ฑ

์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ์—์„œ๋Š” ๋‹จ์ˆœํ•œ ๋ฉ”์‹œ์ง€ ์†ก์ˆ˜์‹  ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ์•Œ๋ฆผ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ƒˆ๋กœ์šด ๋ฉ”์‹œ์ง€ ๋„์ฐฉ ์‹œ ํ™”๋ฉด ํ•˜๋‹จ์— ํ† ์ŠคํŠธ ์•Œ๋ฆผ์„ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž๊ฐ€ ์ ‘์† ์ค‘์ด์ง€ ์•Š์„ ๋•Œ ๋ธŒ๋ผ์šฐ์ € ์•Œ๋ฆผ(Notification API)์„ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, WebSocket ์—ฐ๊ฒฐ์ด ๋Š์–ด์ง€๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ์žฌ์—ฐ๊ฒฐ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๋Š” ๋“ฑ, ์•ˆ์ •์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์ „๋žต์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

์›น์†Œ์ผ“๊ณผ ๋ฆฌ์•กํŠธ๋ฅผ ๊ฒฐํ•ฉํ•œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๋ฐ ๋ฉ”์‹œ์ง€ ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฆ‰๊ฐ์ ์ด๊ณ  ์›ํ™œํ•œ ์†Œํ†ต ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ์›น์†Œ์ผ“์„ ํ†ตํ•œ ์—ฐ๊ฒฐ ๊ด€๋ฆฌ, ๋ฆฌ์•กํŠธ์˜ ์ƒํƒœ ๋ฐ ๋ผ์ดํ”„์‚ฌ์ดํด ํ›…์„ ํ™œ์šฉํ•œ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ, ๊ทธ๋ฆฌ๊ณ  ์ง๊ด€์ ์ธ UI ๊ตฌ์„ฑ ์‚ฌ๋ก€๋ฅผ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

  • ์›น์†Œ์ผ“์˜ ํ™œ์šฉ: ์ง€์†์ ์ธ ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๋ฉฐ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์›น์†Œ์ผ“์˜ ์žฅ์ ์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฆฌ์•กํŠธ์™€์˜ ๊ฒฐํ•ฉ: ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜์™€ ์ƒํƒœ ๊ด€๋ฆฌ ๊ธฐ๋ฒ•์„ ํ†ตํ•ด, ๋ฉ”์‹œ์ง€ ๋ฆฌ์ŠคํŠธ์™€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ ์ฒ˜๋ฆฌ ๋“ฑ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… UI๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • UI/UX ๊ฐœ์„ : ์‚ฌ์šฉ์ž ์นœํ™”์ ์ธ ๋””์ž์ธ, ์ž๋™ ์Šคํฌ๋กค, ๋ช…ํ™•ํ•œ ์‹œ๊ฐ„ ํ‘œ์‹œ ๋“ฑ์„ ํ†ตํ•ด, ์‚ฌ์šฉ์ž๊ฐ€ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฑ„ํŒ…ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์‹œ์Šคํ…œ ์™ธ์—๋„, ์•Œ๋ฆผ ๊ธฐ๋Šฅ์ด๋‚˜ ๊ธฐํƒ€ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ๋ชจ๋‹ˆํ„ฐ๋ง ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๋”์šฑ ํ’๋ถ€ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›น์†Œ์ผ“์˜ ์•ˆ์ •์„ฑ, ์—ฐ๊ฒฐ ์žฌ์‹œ๋„ ๋กœ์ง, ๊ทธ๋ฆฌ๊ณ  ๋ณด์•ˆ ๊ฐ•ํ™” ๋“ฑ์˜ ์š”์†Œ๋„ ํ•จ๊ป˜ ๊ณ ๋ คํ•˜์—ฌ, ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์‹ค์‹œ๊ฐ„ ํ†ต์‹  ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜์‹œ๊ธธ ๊ถŒ์žฅ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€