[App 개발] 인텔맥에 대처하는 우리의 자세 ㅡㅡ;
본문
그래서 저도 맥북 프로를 질렀습니다. ㅠㅠ
어제 하루종일 프로그램을 짜고 컴파일을 하는데, 컴파일 속도가 기존 파워북에 비해서 정말 발군의 능력을 갖추고 있었다는 것을 몸으로 확인할 수 있었으며, 에디터도 빨라서 훨씬 작업이 경쾌하게 이루어질 수 있었습니다.
아시다시피 Xcode 에서 유니버설 바이너리를 컴파일하는 것은 무척 쉽습니다. Command+I 를 누르셔서 Project Info 를 보시면, 두 번째 탭 Build 의 Architecture 에서 Setting 을 더블클릭하면 PowerPC 로 컴파일할 것인가, Intel 로 컴파일할 것인가를 선택할 수 있습니다. 여기서 두 개 모두 체크하면 바로 그 Universal binary 로 컴파일이 되는 것이지요. 요즘은 뒤에 붙인 binary 라는 것이 너무 개발자틱해서 그런지 Universal Applications 이라고 부르는 것 같습니다. 웬만하면 유니버설 이라고만 불러주어도 될 듯...
그런데, 많은 개발자들이 우려하고 걱정하는 것이 있으니, Big Endian/Little Endian 문제입니다. 전통적으로 인텔은 Little Endian 을 선호해 왔고, 모토롤라, 선, IBM 등은 Big Endian 을 사용하고 있습니다. Java 가 Big Endian 을 주로 사용하고 있다는 것을, 경험있는 자바 개발자들은 잘 아시리라 생각합니다. 저도 그것때문에 고생을 많이 했습니다. ㅡㅡ;
코코아 개발자들의 경우는 raw data 를 취급할 일이 거의 없기때문에 유니버설 프로그램 개발이 어렵지 않습니다. 하지만, 데이터를 바이트/비트별로 만져줄 일이 많은 카본 개발자들에게는 대단히 민감한 사안이 됩니다.
"컴파일러가 알아서 해주는 것 아니냐?"
이렇게 말씀하시는 사람은 큰 규모의 소프트웨어를 제작해본 경험이 없는 사람이라고 할 수 있겠습니다. ㅡㅡ;
Byte ordering 이 문제되는 경우는 크게는 두 가지 경우입니다. 데이터 파일 입출력, 그리고 네트웍 데이터 교환입니다. 자신의 플랫폼이 Big Endian 이냐 Little Endian 이냐를 확실히 알고 있다면 그에 맞게 프로그램을 작성해 주면 됩니다. 그러나, 유니버설 소프트웨어의 경우는 자신의 플랫폼에 따라서 루틴을 다르게 사용해야 합니다.
애플이 내놓은 해법은 무엇인가?
카본 개발자들 (그리고 코코아 개발자들도 마찬가지) 이 쓸 수 있는 바이트 오더링 툴은 몇 가지가 있습니다만, 가장 직관적인 방법은 CoreEndian 을 이용하는 것입니다. CoreServices 에 포함되어 있습니다.
* 단순 무식 바이트 정렬 함수
가장 기본적인 루틴으로서 일단 바이트를 정렬하는 함수들이 필요하겠지요? 대략 세 가지가 준비되어 있습니다.
UInt16 in16, out16 ; // 대충 이런 식으로 변수를 선언... ㅡㅡ;
out16 = Endian16_Swap( in16 ) ;
out32 = Endian32_Swap( in32 ) ;
out64 = Endian64_Swap( in64 ) ;
말 그대로 바이트 오더를 뒤바꾸는 함수입니다. 예를 들어 Endian32_Swap 함수를 호출하게 되면, 4바이트 (32비트) 데이터가 1234 로 되어 있던 것이 4321 로 뒤바뀌게 되는 것이지요.
사실 말도 할 수 없이 간단한 이 함수에 (헤더에 #define 으로 짜여있음 ㅡㅡ;), 자기 플랫폼이 어떤 것인지만 알아내면 이제 만사는 끝인 것이죠? 그런데, 자기 프로그램이 현재 어떤 플랫폼에서 돌고 있는 것은 어떻게 알아낼 수 있을까요? __INTEL__ 이나 __PPC__ 같은 선언문을 체크할까요?
친절한 애플, 다음과 같은 좋은 함수들을 제공해 주었습니다.
out = EndianS16_BtoN( in ) ;
무슨 뜻인고...
S 는 Signed (부호있는) 변수를 뜻합니다. 반대말은 U (Unsigned) 가 되겠지요?
16 은 16비트용 함수입니다. 32 와 64 등이 있겠지요.
B 는 Big Endian 입니다. L 을 쓰면 Little Endian 이 되겠지요? N 은 Native 입니다. 현재 프로그램이 동작하는 고유 바이트 정렬형을 말합니다.
따라서, 디스크에 저장되어 있는 부호 있는 Big Endian 형 32비트 데이터를 현재 플랫폼에 읽어들인다면 다음과 같은 함수를 쓰게 됩니다.
out = EndianS32_BtoN( in ) ;
반대로, 현재 작업중인 부호 없는 16비트 데이터를 Little Endian 형으로 디스크에 저장하고 싶다면, 다음과 같이 데이터를 변환하여 파일에 저장하면 됩니다.
out = EndianU16_NtoL( in ) ;
간단하죠? 하지만, 이런 작업을 프로그램 내에서 계속 계속 반복한다는 것은 전체 프로그램의 효율을 떨어뜨리는 행위이므로, 바이트 정렬은 부득이하게 필요한 곳에서 최소한으로 사용하는 것이 올바른 자세라고 할 수 있습니다. 아울러, __LITTLE_ENDIAN__ 등의 예약어 등을 함부로 참조해서 프로그램을 짜게 되면 나중에 가서 또 다시 고생하게 될 수 있습니다.
그 외에도 CoreEndian 에서는 플랫폼에 관계없이 바이트 오더링을 지정할 수 있는 데이터형도 제공하고 있습니다. 예를 들어 BigEndianLong 이라는 변수 형태는 어떤 플랫폼에 가져가더라도 항상 BigEndian 형의 바이트 정렬을 하도록 되어 있습니다.
CoreEndian 은 이렇고, CoreFoundation 에서도 바이트 정렬 루틴을 제공합니다. 이 내용에 대해서는 애플 개발자 페이지에 아주 concise 하게 잘 정리된 것이 있군요.
http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_byte_swap/chapter_4_section_5.html
대략 이정도만 있으면 유니버설 소프트웨어를 만들 준비가 다 된 것 같습니다. ^^
최신글이 없습니다.
최신글이 없습니다.
댓글목록 6
美청년.영환군님의 댓글
오.. 큰 프로젝트 진행의 경험이 없던 저로서는 새로운 한가지를 알게되었네요.
프로그래밍에 앞서 얼마나 그 환경을 이해하느냐가 중요한지 알게되었슴돠.
잿빛하늘님의 댓글
제목만 보고 재미있을까 싶어 들어왔으나
저와는 전혀 딴 동네의 얘기였군요. -,.-"a
hongjuny님의 댓글
죄송하네요 ^^;;;
잿빛하늘님의 댓글
죄송까지야... ㅎㅎ
머쓱해서 쓸데없는 리플 달아봤습니다. ^^
향기님의 댓글
Big Endian, Little Endian은 볼 때마다 헷갈리네요.^^
원샷원킬님의 댓글
제목만 보고 재미있을까 싶어 들어왔으나
저와는 전혀 딴 동네의 얘기였군요. -,.-"a. - 2