자바로 구현한다면 P2P 구조 + TCP + 멀티스레드로 설계하면 됩니다.
요구사항을 기준으로 실제로 구현 가능한 수준의 아키텍처를 보여줄게요. 💻
요구사항 다시 정리:
┌─────────────────────┐
│ ChatProgram │
└─────────┬───────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
ConnectionManager PeerManager CLIManager
│ │ │
│ │ │
┌────┴────┐ ┌───┴────┐ ┌────┴────┐
│Listener │ │PeerList│ │Command │
│Connector │ │Status │ │Input │
└────┬────┘ └───┬────┘ └────┬────┘
│ │ │
└────────── MessageManager ─────────┘
각 모듈 역할 설명 👇
프로그램 시작점
public class Main {
public static void main(String[] args) {
ChatNode node = new ChatNode(5000);
node.start();
}
}
프로그램 전체를 관리하는 핵심 클래스
class ChatNode {
private ConnectionManager connectionManager;
private PeerManager peerManager;
private CLIManager cliManager;
public ChatNode(int port) {
connectionManager = new ConnectionManager(port);
peerManager = new PeerManager();
cliManager = new CLIManager(peerManager, connectionManager);
}
public void start() {
connectionManager.startListening();
cliManager.start();
}
}
역할
class ConnectionManager {
private ServerSocket serverSocket;
private List<Socket> connections = new ArrayList<>();
public ConnectionManager(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void startListening() {
new Thread(() -> {
while(true) {
try {
Socket socket = serverSocket.accept();
connections.add(socket);
new Thread(new MessageReceiver(socket)).start();
} catch(Exception e) {}
}
}).start();
}
public void connectTo(String ip, int port) throws IOException {
Socket socket = new Socket(ip, port);
connections.add(socket);
new Thread(new MessageReceiver(socket)).start();
}
}
요구사항 핵심:
채팅중이지 않은 사람 선택
그래서 상태 관리 필요
class Peer {
String name;
Socket socket;
boolean chatting;
}
관리 클래스
class PeerManager {
private Map<String, Peer> peers = new HashMap<>();
public void addPeer(String name, Socket socket) {
peers.put(name, new Peer(name, socket, false));
}
public List<Peer> getIdlePeers() {
return peers.values()
.stream()
.filter(p -> !p.chatting)
.toList();
}
}
각 연결마다 하나의 스레드
class MessageReceiver implements Runnable {
private Socket socket;
public MessageReceiver(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader reader =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String msg;
while((msg = reader.readLine()) != null) {
System.out.println("Received: " + msg);
}
} catch(Exception e) {}
}
}
사용자 입력 처리
class CLIManager {
private Scanner scanner = new Scanner(System.in);
private PeerManager peerManager;
private ConnectionManager connectionManager;
public CLIManager(PeerManager pm, ConnectionManager cm) {
peerManager = pm;
connectionManager = cm;
}
public void start() {
while(true) {
System.out.println("1. Connect");
System.out.println("2. Show Users");
System.out.println("3. Chat");
int cmd = scanner.nextInt();
if(cmd == 1) {
System.out.print("IP: ");
String ip = scanner.next();
connectionManager.connectTo(ip, 5000);
}
}
}
}
단순 문자열 대신 프로토콜을 만드는 것이 좋습니다.
예:
HELLO|username
CHAT_REQUEST|username
CHAT_ACCEPT|username
CHAT_MESSAGE|username|message
CHAT_END|username
예시
CHAT_MESSAGE|Alice|Hello
프로그램 내부
Main Thread
│
├─ CLI Thread
│
├─ Server Listener Thread
│
└─ Connection Threads
├─ Peer A Receiver
├─ Peer B Receiver
└─ Peer C Receiver
프로그램 실행
컴퓨터 A
java -jar chat.jar
컴퓨터 B
java -jar chat.jar
A에서
1. Connect
IP: 192.168.0.15
연결 성공
Users
1. Bob
채팅 시작
Chat with Bob >
jar
jar cfe chat.jar Main *.class
exe (선택)
실제로 학생들이 막히는 부분:
1️⃣ 동시 입력 + 메시지 출력 충돌
2️⃣ 채팅 상태 관리
3️⃣ 여러 연결 관리
4️⃣ 메시지 프로토콜 설계
💡 원하면 내가 다음도 보여줄게:
특히 자동 사용자 발견 기능까지 넣으면 이 프로젝트 퀄리티가 과제 수준 → 제대로 된 네트워크 프로그램 수준으로 올라갑니다.