KRX(한국거래소) 시세 데이터는 보통 UDP Multicast 방식으로 전송됩니다. Java에서 이를 수신하려면 MulticastSocket을 사용해야 하며, 특히 리눅스 서버 환경에서는 **네트워크 인터페이스(Network Interface)**를 명확하게 지정해주는 것이 중요합니다.
가장 최신 방식인 Java 7 이후의 NIO와 MulticastSocket을 이용한 샘플 코드를 작성해 드립니다.
KRX 시세 UDP 수신 Java 샘플
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.StandardSocketOptions;
import java.util.Enumeration;
public class KrxUdpReceiver {
public static void main(String[] args) {
// 1. 코스콤/KRX에서 제공한 설정 정보 (예시)
String mcastIp = "239.1.1.1"; // 멀티캐스트 그룹 IP
int port = 12345; // 포트 번호
String interfaceName = "eth0"; // 데이터가 들어오는 랜카드 이름 (ip addr로 확인)
try {
// 2. 멀티캐스트 소켓 생성 및 포트 바인딩
MulticastSocket socket = new MulticastSocket(port);
// 소켓 옵션 설정 (포트 재사용)
socket.setReuseAddress(true);
// 3. 네트워크 인터페이스 설정
// 서버에 랜카드가 여러 개인 경우, 데이터를 받을 랜카드를 명확히 지정해야 함
NetworkInterface networkInterface = NetworkInterface.getByName(interfaceName);
if (networkInterface == null) {
// 인터페이스 이름을 모를 경우 첫 번째 유효한 인터페이스 선택 (주의 필요)
networkInterface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
}
// 4. 멀티캐스트 그룹 가입 (IGMP Join)
InetAddress group = InetAddress.getByName(mcastIp);
InetSocketAddress groupAddress = new InetSocketAddress(group, port);
socket.joinGroup(groupAddress, networkInterface);
System.out.println(String.format("Listening KRX UDP on %s:%d (Interface: %s)...",
mcastIp, port, networkInterface.getName()));
// 5. 수신 버퍼 설정 (KRX 패킷은 보통 MTU 사이즈인 1500바이트 이하)
byte[] buffer = new byte[2048];
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 데이터 수신 (패킷이 들어올 때까지 블로킹)
socket.receive(packet);
// 6. 데이터 처리
byte[] receivedData = new byte[packet.getLength()];
System.arraycopy(packet.getData(), 0, receivedData, 0, packet.getLength());
processPacket(receivedData);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 수신된 바이너리 데이터를 처리하는 메서드
*/
private static void processPacket(byte[] data) {
// 실무에서는 여기서 전문 가이드(Spec)에 따라 바이트를 잘라 파싱합니다.
// 예: 종목코드(최초 12바이트), 현재가, 거래량 등
System.out.println("--------------------------------------------------");
System.out.println("Received Packet Length: " + data.length);
// 헥사(Hex) 출력 (디버깅용)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Math.min(data.length, 50); i++) { // 앞 50바이트만 출력
sb.append(String.format("%02X ", data[i]));
}
System.out.println("Hex Data (First 50b): " + sb.toString());
// ASCII 변환 출력 (문자열 데이터 확인용)
// KRX 데이터는 보통 EUC-KR(CP949)을 사용합니다.
try {
String rawString = new String(data, "EUC-KR");
System.out.println("Raw String: " + rawString.substring(0, Math.min(rawString.length(), 100)));
} catch (Exception e) {
System.out.println("ASCII Conversion Error");
}
}
}
주요 구현 포인트 설명

-
MulticastSocket(port): 지정된 UDP 포트로 소켓을 엽니다.
-
NetworkInterface: 개발 서버가 외부망과 내부망이 분리된 경우, 시세 데이터가 들어오는 특정 랜카드(Interface)를 지정해줘야 IGMP Join 메시지가 올바른 곳으로 나갑니다.
-
joinGroup: OS 커널에 “이 멀티캐스트 IP의 패킷을 받겠다”라고 알리는 과정입니다. (네트워크 스위치에 IGMP Report 전달)
-
socket.receive(): UDP 패킷 하나가 도착할 때까지 대기합니다.
-
바이너리 처리: 시세 데이터는 숫자와 문자가 섞인 고정 길이 바이너리입니다. new String(data, “EUC-KR”)로 전체를 보기보다는, 가이드북에 정의된 바이트 오프셋(예: 20번 바이트부터 10바이트는 종목명)으로 잘라서 읽어야 합니다.
실행 전 체크사항
-
컴파일 및 실행:
Bashjavac KrxUdpReceiver.java java KrxUdpReceiver -
방화벽: 서버 내부 방화벽(iptables 또는 firewalld)에서 해당 UDP 포트가 열려 있어야 합니다.
-
라우팅: 멀티캐스트 대역에 대한 라우팅 경로가 설정되어 있어야 합니다.
Bash# 경로가 없다면 추가 (예시) sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0 -
성능 최적화: 실제 운영 환경(Production)에서는 Thread를 분리하거나, 고성능 처리가 필요한 경우 Netty 라이브러리나 Java NIO의 DatagramChannel을 사용하는 것이 좋습니다. (위 코드는 개발 서버 테스트용 샘플입니다.)