My HomePage (board project)

8회차 : 💡 멀티 쓰레드 기반 채팅 서버 구현 (2025-01-30)

upwardtrend 2025. 1. 30. 20:39

 

💡 멀티 쓰레드 기반 채팅 서버 구현 (소켓 프로그래밍)

오늘은 멀티 쓰레드 기반의 채팅 서버를 직접 구현해 보았습니다.

소켓을 이용해 서버와 클라이언트가 통신하며, 여러 사용자가 동시에 접속할 수 있도록 설계했습니다. 또한, 메시지 전송뿐만 아니라 닉네임 변경, 귓속말, 이미지 전송, 채팅 기록 저장 등의 기능도 추가했습니다.


🛠️ 사용 기술

  • Java (소켓 프로그래밍, 멀티 쓰레드, 파일 입출력)
  • ConcurrentHashMap (멀티쓰레드 환경에서 동기화된 데이터 관리)
  • InputStream / OutputStream (데이터 송수신)
  • UUID (고유 ID 생성)
  • File API (이미지 저장 및 불러오기)

📌 채팅 서버 구조 및 기능

🔹 ChatServer.java (서버)

  • ServerSocket 을 이용해 클라이언트 접속을 대기
  • 멀티 쓰레드 처리로 여러 클라이언트 동시 접속 가능
  • ConcurrentHashMap 으로 클라이언트 정보 관리
  • 전체 메시지 전송, 귓속말, 닉네임 변경, 이미지 저장/불러오기 기능 포함
public class ChatServer {
    ServerSocket serverSocket;
    Map<String, ClientService> chatClientInfo = new ConcurrentHashMap<>();
    Map<String, byte[]> imageStore = new ConcurrentHashMap<>();

    public void start(int portNo) {
        try {
            serverSocket = new ServerSocket(portNo);
            System.out.println("[채팅서버] 시작");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void connectClient() {
        new Thread(() -> {
            try {
                while (true) {
                    Socket socket = serverSocket.accept();
                    new ClientService(this, socket);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

🔹 ChatClient.java (클라이언트)

  • 서버에 접속 후 메시지를 주고받음
  • 실시간 메시지 수신 (새로운 쓰레드로 처리)
  • 닉네임 변경, 귓속말, 이미지 전송 등 다양한 기능 제공
public class ChatClient {
    Socket socket;
    DataInputStream dis;
    DataOutputStream dos;

    public void connect(String serverIP, int portNo, String chatName) {
        try {
            socket = new Socket(serverIP, portNo);
            dis = new DataInputStream(socket.getInputStream());
            dos = new DataOutputStream(socket.getOutputStream());
            send(chatName);
        } catch (IOException e) {
            System.out.println("서버 연결 실패");
        }
    }
}

🔹 ClientService.java (클라이언트 개별 처리)

  • 각 클라이언트별 개별 스레드 실행
  • 닉네임 관리, 메시지 송수신, 귓속말, 이미지 전송 기능 포함
public class ClientService {
    ChatServer chatServer;
    Socket socket;
    DataInputStream dis;
    DataOutputStream dos;
    String chatName;

    public ClientService(ChatServer chatServer, Socket socket) throws IOException {
        this.chatServer = chatServer;
        this.socket = socket;
        dis = new DataInputStream(socket.getInputStream());
        dos = new DataOutputStream(socket.getOutputStream());

        while (true) {
            chatName = dis.readUTF();
            if (chatServer.isChatNameUnique(chatName)) {
                chatServer.addClientInfo(this);
                break;
            } else {
                send("닉네임 중복, 다른 이름을 입력하세요");
            }
        }
    }
}

📌 오늘 공부하면서 어려웠던 점

  1. 멀티 쓰레드 동기화 문제 🚀
    • 여러 클라이언트가 동시에 접속하면 데이터 충돌이 발생할 가능성이 높음
    • 해결 방법: synchronized 키워드와 ConcurrentHashMap 사용
  2. 이미지 전송 처리 🖼️
    • 파일을 byte[]로 변환 후 전송해야 함
    • 파일 크기 정보도 함께 전송해야 정상적으로 수신 가능

🔥 개선할 부분

  1. 클라이언트 UI 추가 🎨
    • 현재는 콘솔에서 채팅을 주고받지만, Swing 또는 JavaFX로 GUI를 추가하면 사용자 경험이 개선될 것 같음
  2. 데이터베이스 연동 🗄️
    • 현재는 서버 메모리에 사용자 정보를 저장하는데, MySQL, MongoDB 같은 DB와 연결하면 더욱 안정적인 시스템이 될 것

🎥 추가 학습 자료

더 자세한 설명과 실습 영상은 유튜브 우코딩AI에서 확인할 수 있습니다!
👉 유튜브 우코딩AI


✅ 오늘의 결론

소켓 프로그래밍을 이용한 멀티 쓰레드 채팅 서버 구현 성공!
서버-클라이언트 간 메시지 송수신 및 다양한 기능 추가
멀티쓰레드 동기화와 파일 전송 방법 학습 완료
앞으로 GUI 개선 및 데이터베이스 연동 도전 예정! 🚀