역할설명
✅ 1. 소켓 통신(Socket Communication) 이란?
📌 정의
양쪽 컴퓨터(또는 장비)가 네트워크상에서 직접 데이터를 주고받기 위한 통로를 만드는 것이에요. 국제통신규약에 따라. 내부적으로 InputStream, OutputStream으로 구성돼요. 스트림의 기본 단위는 byte 배열, 즉 버퍼입니다. (모든 소켓은 내부적으로 버퍼로 구현. 버퍼라서 소켓이 아니고 버퍼는 수단임)
Java에서 소켓 데이터를 주고받는 도구 (InputStream, OutputStream)
메모리상에서 임시로 데이터를 저장하는 공간
byte[] buffer = new byte[1024];
inputStream.read(buffer);
→ 한 번에 하나씩 1바이트씩 주고받지 않고,
→ 어느 정도 모아서(또는 준비해서) 한 덩어리씩 주고받습니다.
✔ 모든 소켓 통신이 버퍼를 쓰는 이유는 성능 때문이에요. 전송 최적화 기법이 버퍼
Zipher 프린터와 Java 서버가 “전화 연결”처럼 통신하는 구조라고 보면 돼요.
- Java에서는 이런 식으로 열죠:
Socket socket = new Socket("192.168.0.100", 3003);
// 1. 연결 (TCP 규약에 따라 3-way handshake)
// 2. 데이터 전송 (Socket → OutputStream → byte buffer → 전송)
// 3. 데이터 수신 (InputStream → byte buffer → 문자열로 해석)
- 위 코드는 192.168.0.100 IP의 장비(예: 프린터)의 3003번 포트로 연결하는 거예요.
📶 소켓 통신 구성
역할 | 설명 |
클라이언트 | 요청하는 쪽 (예: Java 서버가 프린터에 명령 전송) |
서버 | 요청을 받는 쪽 (예: 프린터가 명령 수신 후 응답) |
포트 | 주소 중 하나 (예: 3003 포트에서 프린터 대기 중) |
🔁 예시 흐름
Java
→ 소켓 연결(IP:192.168.0.100, Port:3003)
→ "SEL|WeightLabel|중량=12.34kg\r" 전송 ← "ACK\r" 응답 수신
→ "PRN\r" 전송 ← "ACK\r" 응답 수신
💬 왜 소켓을 쓰나요?
- 빠르다 (HTTP보다 빠름)
- 양방향 실시간 통신 가능
- Zipher 프린터는 기본적으로 TCP/IP 소켓으로 대기 중
✅ 2. Java에서 Socket 통신 구현 방법
Zipher는 TCP 기반이라 (연결만드는 방법, 데이터 전송방법, 순서보장, 오류처리 방법을 정해놓은 국제적으로 표준화된 규약에 따라 만들었기 때문에) Java에서 Socket 클래스로(가 그 규약대로 구현해둔 도구라서) 쉽게 연결 가능해요.
new Socket(ip, port) //자바가 TCP연결 열어서 스트림으로 전송/수신 가능한 상태가 된다.
( 신뢰성 보장형 프로토콜. 정확한 명령 처리가 필요한 장비는 무조건 TCP를 사용해야 함. 반대개념 UDP)
소켓 통신은 내부적으로 데이터를 전부 byte배열(buffer)로 주고받습니다.
socket.getOutputStream().write("SLA|Job|label=한라봉\r".getBytes("UTF-16LE"));
//인코딩 방식을 넘기지 않으면 JVM설정(OS)따라서 윈도우의 경우 기본 MS949 일 가능성이 높음
☕ Java 예제 코드 (Zipher 명령어 보내기)
import java.io.*;
import java.net.Socket;
public class ZipherClient {
public static void main(String[] args) {
String printerIp = "192.168.0.100";
int printerPort = 3003;
try (Socket socket = new Socket(printerIp, printerPort);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "US-ASCII"));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "US-ASCII"))) {
// 1. 작업 선택
send(writer, reader, "SLA|WeightJob|weight=12.34kg");
// 2. 출력 실행
send(writer, reader, "PRN");
} catch (IOException e) {
e.printStackTrace();
}
}
private static void send(BufferedWriter writer, BufferedReader reader, String command) throws IOException {
writer.write(command + "\\r"); // \\r은 필수!
writer.flush();
String response = reader.readLine();
System.out.println(">> " + command);
System.out.println("<< " + response); // 예: ACK 또는 ERR
}
}
✅ 3. Socket 통신이 빠른 이유
🔥 이유는 "직접 연결 + 스트리밍"이기 때문이에요.
방식 과정 속도 비교
HTTP | 요청 → 연결 → 헤더 → 데이터 → 응답 | 느림 (수십 ~ 수백 ms) |
Socket | 이미 연결된 상태에서 데이터만 송수신 | 빠름 (수 ms, 실시간 수준) |
- Socket은 연결만 되면 바로 송수신 가능
- HTTP는 요청마다 연결을 새로 열어야 함
- Zipher도 실시간 통신(TCP 기반)이기 때문에 Socket과 궁합이 좋음
✅ 4. 저울까지 연동한 전체 구조
Zipher 외에 저울 연동까지 포함된 실무 구조는 아래와 같아요:
-
[저울 (RS232)] ← 시리얼 통신 → [Java 백엔드] ←→ [Vue 프론트] ↓ (TCP) → [Zipher 프린터]
📌 각 컴포넌트 설명
구성 요소역할
저울 | RS232(시리얼)로 무게 측정값 전송 |
Java 백엔드 | 저울과 시리얼 연결, 중량 수신 + Vue에 전달 + Zipher 명령 생성 |
Vue 프론트 | 현재 중량 보여주기, 인쇄 요청 버튼 |
Zipher 프린터 | Java로부터 명령 수신 후 라벨 인쇄 |
🛠 실무 구현 포인트
- Java는 jSerialComm 같은 라이브러리로 저울 데이터 읽음
- 읽은 무게를 메모리에 저장하거나 WebSocket/REST로 Vue에 보냄
- Vue에서 "인쇄" 버튼 → Java로 POST /print → Java가 Zipher에 SEL, PRN 명령 전송
✅저울 연동은 Java에서 처리하는 게 맞을까, Vue에서?
✅ 정답: Java가 저울과 직접 연결하는 게 맞습니다
이유 | 설명 |
Vue는 웹 브라우저에서 돌아감 | → 시리얼 포트를 직접 읽을 수 없음 (보안 제한) |
Java는 서버 또는 PC 앱 | → 시리얼 통신 가능 (jSerialComm 등) |
Vue는 표시용 + 전송용 | → 무게만 보여주고 Java API에 전달해서 DB 저장 |
✅ 보너스: 동작 흐름 예시
1. 저울 → Java로 "12.34kg" 전송 2. Vue에 현재 중량 표시됨 3. 사용자가 Vue에서 "출력" 버튼 클릭 4. Java가 Zipher 프린터에 명령 전송: SEL|WeightJob|weight=12.34kg\r PRN\r 5. 프린터에서 라벨 인쇄됨
💬 추가학습
- 저울 연동을 위한 Java 시리얼통신 코드 예제
- Vue + WebSocket 실시간 무게 표시 예제
- Spring Boot API + 프린터 모듈 구성
댓글