2024. 12. 12. 01:46ㆍProjects/SimpleChat
1. 시작하게 된 계기
개인적으로, 옛날부터 네트워크 활용 경험이 부족한 것이 약점이라고 생각해왔습니다. 개발 공부는 만들고 싶은 것을 만들면서 Top-down 형태로 공부해나가라는 말을 많이 봤죠. 저 또한 이에 동의하며, 거창한 건 아니더라도 간단한 기능부터 점차 살을 붙여가며 개발해볼까 합니다.
2. 뭐부터 시작해야하지?..
하지만 의욕과 달리, 처음부터 난관에 부딪혔습니다. 자바 언어를 활용해 응용 프로그램을 만들어 본 경험도 없고, 책도 없었습니다. 다행히 저에겐 구글이라는 방대한 지식 창고가 있고, 최근에 고용한 Claude
라는 멋진 비서가 있죠. Claude에게 간단한 채팅 프로그램을 만들기 위해 뭐부터 시작해야 하는지 물어봤습니다.

저는 아래와 같이 Claude가 알려준대로 학습을 진행해보기로 했습니다.

3. 간단한 1:1 채팅 프로그램 만들기 | 클라이언트
자바 IDE로 생산성이 좋고 다양한 플러그인을 지원하는 인텔리제이(IntelliJ)를 많이 사용하더라구요. 저 또한 이번 기회에 인텔리제이를 써보면서 기존에 써봤던 이클립스(Eclips)와 어떤 차이점이 있는지 느껴볼까 합니다. SimpleChat
이란 프로젝트명과 함께, 클라이언트에 해당하는 자바 코드를 작성해보겠습니다.
(1) 호스트 설정
package client;
public class ChatClient {
private static final String SERVER_HOST = "localhost";
// ...
}
우선 해당 클라이언트가 어느 컴퓨터에 접속시킬 지부터 지정해줘야 했습니다. 현재 네트워크에 연결된 컴퓨터나 장치를 호스트(Host)
라고 부르며, 이는 IP 주소
나 도메인 이름
으로 식별됩니다.
localhost
는 자기 자신의 컴퓨터를 가리키는 호스트명으로, IP 주소로는 127.0.0.1
과 동일합니다. 만약 다른 컴퓨터와 연결하고 싶다면 해당 컴퓨터의 IP 주소 또는 도메인 이름을 지정해주면 접속할 수 있습니다. 저는 우선 같은 컴퓨터 환경에서 메시지를 잘 주고 받는지에 대한 간단한 기능만 만들 거라서 localhost
로 지정해줬습니다.
옛날에 "카운터스트라이크 온라인"이라는 게임을 할 때 게임 방에 접속하는 과정에서 "호스트 연결 중"이라는 메시지 문구를 본 적이 있습니다. 그때는 무슨 의미인지 몰랐지만 이제는 알겠네요!
(2) 포트 번호 설정
package client;
public class ChatClient {
private static final String SERVER_HOST = "localhost";
private static final int SERVER_PORT = 12345;
// ...
}
컴퓨터의 IP 주소는 고유하게 1개로 지정되지만, 컴퓨터 안에서 돌아가는 프로그램들은 여러 개죠. 그렇기에 이들을 각각 구별해줄 수 있는 식별자가 필요한데, 그것이 바로 포트 번호(Port Number)
입니다. 가령, 편지를 보낼 때 집 주소를 IP에 비유할 수 있고, 편지를 받을 집 구성원들(ex. 아빠, 엄마, 누나, 나) 중에 누가 받을 것인지를 포트 번호에 비유할 수 있습니다.
이와 같이, 포트 번호는 하나의 컴퓨터에서 실행되는 여러 네트워크 프로그램을 구분하는 번호이며
Well-known Ports(0 ~ 1023)
: 잘 알려진 서비스들이 사용하는 예약된 포트Registered Ports(1024 ~ 49151)
: 기업 및 서비스가 등록해 사용하며, 일반적으로 개발자가 자유롭게 사용 가능Dynamic/Private Ports(49152 ~ 65535)
: 누구나 자유롭게 사용 가능한 포트이며, 임시 할당에 주로 사용
저는 이 중에서 Registered Ports
영역에 속하는 숫자 아무거나를 하나 골라 설정해주었습니다.
(3) Java Socket 및 I/O 클래스들
프로그램이 시작되었을 때 클라이언트 인스턴스가 생성되고, 인스턴스가 생성되면 서버로 세션 연결 요청을 합니다.
public static void main(String[] args) {
ChatClient chatClient = new ChatClient();
chatClient.startChatSession();
}
// 게시글 폭이 좁아서 코드가 이쁘게 나오질 않아, 줄 바꿈을 많이 했습니다.
public void startChatSession() {
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
BufferedReader userInputReader =
new BufferedReader(new InputStreamReader(System.in));
PrintWriter messageTransmitter =
new PrintWriter(socket.getOutputStream(), true);
BufferedReader messageReceiver =
new BufferedReader(new InputStreamReader(socket.getInputStream())))
{
System.out.println("Successfully connected to chat server.");
handleChatSession(userInputReader, messageTransmitter, messageReceiver);
} catch (IOException e) {
System.err.println("Socket Connection Error: " + e.getMessage());
}
}
연결하고자 하는 서버의 호스트와 포트 번호를 넘겨주어 연결을 신청하고, 연결에 성공했다면 통신할 준비가 끝난 겁니다. 지금 만들고 있는 프로그램은 채팅 프로그램이므로 유저가 키보드를 통해 입력하는 것과 서버로부터 메시지를 입력받기 위해 BufferedReader
를 사용합니다.
둘 다 BufferedReader
를 사용하지만 유저의 입력은 키보드로 받으므로 System.in
노드 스트림을, 서버로부터 받는 메시지는 연결한 소켓으로부터 InputStream
을 받고 있습니다.
또한, 유저가 작성한 메시지를 서버로 보내기 위해 PrintWriter
인스턴스를 생성했으며, 이 또한 소켓의 OutputStream
을 사용하고 있는 모습을 볼 수 있습니다. 이제 이를 통해 서버와 메시지를 주고 받으면 됩니다.
private static final String EXIT_COMMAND = "quit";
private static final String PROMPT_MESSAGE = "Enter your message: ";
private void handleChatSession(BufferedReader userInputReader,
PrintWriter messageTransmitter,
BufferedReader messageReceiver) throws IOException {
String userMessage;
while (true) {
System.out.println(PROMPT_MESSAGE);
userMessage = userInputReader.readLine();
if (userMessage.equalsIgnoreCase(EXIT_COMMAND)) {
System.out.println("Chat session ended.");
break;
}
sendAndReceiveMessage(userMessage, messageTransmitter, messageReceiver);
}
}
private void sendAndReceiveMessage(String message,
PrintWriter messageTransmitter,
BufferedReader messageReceiver) throws IOException {
messageTransmitter.println(message);
String serverResponse = messageReceiver.readLine();
System.out.println("Seraver response: " + serverResponse);
}
4. 간단한 1:1 채팅 프로그램 만들기 | 서버
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ChatServer {
private static final int SERVER_PORT = 12345;
private static final String SERVER_START_MESSAGE = "Chat server is running on port: ";
private static final String CLIENT_CONNECTED_MESSAGE = "New client connection established from: ";
public void startChatServer() {
try (ServerSocket serverSocketConnection = new ServerSocket(SERVER_PORT)) {
System.out.println(SERVER_START_MESSAGE + SERVER_PORT);
while (true) {
try (Socket clientConnection = serverSocketConnection.accept();
BufferedReader messageReceiver = new BufferedReader(new InputStreamReader(clientConnection.getInputStream()));
PrintWriter messageTransmitter = new PrintWriter(clientConnection.getOutputStream(), true))
{
System.out.println(CLIENT_CONNECTED_MESSAGE + clientConnection.getInetAddress());
String receivedMessage;
while ((receivedMessage = messageReceiver.readLine()) != null) {
System.out.println("Message from client: " + receivedMessage);
String responseMessage = "Message received: " + receivedMessage;
messageTransmitter.println(responseMessage);
}
} catch (IOException e) {
System.err.println("Error handling client connection: " + e.getMessage());
}
}
} catch (IOException e) {
System.err.println("Server error: " + e.getMessage());
}
}
public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
chatServer.startChatServer();
}
}
서버 쪽에서는 ServerSocket
이라는 클래스를 사용하여 특정 포트에 대한 연결 요청을 받을 수 있는 것 같습니다. 즉, Listener 역할을 하는 친구인 것 같아요. 그렇게 계속 연결 요청이 오는지 계속 확인하다가 연결 요청이 왔다면 그에 대한 새로운 Socket
을 만들어서 통신합니다. 서버에서는 유저의 입력을 받을 필요가 없으니 클라이언트로부터 메시지를 받아 읽을 BufferedReader
, 그리고 클라이언트로 메시지를 전송하기 위한 PrintWriter
두 개만 있으면 됩니다.
현재 만들고 있는 채팅 프로그램은 진짜 간단한 것이어서 1:1로만 연결하여 채팅을 하죠. 심지어 지금은 같은 컴퓨터 내에서 채팅을 하니 사실상 채팅 프로그램이라고 하기에도 애매한 것 같습니다. 하지만 시작을 초라하더라도 끝은 창대하리라 믿으며, 추후 기능을 하나하나 추가하며 발전시켜 나가도록 하겠습니다.
5. 테스트

서버 소스 코드를 먼저 실행한 후, 클라이언트 소스 코드를 실행하면 잘 연결되는 것을 볼 수 있습니다. 제가 다른 컴퓨터가 없어서 컴퓨터 간 채팅은 아쉽게도 못해보네요. 테스트 할 수 있는 환경이 생긴다면 테스트를 해보고, 다음에는 여러 명이 채팅할 수 있는 기능을 만들어 보는 걸로 하죠.