KRX(한국거래소) 시세 데이터는 보통 UDP Multicast 방식 수신샘플(JAVA)

KRX(한국거래소) 시세 데이터는 보통 UDP Multicast 방식으로 전송됩니다. Java에서 이를 수신하려면 MulticastSocket을 사용해야 하며, 특히 리눅스 서버 환경에서는 **네트워크 인터페이스(Network Interface)**를 명확하게 지정해주는 것이 중요합니다.

가장 최신 방식인 Java 7 이후의 NIO와 MulticastSocket을 이용한 샘플 코드를 작성해 드립니다.

KRX 시세 UDP 수신 Java 샘플

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");
        }
    }
}

주요 구현 포인트 설명

 KRX(한국거래소) 시세 데이터는 보통 UDP Multicast 방식 수신샘플(JAVA)

  1. MulticastSocket(port): 지정된 UDP 포트로 소켓을 엽니다.

  2. NetworkInterface: 개발 서버가 외부망과 내부망이 분리된 경우, 시세 데이터가 들어오는 특정 랜카드(Interface)를 지정해줘야 IGMP Join 메시지가 올바른 곳으로 나갑니다.

  3. joinGroup: OS 커널에 “이 멀티캐스트 IP의 패킷을 받겠다”라고 알리는 과정입니다. (네트워크 스위치에 IGMP Report 전달)

  4. socket.receive(): UDP 패킷 하나가 도착할 때까지 대기합니다.

  5. 바이너리 처리: 시세 데이터는 숫자와 문자가 섞인 고정 길이 바이너리입니다. new String(data, “EUC-KR”)로 전체를 보기보다는, 가이드북에 정의된 바이트 오프셋(예: 20번 바이트부터 10바이트는 종목명)으로 잘라서 읽어야 합니다.

실행 전 체크사항

  • 컴파일 및 실행:

    Bash

    javac 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을 사용하는 것이 좋습니다. (위 코드는 개발 서버 테스트용 샘플입니다.)