일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Bidirectional Associative Memory
- 패턴인식
- 증강현실
- Friendship
- NarwalFreo
- 동아리
- hopfield network
- 파이썬
- 빅데이터
- 멤버십
- Neural Network
- 신경망
- Python
- 삼성
- 신경회로망
- 나르왈프레오
- 고려대학교
- 물걸레로봇청소기추천
- 물걸레자동세척로봇청소기
- 갤럭시탭S8울트라
- 삼성전자 소프트웨어멤버십 SSM
- 가상화
- 인공지능
- 삼성소프트웨어멤버십
- 패턴 인식
- 하이퍼바이저
- Google App Engine
- SSM
- BAM
- 구글 앱 엔진
- Today
- Total
정보공간_1
[4기 광주 박주연] 바이트 데이터 변환 본문
바이트 데이터 변환
이번 글에서는 데이터를 처리하는 과정 중에서 바이트 데이터를 4바이트 정수형 데이터로 변환하는 내용을 이야기 해보려고 합니다. 소켓으로 들어오는 4바이트 데이터를 4바이트 정수형 변수 값으로 변환하는 과정에서 발생했었던 문제를 통해 사소하지만 쉽게 접할 수 있는 오류를 다시 되새겨 보고 데이터 변환 과정을 다시 되짚어 보고자 합니다.
네트워크 프로그램을 작성할 때 서로 다른 환경과, 서로 다른 곳에 위치한 컴퓨터 간의 데이터의 올바런 전송과 수신은 가장 정확하고 확실하게 처리되어야 하는 부분입니다. 이는 보내고 받는 데이터가 올바르게 전송되고 수신되어야 함을 의미합니다. 최근에는 다양한 플랫폼을 통해서 네트워크 프로그램이 작성되고 있습니다. Java, C#, C++, C 등 정말 다양한 방법이 존재합니다.
서버와 연결되는 클라이언트가 동일한 개발환경을 갖는다면 네트워크 프로그램도 데이터 변환에 대해서는 걱정할 필요가 없겠지만 동일 환경이 아닐 경우에는 바이트 단위의 데이터 통신을 생각할 수 있습니다. 이 때는 자체 프로토콜을 구성하고 송/수신할 데이터 메시지를 구성하게 됩니다.
바이트 단위의 통신은 전송을 바이트 단위로 수행하며 수신하는 쪽에서도 데이터를 바이트 단위로 읽고 원래의 데이터로 복원하여 사용하게 됩니다. 그림 1은 4바이트 int 정수 값을 네트워크를 통해 전송하고자 할 때의 바이트 단위 통신의 예를 보여줍니다.
그림 1. 바이트 데이터 통신의 예
이 것은 4바이트 Int 정수 값을 소켓을 통해 전송할 때 4 byte의 바이트 값으로 변경하고 이를 소켓을 통해 전송하면 C, C#, Java 등 다른 개발 환경에서라도 4 byte의 데이터 값을 읽고 원래의 Int 정수 값으로 변환해 사용하도록 하는 것입니다.
그림 1과 같이 바이트 데이터 처리 과정을 통해서 개발환경이 다른 환경에서도 데이터를 전송하고 수신할 수 있습니다.
(서버와 클라이언트 간의 프로토콜을 설계하고 교환할 데이터 메시지를 구성하는 것은 이야기 하고자 하는 내용의 범위를 벗어나기 때문에 여기서는 생략하도록 하겠습니다.)
그렇다면 전송을 위해 소켓에 데이터를 쓰기 전에 데이터 변환의 예로 4바이트 정수 값을 byte 값으로 변환하는 과정을 살펴보겠습니다. 그림 2는 int 정수 값의 byte 변환을 보여줍니다.
그림 2. 4바이트 정수 값의 바이트 변환
데이터를 전송하는 쪽에서는 바이트로 값을 변환하여 전송하게 되며 전송을 위한 데이터 변환은 쉬프트(Shift) 연산자를 사용하여 처리합니다. 쉬프트 연산자를 사용하여 1바이트(8비트) 단위로 잘라낸 후 바이트 배열에 할당하는 것을 알 수 있습니다.
(Big-endian형태로 바이트 순서를 맞추기
위해 오른쪽으로 Shift 하면서 값을 잘라냄)
그리고 바이트로 변환되어 전송된 데이터를 수신한 쪽에서는 원래의 데이터로의 복원을 위해 정수형 데이터로의 변환을 거치게 됩니다. 그림 3은 4바이트 데이터를 4바이트 정수형 값으로 변환하는 과정을 보여줍니다.
그림 3. 4바이트 데이터의 정수 값 변환
바이트 배열의 값을 정수형 변수 값으로 변환하는 과정은 앞서 설명한 내용을 역으로 하는 과정입니다. 바이트를 하나씩 자릿수에 맞춰 쉬프트 시키면서 이를 결과값에 더하게 됩니다.
이러한 간단한 과정을 통해 서로 다른 환경에서도 데이터를 교환하고 사용하게 됩니다.
하지만 바이트를 정수형 값으로 변환하는 과정에는 문제가 있습니다.
바로 그림 2에서 제시된 값에 대한 변환은 문제가 없지만 부호비트의 확장에 대한 부분이 고려되지 않았기 때문에 다른 값에서는 문제가 발생하게 됩니다.
다시 천천히 예제를 살펴보면 만약 부호비트 가 설정된 0x87과 같은 값을 변환한다면 결과는 전혀 다른 값을 갖게 됩니다. 그림 4은 이러한 의도되지 않은 상황의 변환 오류에 대한 예를 보여줍니다.
그림 4. 바이트 변환 오류 예
0x12, 0x87, 0x56, 0x34 바이트 배열을 정수 값으로 변환하였을 때는 310,859,316 값이 나와야 하지만 실제 변환을 해보면 294,082,168 값이 나오는 것을 알 수 있습니다. 네트워크 프로그램 작성과 같은 서버/클라이언트의 데이터 교환에서는 정확한 값을 주고 받는 것이 중요한데 위와 같은 상황은 큰 문제가 될 수 있습니다.
변환의 문제는 데이터를 쉬프트 연산할 때 연산을 위해 1 바이트 값이 4 바이트 정수 값으로 확장되면서 발생합니다. 그림 5는 바이트 변수의 값이 확장되는 예를 보여줍니다.
그림 5. 변수 확장의 예
변수의 형이 확장될 때(형이 변환될 때) 확장되기 전의 값을 그대로 유지하기 위해서는 부호 비트를 확장되는 부분에 채우게 됩니다. (부호 비트로 확장하지 않으면 값이 달라지게 되므로..)
따라서 4바이트 배열의 값을 4바이트 정수형 값으로 변환할 때는 부호 비트의 확장을 고려하여 비트 연산을 수행해야 합니다. 그림 6은 변수 확장을 고려한 변환 처리의 예를 보여줍니다.
그림 6. 올바른 바이트 변환의 예
4바이트 배열의 바이트 값이 쉬프트 연산을 위해 데이터가 4바이트로 확장될 때 하위 1바이트(원래의 바이트 값) 값만을 비트 연산(&)을 통해 취합니다. 이를 바이트의 자릿수에 맞게 쉬프트 연산을 수행하면서 더해 나가면 원래의 값으로 올바르게 변환할 수 있습니다.
이번 글에서는 서로 다른 환경에서 데이터를 주고 받을 때 이용할 수 있는 바이트 단위의 데이터 통신에서 사소하지만 쉽게 만날 수 있는 데이터 변환 문제를 이야기하였습니다. 이를 통해서 데이터 변환 과정에서 비트연산, 쉬프트 연산을 사용하는 것과 데이터 확장에서 부호 비트가 채워지는 부분을 유의해야 하는 것을 알 수 있었습니다.
감사합니다. ^.^
'IT 놀이터 > Elite Member Tech & Talk' 카테고리의 다른 글
[4기 강남 이상훈] What's New in Android 4.4 - 모두를 위한 안드로이드 (0) | 2013.12.04 |
---|---|
[4기 강북 송용길] Unit test with JUnit(4) (0) | 2013.12.04 |
[4기 광주 박주연] Java Generic 이해 (0) | 2013.12.04 |
[4기 수원 전낙현] VS 2013 #3 (0) | 2013.12.02 |
[4기 수원 전낙현] VS 2013 #2 (0) | 2013.12.02 |