Java 소켓(Socket)을 이용한 서버-클라이언트 통신 구현

scminy0527·2026년 3월 6일
post-thumbnail

자바를 공부하다 보면 네트워크 통신이라는 개념을 만나게 된다.
이번 실습에서는 서버(Server)와 클라이언트(Client)가 서로 메시지를 주고받는 간단한 채팅 프로그램을 구현해보았다.

핵심은 소켓(Socket) 이라는 개념이다.


1. 소켓(Socket)이란?

소켓은 네트워크 통신을 위한 연결 통로라고 볼 수 있다.

쉽게 말하면 다음과 같은 구조다.

클라이언트 <---- Socket ----> 서버
  • 클라이언트는 서버의 IP 주소와 포트(port) 를 통해 연결을 요청한다.
  • 서버는 해당 포트를 열어 두고 연결 요청을 기다린다.
  • 연결이 성립되면 서로 데이터를 주고받을 수 있다.

소켓은 네트워크 통신의 출입구라고 생각하면 이해하기 쉽다.


2. 서버(Server) 구현

먼저 서버 코드를 살펴보자.

package scoketPractice;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
	public static void main(String[] args) {
		String clientMsg = null, serverMsg = null;
		System.out.println("클라이언트로 부터 받을 준비");

		try(
			ServerSocket serverSocket = new ServerSocket(1100);
			Socket socket = serverSocket.accept();
			BufferedReader bufferedReader =
				new BufferedReader(new InputStreamReader(socket.getInputStream()));
			BufferedWriter bufferedWriter =
				new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			Scanner sc = new Scanner(System.in);
		){

			System.out.println("클라이언트가 연결 되었습니다.");

			while(true) {
				clientMsg = bufferedReader.readLine();
				System.out.println("[클라이언트]: " + clientMsg);

				System.out.println("클라이언트로 보낼 답변을 입력하시오...");
				serverMsg = sc.nextLine();

				bufferedWriter.write(serverMsg + "\n");
				bufferedWriter.flush();

				System.out.println("[서버]: " + serverMsg);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

서버 동작 과정

서버의 흐름은 다음과 같다.

1. ServerSocket 생성

ServerSocket serverSocket = new ServerSocket(1100);

1100번 포트를 열고 클라이언트 연결을 기다린다.


2. 클라이언트 연결 수락

Socket socket = serverSocket.accept();

클라이언트가 접속하면
Socket 객체를 통해 통신이 시작된다.


3. 데이터 입출력 스트림 생성

BufferedReader bufferedReader =
 new BufferedReader(new InputStreamReader(socket.getInputStream()));

BufferedWriter bufferedWriter =
 new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  • InputStream → 데이터를 받는 통로
  • OutputStream → 데이터를 보내는 통로

4. 메시지 송수신

clientMsg = bufferedReader.readLine();

클라이언트 메시지를 받고

bufferedWriter.write(serverMsg + "\n");
bufferedWriter.flush();

서버 메시지를 다시 보내준다.


3. 클라이언트(Client) 구현

클라이언트 코드는 다음과 같다.

package scoketPractice;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client {
	public static void main(String[] args) {

		String clientMsg = null, serverMsg = null;
		int port = 1100;
		String ip = "192.168.215.105";

		System.out.println("서버에 연결 준비");

		try(
			Socket socket = new Socket(ip, port);
			BufferedReader bufferedReader =
				new BufferedReader(new InputStreamReader(socket.getInputStream()));
			BufferedWriter bufferedWriter =
				new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			Scanner sc = new Scanner(System.in);
		){

			System.out.println("서버에 연결 완료");

			while(true) {
				System.out.println("서버에 보낼 메세지를 입력하세요");

				clientMsg = sc.nextLine();
				bufferedWriter.write(clientMsg + "\n");
				bufferedWriter.flush();

				System.out.println("[클라이언트]: " + clientMsg);

				serverMsg = bufferedReader.readLine();
				System.out.println("[서버]: " + serverMsg);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

클라이언트 동작 과정

클라이언트는 서버와 달리 연결을 기다리는 것이 아니라 연결을 요청한다.

Socket socket = new Socket(ip, port);
  • 서버 IP
  • 서버 포트

이 두 정보를 이용해서 서버에 접속한다.

연결이 성공하면 이후에는 서버와 동일하게 스트림을 이용해서 데이터를 주고받는다.


4. 실행 결과

서버와 클라이언트를 실행하면 다음과 같은 대화가 가능하다.

클라이언트: 안녕하세요
서버: 반갑습니다

클라이언트: 오늘 날씨가 좋네요
서버: 맞아요

이렇게 양방향 통신이 가능하다.


5. 이번 실습의 핵심 정리

이번 실습에서 가장 중요한 개념은 다음이다.

1. 소켓(Socket)

네트워크 통신을 위한 연결 통로


2. ServerSocket

서버가 클라이언트 연결을 기다리기 위한 객체


3. Socket

서버와 클라이언트 사이에서
실제 데이터 통신을 담당하는 객체


4. Stream

데이터를 주고받기 위한 통로

  • InputStream → 받기
  • OutputStream → 보내기

마무리

이번 실습을 통해 자바에서 네트워크 통신의 기본 구조를 이해할 수 있었다.

정리하면 다음과 같다.

ServerSocket → 연결 대기
Socket → 실제 통신
Stream → 데이터 송수신

지금 구현한 코드는 1:1 채팅 수준의 간단한 예제이지만,
여기에 Thread를 추가하면 여러 명이 동시에 접속하는 채팅 서버도 만들 수 있다.

앞으로는 멀티스레드를 활용해서
여러 클라이언트를 동시에 처리하는 채팅 서버도 구현해보고 싶다.

profile
비전공자에서 시작해 Flutter로 실서비스를 만들었고, 더 깊은 개발을 향해 계속 성장 중인 개발자

0개의 댓글