🌐 네트워크 프로그래밍
이번 강의에서는 자바에서 TCP 소켓 통신, 클라이언트-서버 구조 설계, 그리고 HTTP 통신에 대해 깊이 있게 다룹니다. 네트워크 프로그래밍은 다양한 장치와 소프트웨어가 데이터를 주고받을 수 있도록 하는 중요한 기술로, 특히 분산 시스템이나 웹 개발에서 필수적인 영역입니다.
📌 목차
- TCP 소켓 통신 개념
- 클라이언트-서버 예제
- HTTP 통신 with HttpURLConnection
🔹 1. TCP 소켓 통신 개념
TCP(Transmission Control Protocol)는 네트워크 상에서 안정적이고 순서가 보장된 데이터 전송을 제공하는 프로토콜입니다. 자바에서는 Socket 클래스와 ServerSocket 클래스를 통해 TCP 통신을 구현할 수 있습니다.
ServerSocket은 서버 측에서 특정 포트를 열어 클라이언트의 접속을 기다리고, Socket은 서버와 클라이언트 간 실제 데이터 송수신을 담당합니다. 소켓 통신은 스트림 기반으로 동작하며, 입출력 스트림을 통해 데이터를 주고받습니다.
TCP는 연결 지향적이므로 먼저 연결이 성립되어야 데이터 교환이 가능합니다. 이 점에서 UDP와 차별화되며, 안정성을 중시하는 애플리케이션에 적합합니다.
🔹 2. 클라이언트-서버 예제
다음은 간단한 TCP 서버와 클라이언트 예제입니다. 서버는 클라이언트가 보낸 메시지를 받아서 대문자로 변환해 다시 돌려줍니다.
🖥️ Server.java
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("서버가 클라이언트를 기다립니다...");
// 클라이언트 접속 대기
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String inputLine;
// 클라이언트가 메시지를 보내는 동안 반복 수신
while ((inputLine = in.readLine()) != null) {
System.out.println("클라이언트: " + inputLine);
// 받은 메시지를 대문자로 변환해 다시 보냄
out.println("서버: " + inputLine.toUpperCase());
}
// 자원 해제
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
💻 Client.java
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 1234);
BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String input;
System.out.println("서버에 메시지를 입력하세요 (종료하려면 Ctrl+C):");
while ((input = userInput.readLine()) != null) {
out.println(input); // 서버에 메시지 전송
System.out.println("서버 응답: " + in.readLine()); // 서버 응답 출력
}
// 자원 해제
in.close();
out.close();
socket.close();
}
}
위 예제에서 서버는 ServerSocket을 통해 1234 포트에서 클라이언트 접속을 기다립니다. 클라이언트가 접속하면 accept()가 반환되고, 이후 입출력 스트림으로 메시지를 주고받습니다. 클라이언트는 사용자로부터 입력을 받아 서버에 전송하고, 서버의 응답을 출력합니다.
이처럼 TCP 소켓 프로그래밍은 기본적으로 연결을 설정하고, 데이터를 주고받고, 종료하는 흐름으로 동작합니다. 실전에서는 여러 클라이언트를 처리하기 위해 멀티스레딩을 적용하는 경우가 많습니다.
🔹 3. HTTP 통신 (HttpURLConnection)
웹 애플리케이션 개발에서 서버와 통신하는 표준 프로토콜은 HTTP입니다. 자바에서는 HttpURLConnection 클래스를 통해 간단하게 HTTP 요청을 보낼 수 있습니다.
다음은 GET 요청을 보내고, 서버의 응답을 콘솔에 출력하는 기본적인 예제입니다.
import java.io.*;
import java.net.*;
public class HttpExample {
public static void main(String[] args) throws Exception {
URL url = new URL("https://httpbin.org/get");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET"); // GET 요청 설정
int status = con.getResponseCode();
System.out.println("응답 코드: " + status);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
con.disconnect();
}
}
위 코드는 HTTP GET 요청을 지정된 URL로 보내고, 서버가 반환한 JSON 형식의 응답 데이터를 한 줄씩 출력합니다. HttpURLConnection은 요청 메서드 설정, 헤더 추가, 응답 코드 확인 등 다양한 기능을 지원합니다.
또한 POST, PUT 같은 다른 HTTP 메서드도 설정할 수 있으며, 요청 본문을 전송하는 기능도 제공하기 때문에 RESTful API 호출에 자주 활용됩니다.
🔹 4. 네트워크 프로그래밍 활용 팁과 주의사항
네트워크 프로그래밍 시 반드시 알아두어야 할 점들은 다음과 같습니다:
- 예외 처리: 네트워크는 언제든 끊기거나 장애가 발생할 수 있으므로
IOException을 반드시 처리해야 합니다. - 멀티스레딩: 다수 클라이언트를 처리하려면 서버에서 스레드를 사용하거나 스레드 풀을 활용해 병렬 처리를 해야 효율적입니다.
- 자원 해제: 소켓, 스트림 등 네트워크 관련 객체는 사용 후 반드시 닫아줘야 리소스 누수를 방지할 수 있습니다.
- 포트 번호: 서버는 시스템에서 허용된 범위 내에서 포트를 할당해야 하며, 1024 미만 포트는 관리자 권한이 필요합니다.
- 방화벽 및 네트워크 환경: 실제 운영 환경에서는 방화벽, NAT 설정 등 네트워크 환경에 따라 통신이 차단될 수 있으니 이를 고려해 개발해야 합니다.
네트워크 프로그래밍을 이해하고 숙련하는 것은 분산 시스템, 클라우드 서비스, 실시간 데이터 처리 등 현대 IT 인프라에서 매우 중요한 역량입니다. TCP/IP 프로토콜과 HTTP 통신 원리를 바탕으로 다양한 네트워크 서비스를 개발할 수 있습니다.
🔹 5. 추가 예제: 멀티클라이언트 서버 구현 (Thread 활용)
실제 서버 프로그램은 여러 클라이언트 요청을 동시에 처리해야 합니다. 아래는 각 클라이언트 연결마다 새로운 스레드를 생성해 병렬로 처리하는 간단한 서버 예제입니다.
import java.io.*;
import java.net.*;
public class MultiThreadServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(1234);
System.out.println("멀티 클라이언트 서버 시작...");
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(new ClientHandler(clientSocket)).start();
}
}
}
class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("클라이언트[" + socket.getPort() + "]: " + inputLine);
out.println("서버 응답: " + inputLine.toUpperCase());
}
} catch (IOException e) {
System.err.println("클라이언트 연결 오류: " + e.getMessage());
} finally {
try {
socket.close();
} catch (IOException e) {
System.err.println("소켓 닫기 실패: " + e.getMessage());
}
}
}
}
이 예제에서는 while(true) 루프 내에서 클라이언트 접속이 감지될 때마다 ClientHandler 객체를 새로운 스레드에서 실행해 다중 접속을 처리합니다. 각 클라이언트와 독립적으로 입출력 스트림을 관리하여 통신 충돌 없이 병렬 처리가 가능합니다.
스레드 사용 시 동기화 문제가 발생할 수 있으므로, 공유 자원에 접근할 때는 적절한 synchronized 처리 또는 동시성 제어를 해줘야 합니다.
🔹 6. 마치며
이번 강의에서는 자바 네트워크 프로그래밍의 핵심인 TCP 소켓 통신, 클라이언트-서버 구조, HTTP 통신 방식을 살펴보았습니다. 이 기초를 바탕으로 여러분은 채팅 프로그램, 파일 전송, 웹 클라이언트 등 다양한 네트워크 기반 애플리케이션을 개발할 수 있습니다.
더 나아가 비동기 처리, NIO, WebSocket, REST API 등 심화 주제도 함께 공부하면 현대 네트워크 프로그래밍 역량을 더욱 강화할 수 있습니다.
여러분의 네트워크 프로그래밍 여정에 큰 도움이 되길 바랍니다!
'Programming' 카테고리의 다른 글
| JAVA 리플렉션과 어노테이션 (63) | 2025.11.27 |
|---|---|
| JAVA 디자인 패턴 (40) | 2025.11.26 |
| JAVA 쓰레드와 동시성 (62) | 2025.11.24 |
| JAVA 클래스 고급 (40) | 2025.11.23 |
| JAVA 날짜와 시간 처리 (35) | 2025.11.22 |