본문 바로가기
프로그래밍 언어/자바

자바 네트워킹의 기초부터 실전까지

by 김코딩스타 2023. 7. 17.
반응형

안녕하세요, 김코딩스타입니다. 오늘은 자바 네트워킹에 대해 알아보겠습니다. 자바 네트워킹이란 자바에서 네트워크를 통해 데이터를 주고받는 기술을 말합니다. 자바는 네트워킹을 지원하는 다양한 클래스와 인터페이스를 제공하므로 소켓 프로그래밍, HTTP 통신, 웹소켓 등을 쉽게 구현할 수 있습니다. 이 글에서는 자바 네트워킹의 기본 개념과 예제를 소개하고, 자바 네트워킹의 장점과 단점에 대해 설명하겠습니다.

 

자바 네트워킹의 기본 개념

 

네트워킹은 컴퓨터들이 서로 데이터를 주고받기 위해 연결되는 과정입니다. 네트워크에 연결된 컴퓨터들은 서버와 클라이언트라는 역할을 가집니다. 서버는 클라이언트의 요청을 받아서 처리하고 응답을 보내주는 역할을 하고, 클라이언트는 서버에게 요청을 보내고 응답을 받는 역할을 합니다.

자바에서는 java.net 패키지에 네트워킹을 위한 다양한 클래스와 인터페이스가 정의되어 있습니다. 그 중에서 가장 기본적인 것은 Socket과 ServerSocket 클래스입니다. Socket 클래스는 클라이언트 쪽에서 서버와의 연결을 담당하고, ServerSocket 클래스는 서버 쪽에서 클라이언트의 연결 요청을 받아들이는 역할을 합니다.

Socket과 ServerSocket 클래스를 사용하면 TCP (Transmission Control Protocol) 방식의 소켓 프로그래밍을 할 수 있습니다. TCP 방식은 연결 지향적인 프로토콜로서, 클라이언트와 서버가 연결된 상태에서 데이터를 주고받습니다. TCP 방식은 데이터의 전송 순서와 정확성을 보장하지만, 연결 과정이 복잡하고 오버헤드가 발생할 수 있습니다.

자바에서는 UDP (User Datagram Protocol) 방식의 소켓 프로그래밍도 할 수 있습니다. UDP 방식은 비연결 지향적인 프로토콜로서, 클라이언트와 서버가 연결 없이 데이터를 주고받습니다. UDP 방식은 데이터의 전송 순서와 정확성을 보장하지 않지만, 연결 과정이 간단하고 오버헤드가 적습니다.

UDP 방식의 소켓 프로그래밍을 하려면 DatagramSocket과 DatagramPacket 클래스를 사용해야 합니다. DatagramSocket 클래스는 UDP 소켓을 생성하고 닫는 역할을 하고, DatagramPacket 클래스는 UDP 패킷(데이터와 주소 정보를 가진 단위)을 생성하고 보내고 받는 역할을 합니다.

 

 


 

 

자바 네트워킹의 예제

 

 

자바 네트워킹의 예제를 보기 전에, 네트워크에서 사용되는 주요 용어들을 간단히 알아보겠습니다.

 - IP 주소: 네트워크에 연결된 컴퓨터의 고유한 식별자입니다. IPv4와 IPv6 두 가지 형식이 있습니다. 예) 192.168.0.1, 2001:db8::1

 - 포트 번호: 컴퓨터에서 실행되는 프로세스(프로그램)의 고유한 식별자입니다. 0부터 65535까지의 정수로 표현됩니다. 예) 80, 443, 8080

 - 호스트 이름: IP 주소를 사람이 읽고 쓰기 쉽게 만든 문자열입니다. DNS (Domain Name System) 서비스를 통해 IP 주소와 매핑됩니다. 예) www.google.com,  www.naver.com  

 

네이버

네이버 메인에서 다양한 정보와 유용한 컨텐츠를 만나 보세요

www.naver.com

 - URL (Uniform Resource Locator): 인터넷 상의 자원의 위치를 표현하는 문자열입니다. 프로토콜, 호스트 이름, 포트 번호, 경로, 쿼리 등으로 구성됩니다. 예) https://www.naver.com:443/search?query=java 

 

자바에서는 이러한 용어들과 관련된 클래스들을 제공합니다. 예를 들어, InetAddress 클래스는 IP 주소와 호스트 이름을 다루는 클래스이고, URL 클래스는 URL을 다루는 클래스입니다.

이제 자바 네트워킹의 예제를 보겠습니다. 첫 번째 예제는 TCP 방식의 소켓 프로그래밍으로, 간단한 에코 서버와 클라이언트를 구현한 것입니다. 에코 서버는 클라이언트가 보낸 메시지를 그대로 되돌려주는 서버입니다.

에코 서버

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

public class EchoServer {

public static void main(String [] args) throws Exception {

int port = 12345 ;

try (ServerSocket serverSocket = new ServerSocket (port)) {

System.out.println ( "Server is listening on port " + port);

while ( true) {

try (Socket clientSocket = serverSocket.accept ()) {

BufferedReader reader = new BufferedReader ( new InputStreamReader (clientSocket.getInputStream ()));

PrintWriter writer = new PrintWriter (clientSocket.getOutputStream (), true );

String message = reader.readLine ();

System.out.println ( "Received: " + message);

writer.println ( "Echo: " + message);

}

}

}

}

에코 클라이언트

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.net.Socket;

public class EchoClient {

public static void main(String [] args) throws Exception {

String serverAddress = "localhost" ;

int port = 12345 ;

try (Socket socket = new Socket (serverAddress, port)) {

PrintWriter writer = new PrintWriter (socket.getOutputStream (), true );

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

writer.println ( "Hello, server!" );

String response = reader.readLine ();

System.out.println ( "Server response: " + response);

}

}

이 예제에서는 서버와 클라이언트가 각각 12345번 포트를 사용하여 연결하고, 클라이언트가 "Hello, server!"라는 메시지를 보내면, 서버가 "Echo: Hello, server!"라는 메시지를 되돌려줍니다. 서버와 클라이언트는 BufferedReader와 PrintWriter를 사용하여 문자열 데이터를 주고받습니다.

두 번째 예제는 HTTP 통신을 위한 URL과 HttpURLConnection 클래스를 사용한 것입니다. 이 예제에서는 GET 요청을 보내고 응답을 받아보겠습니다.

 


 

 

HTTP 통신 예제

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net.URL;

public class HttpGetExample {

public static void main(String [] args) throws Exception {

String urlString = "https://jsonplaceholder.typicode.com/todos/1\" ;

URL url = new URL (urlString);

HttpURLConnection connection = (HttpURLConnection) url.openConnection ();

connection.setRequestMethod ( "GET" );

int responseCode = connection.getResponseCode ();

System.out.println ( "Response Code: " + responseCode);

BufferedReader reader = new BufferedReader ( new InputStreamReader (connection.getInputStream ()));

String line;

StringBuilder response = new StringBuilder ();

while ( (line = reader.readLine ()) != null) {

response.append (line);

}

reader.close ();

System.out.println ( "Response: " + response.toString ());

connection.disconnect ();

}

이 예제에서는 https://jsonplaceholder.typicode.com/todos/1 이라는 URL에 GET 요청을 보내고, 응답 코드와 응답 내용을 출력합니다. HttpURLConnection 클래스는 HTTP 요청과 응답을 다루는 클래스로서, setRequestMethod 메소드로 요청 방식을 설정하고, getResponseCode 메소드로 응답 코드를 얻고, getInputStream 메소드로 응답 내용을 얻을 수 있습니다.

세 번째 예제는 자바 NIO (Non-blocking I/O)를 사용한 것입니다. 자바 NIO는 자바에서 비동기 입출력을 지원하는 프레임워크입니다. 기존 I/O 방식과 달리, NIO를 사용하면 복수의 클라이언트와의 연결을 처리할 때 스레드를 적게 사용하면서도 높은 효율성을 얻을 수 있습니다.

자바 NIO의 핵심 개념은 채널(Channel)과 버퍼(Buffer)입니다. 채널은 데이터의 입출력을 담당하는 객체로서, 파일 채널, 소켓 채널, 데이터그램 채널 등이 있습니다. 버퍼는 데이터의 임시 저장소로서, 바이트 버퍼, 문자 버퍼, 정수 버퍼 등이 있습니다. 채널과 버퍼를 사용하면 데이터의 입출력을 효율적으로 처리할 수 있습니다.

자바 NIO의 예제는 다음과 같습니다.

 


 

 

자바 NIO 예제

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.util.Iterator;

public class NioEchoServer {

public static void main(String [] args) throws IOException {

int port = 12345 ;

ServerSocketChannel serverChannel = ServerSocketChannel.open ();

serverChannel.configureBlocking ( false );

serverChannel.socket ().bind ( new InetSocketAddress (port));

Selector selector = Selector.open ();

serverChannel.register (selector, SelectionKey.OP_ACCEPT);

System.out.println ( "Server is listening on port " + port);

NIO 서버의 메인 루프

 

while ( true) {

int readyChannels = selector.select ();

if (readyChannels == 0 ) continue ;

Iterator 

 keyIterator = selector.selectedKeys ().iterator ();

while (keyIterator.hasNext ()) {

SelectionKey key = keyIterator.next ();

if (key.isAcceptable ()) {

SocketChannel clientChannel = serverChannel.accept ();

clientChannel.configureBlocking ( false );

clientChannel.register (selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

System.out.println ( "Accepted connection from " + clientChannel);

}

if (key.isReadable ()) {

SocketChannel clientChannel = (SocketChannel) key.channel ();

ByteBuffer buffer = ByteBuffer.allocate (1024 );

int bytesRead = clientChannel.read (buffer);

if (bytesRead == -1 ) {

clientChannel.close ();

System.out.println ( "Closed connection from " + clientChannel);

} else {

buffer.flip ();

byte [] data = new byte [buffer.limit ()];

buffer.get (data);

String message = new String (data);

System.out.println ( "Received: " + message);

key.attach (message);

}

}

if (key.isWritable ()) {

SocketChannel clientChannel = (SocketChannel) key.channel ();

String message = (String) key.attachment ();

if (message != null) {

ByteBuffer buffer = ByteBuffer.wrap (( "Echo: " + message).getBytes ());

clientChannel.write (buffer);

System.out.println ( "Sent: " + message);

}

keyIterator.remove ();

}

이 예제에서는 NIO 서버의 메인 루프를 보여줍니다. NIO 서버는 Selector 객체를 사용하여 채널들의 상태를 감시하고, 채널들에 대한 이벤트를 처리합니다. Selector 객체는 select 메소드로 준비된 채널들의 수를 반환하고, selectedKeys 메소드로 준비된 채널들의 키를 반환합니다. 키는 채널과 관심 있는 이벤트를 연결하는 객체입니다.

NIO 서버는 준비된 채널들의 키를 순회하면서, 각 키에 대해 다음과 같은 작업을 수행합니다.

 - 키가 연결 요청을 받아들일 수 있는 상태라면, ServerSocketChannel의 accept 메소드로 클라이언트와 연결된 SocketChannel을 얻고, 이를 Selector에 등록합니다.

 - 키가 읽기 가능한 상태라면, SocketChannel의 read 메소드로 클라이언트가 보낸 데이터를 버퍼에 읽고, 이를 문자열로 변환하여 출력하고, 키에 첨부합니다.

 - 키가 쓰기 가능한 상태라면, 키에 첨부된 문자열을 가져와서 버퍼에 담고, SocketChannel의 write 메소드로 클라이언트에게 되돌려 보냅니다.

 

이 예제에서는 NIO 서버가 에코 서버의 역할을 하고 있습니다. 즉, 클라이언트가 보낸 메시지를 그대로 되돌려주고 있습니다.

자바 네트워킹의 장점과 단점

 

자바 네트워킹의 장점은 다음과 같습니다.

 - 자바는 네트워킹을 위한 다양한 클래스와 인터페이스를 제공하므로, 소켓 프로그래밍, HTTP 통신, 웹소켓 등을 쉽게 구현할 수 있습니다.

 - 자바는 플랫폼 독립적인 언어이므로, 자바 네트워킹 프로그램은 여러 운영체제에서 실행될 수 있습니다.

 - 자바는 멀티스레드를 지원하므로, 자바 네트워킹 프로그램은 병렬 처리를 할 수 있습니다.

 - 자바는 NIO를 지원하므로, 자바 네트워킹 프로그램은 비동기 입출력을 할 수 있습니다.

 

자바 네트워킹의 단점은 다음과 같습니다.

 - 자바는 네트워킹을 위한 다양한 클래스와 인터페이스를 제공하므로, 이들을 모두 숙지하고 사용하는 것이 쉽지 않습니다.

 - 자바는 플랫폼 독립적인 언어이므로, 자바 네트워킹 프로그램은 특정 운영체제의 기능을 활용하기 어렵습니다.

 - 자바는 멀티스레드를 지원하므로, 자바 네트워킹 프로그램은 스레드 간의 동기화 문제에 주의해야 합니다.

 - 자바는 NIO를 지원하므로, 자바 네트워킹 프로그램은 비동기 입출력의 복잡성에 대처해야 합니다.

 

 


 

 

자바 네트워킹의 개요

이 글에서는 자바 네트워킹에 대해 알아보았습니다. 자바 네트워킹이란 자바에서 네트워크를 통해 데이터를 주고받는 기술을 말합니다. 자바는 네트워킹을 위한 다양한 클래스와 인터페이스를 제공하므로 소켓 프로그래밍, HTTP 통신, 웹소켓 등을 쉽게 구현할 수 있습니다. 또한, 자바는 플랫폼 독립적이고 멀티스레드이며 NIO를 지원하는 언어이므로, 높은 성능과 확장성을 가진 네트워킹 프로그램을 작성할 수 있습니다. 하지만, 이러한 장점들은 동시에 단점이 될 수도 있으므로, 주의 깊게 사용해야 합니다.

이 글을 읽으시면서 자바 네트워킹에 대해 조금이라도 이해하셨다면 기쁩니다. 다음 글에서는 자바 웹소켓에 대해 알아보겠습니다. 웹소켓은 실시간 양방향 통신을 가능하게 하는 기술입니다. 웹소켓에 대해 궁금하신 분들은 꼭 읽어보세요!

 

 

 

 

반응형