메신저는 이미 수백만 명의 사용자를 가질만큼 규모가 급성장하고 있다. MSN 뿐만 아니라 AOL, Yahoo, ICQ(AOL과 통합되었음) 등 다양한 메신저들이 이미 인터넷 시장에서 ‘작은 포탈’로 주목받고 있다. 이들 메신저는 단순한 메시지 전송 기능과 파일 전송 기능을 넘어서서 교육, 증권, 은행, 음악, 복권 등 다양한 서비스를 함께 제공하고 있어 사용자들에게 인터넷만큼 편리하게 이용된다.
그러나 서로 다른 메신저를 사용하는 사용자간의 대화나 파일 전송은 불가능하다는 단점이 있다. 그 뿐만 아니라 친구 등록에는 한계가 있어서 두 개 이상의 메신저 계정을 가지고 있는 사용자는 동시에 여러 계정을 이용할 수 없다. 우리가 여기서 구현해 보고자 하는 것은 이런 불편함을 해결하고 부가적인 기능을 충분히 수용할 수 있는 임베디드 메신저의 기본 구조이다.
다중 프로토콜과 다중 계정 지원하는 SWIM
이번 연재에 소개하는 임베디드 메신저는 필자가 삼성 소프트웨어 멤버십 회원으로 활동하며 제작한 프로그램이다. 필자는 2002년 삼성 소프트웨어 멤버십으로의 진입을 한번 실패한 후, 2003년 자바 가상머신을 완성하는 단계에서 많은 프로그램과 프로젝트를 수행한 경험으로 다시 도전했다. 새로운 형태의 임베디드 시스템용 메모리 관리 알고리즘을 개발해는데 기존 방법보다 매우 빠르고 효율적이었다. 그 프로젝트를 중심으로 다른 여러 가지 지식들을 정리하여 멤버십을 시작했고 현재 1년째 회원으로 활동하고 있다.
2003년 제1회 임베디드 소프트웨어 공모대전에서 지정 공모 주제가 두 가지가 나왔다. 그중 하나는 ‘모바일 메신저 제작’이었다. 이미 메신저 이용을 많이 해본 필자의 팀은 한번쯤 만들어 보고 싶었던 모바일 메신저 제작을 선택했다. MSN 메신저를 기반으로 한 ‘슈퍼 와이어리스 인스턴스 메신저(Super Wireless Instance Messenger, SWIM)’라는 프로젝트 명을 앞세우고 브레인 스토밍을 통해 프로젝트 기안을 시작했다.
오랜 시간 토의 끝에 나온 아이디어는 여러 개의 메신저 프로토콜을 통합 지원하고 여러 사용자 계정 역시 동시에 지원하는 메신저를 제작하자는 것이었다. 또한 부가 기능으로 PDA에 있는 기능인 일정관리 기능, 메모장, 효과음 재생, 이미지 뷰어 등의 기능을 넣어서 사용자 편의성을 최대한 고려하기로 하였다. 마지막으로 사용자가 직접 이용할 터치 패드와 GUI 구성을 기존 메신저와 거의 동일하게 제작함으로써 사용자가 별도로 이용법을 숙지해야 하는 불편함을 제거키로 했다.
프로그램을 제작하는 동안 GAIM 같이 다중 프로토콜을 동시에 지원하는 뛰어난 프로그램을 많이 참고했다. 하지만 한 가지 미지수가 있었다. MSN 프로토콜은 작년 10월 15일을 이후로 MSN 프로토콜 버전 7(MSNP7) 이하의 접속을 차단시켰다. 즉 최신 버전이 아니면 접속을 못하게 한다는 것이었다. 공모전 기한은 11월 초이므로 그 전까지 라이브러리를 구하지 못한다면 프로젝트는 실패하게 되는 것이었다.
그 소식을 일찍 알게 된 필자의 팀은 MSN 프로토콜 버전 8(MSNP8)을 목표로 제작에 들어갔다. 1차, 2차의 실패를 거듭하면서 MSN 프로토콜 제작은 조금씩 다듬어져 갔고 마지막 3차 프로토콜 제작에서 어느 정도 완성도 있는 MSNP7이 완성되었다. 그리고 10월 13일 MSN 서버로부터 차단되기 이틀 전 MSNP8을 완성시켰다. 이렇게 제작하여 완성된 SWIM은 MSN, Yahoo, ICQ, AOL 프로토콜을 동시 지원하고 다중 사용자 계정 역시 동시 접속이 가능하며 여러 가지 부가 기능이 추가된 프로그램으로 완성되었다([화면 1]).
일단 시작해 보는 임베디드 프로그래밍
한번도 임베디드 프로그래밍을 한 적이 없는 프로그래머라면 일반 임베디드 보드를 구입해서 ‘시작’해 볼 것을 권하고 싶다. 시작하기 전에는 막막하게만 느껴졌던 모든 것들이 시작하고 나서는 조금씩 풀려나갈 것이다. 부트로더 탑재에서부터 크로스 컴파일까지 한번 해 본 이후에는 조금 익숙해질 것이고, 다음 번에는 더 깊은 부분까지 살펴 볼 수 있을 것이다. 임베디드 프로그래밍이라고 해서 특별한 것은 없다. 다만 하드웨어에서 소프트웨어까지 특정 목적에 맞게 최적화시켜 놓은 것이기 때문에 제약이 많아 어렵게 느껴질 수도 있다.
필자는 이 글을 통해 임베디드 시스템의 모든 것을 알려주기보다는 어떻게 하면 임베디드 시스템으로 접근할 수 있는지 소프트웨어적인 관점에서 설명하고자 한다. 또한 임베디드 보드가 없더라도 리눅스만 설치되어 있다면 본 기사에서 다룰 임베디드용 메신저 제작에는 지장이 없다. 메신저를 만들면서 임베디드 프로그래밍에 대한 이해를 넓혀갈 수 있을 것이다. 자! 이제 임베디드 프로그래밍을 시작해 보자.
‘PC에 리눅스 설치하기’부터
메신저 제작에 앞서서 준비해야 할 것이 몇 가지 있다. 임베디드 프로그래밍을 할 수 있는 임베디드 시스템 구축과 개발 툴의 설치이다. 가장 먼저 해야 할 것은 ‘PC에 리눅스 설치하기’. 설치할 때 패키지 중에서 Glade와 tftp 등의 필요한 패키지를 선택해서 설치해야 한다. tftp(Trivial File Transfer Protocol)는 파일을 송수신할 수 있는 매우 단순한 형태의 파일전송 프로그램이다. 주로 커널이나 부트로더 전송시 이용된다. 그리고 Glade는 GTK로 GUI를 꾸밀 예정이라면 설치하는 것이 좋다. 쉽게 GTK 코드를 생성해 주기 때문에 유용하게 쓸 수 있을 것이다.
PC에 리눅스 설치하기가 끝났다면 임베디드 보드를 하나 구입하자. 이미 시중에는 임베디드 보드가 다양하게 출시돼 있다. 주로 ARM 계열과 DSP 계열의 보드들인데 영상 처리나 고속데이터 처리 위주의 프로그래밍이라면 DSP를 추천하고 일반적인 프로그래밍에서는 ARM을 추천하고 싶다. 처음 시작하기에는 ARM 계열의 보드인 팜팜테크의 Tynuxbox X를 이용한다면 쉽게 접근할 수 있을 것이다. Tynuxbox X의 경우 Intel Xscale PXA255를 탑재하고 있고 그래픽 LCD부터 TCP/IP 모듈까지 기본적인 하드웨어 모듈을 제공하기 때문에 초보자도 쉽게 이용 가능하다. 현재 CDMA 모듈을 탑재한 Tynuxbox Xe까지 출시되어 있다.
보드를 준비했다면 부트로더와 OS를 타켓 보드에 설치하고 크로스 컴파일 환경까지 구축해 보자. 제공되는 매뉴얼을 하나하나 따라가면서 설치하면 어렵지 않게 할 수 있을 것이다. 간혹 문제가 발생하거나 어려움에 빠졌을 때는 보드 제작사의 Q&A를 이용해서 해결하자.
소스 제작 및 관리는 이렇게
임베디드 프로그래밍뿐만 아니라 모든 프로그래밍에서 소스를 제작하는 것과 관리하는 것은 매우 중요하다. 임베디드 프로그래밍에서는 크로스 컴파일의 과정을 거치기 때문에 더욱 편리한 툴이 필요하다. IDE 툴인 ESTO는 ETRI에서 개발한 프로그래밍 툴이다. 크로스 컴파일부터 타켓보드 전송 후 실행하는 기능까지 다양한 기능을 가지고 있다. 임베디드 프로그래밍을 하다 보면 컴파일, 전송, 실행의 세 과정을 반복하는 경우가 많은데 이를 한번에 처리해 주기 때문에 매우 편리하다. 또한 대규모 작업이 되면 makefile을 매번 수정하는 일 또한 번거로운 작업인데 그런 작업을 간단하게 해결할 수 있다. vi에서 작업을 해도 상관은 없지만 이런 IDE 툴을 이용해서 개발을 한다면 개발 속도를 더 높일 수 있을 것이다.
대규모 프로젝트라면 소스와 문서를 관리하는 것이 매우 중요하다. 한 번의 실수로 그 동안의 결과를 날려버릴 수도 있다. 또한 여러 명이 동시에 비슷한 분야의 일을 한다면 소스가 섞여버리는 경우도 있다. 이를 위해 소스 관리를 할 필요가 있다. 리눅스에서는 CVS (Concurrent Versions System)를 지원하고 있는데 서버로 셋팅을 해 주고 CVS를 이용해서 소스를 관리하기를 추천한다. 리눅스가 아니라도 CVS는 얼마든지 이용 가능하므로 소스나 문서를 관리하기에 매우 유용하리라 생각한다. CVS는 버전별로 소스를 관리해 주고 동시작업으로 인한 소스 충돌에 대해서도 어느 정도 해결책을 제시해 주기 때문에 대규모 프로젝트에서는 필수적이라 할 수 있다.
필자 팀은 CVS의 덕을 많이 보았다. 프로젝트 마무리를 앞두고 하드코딩 모드(?)에 돌입해서 프로그래밍을 하다가 소스가 뒤섞여버리는 바람에 프로젝트를 거의 실패할뻔 했다. 그때 CVS를 이용해서 간단히 1주 전의 소스로 모든 것을 되돌릴 수 있었고 1주 전의 코드부터 새로 시작해서 그 상황을 복구할 수 있었다. 프로그램을 제작하는 일만큼이나 그 프로그램을 관리하는 일 역시 중요하다는 것을 항상 명심하자.
메신저의 기본 틀 정하기
모든 프로그램이 마찬가지겠지만 규모가 큰 프로그램일수록 설계가 중요하다. 간단한 블럭 다이어그램이라도 하나 그려두고 시작할 수 있다면 프로젝트에 중요한 나침반 역할을 할 것이다. 메신저는 구조가 매우 복잡하게 얽혀있다. 프로토콜 자체가 공개되지 않는 경우가 허다하기 때문에 어떤 방식으로 처리해야 하는지에 대한 정답은 없다. 가능한 자신이 만들려고 하는 프로그램의 스펙을 면밀히 분석하라고 권하고 싶다. 우리가 만들 MSN 프로토콜 역시 만만치 않은 분석 작업을 거쳐야 한다. 그 전에 전체를 먼저 설계해 보고 세부 설계를 하면서 프로토콜을 하나씩 파악하자.
[그림 2]를 살펴보면 GUI를 기초로 여러 개의 컴포넌트와 프로토콜이 연결되어 있는 것을 볼 수 있다. 최하위의 하드웨어부터 최상위 GUI까지의 그림을 최대한 간략하게 그리는 것이 중요하다. 하지만 절대 기본 프로그램 구성을 벗어나서는 안 된다. 가령 프로토콜 안쪽에 프로토콜과 관계없는 컴포넌트가 들어가거나 실제 컴포넌트의 제어를 GUI에서 하게 되지만 GUI와는 별도로 동작하는 것처럼 그렸다면 수정하여야 한다. <그림 2>의 설계도는 간단해 보이지만 많은 내용을 내포하고 있다. 첫 설계부터 이처럼 매우 자세하게 기술할 필요는 없다. 쉽게 읽고 해석할 수 있을 정도의 설계면 충분하다. 차츰 내용이 깊이 들어가면서 세밀하게 설계하는 것이 필요하다.
하부부터 살펴보면 하드웨어 기반임을 쉽게 알 수 있다. 하지만 타겟 보드 이외에 다른 하드웨어가 없는 것을 보면 이 프로그램은 추가적인 하드웨어를 필요로 하지 않는다는 것을 알 수 있다. 운영체제 층에서도 임베디드 리눅스를 이용하며 포팅이나 기타 작업을 하지 않는다. 각 컴포넌트들은 서로 연관되기보다는 독립적으로 존재하고, 사용자에 의해서 컨트롤된다. 가장 중요한 프로토콜 부분은 다른 것들과 독립적으로 존재하고 각 프로토콜 역시 독립적으로 존재한다. 그리고 상위에는 추상 계층(Abstract Layer)을 두고 있다.
여기서 추상 계층이란 간단하게 설명하자면 다중 프로토콜을 쉽고 간단하게 제어하기 위한 계층이다. 하위의 다양한 프로토콜들을 GUI 층에서 일일이 직접 조정하지 않더라도 추상 계층을 통해서 통합 관리할 수 있도록 되어 있다. 이 계층을 이용하면 쉽게 모든 프로토콜을 제어할 수 있고 프로토콜의 추가, 삭제가 비교적 자유롭다. 이 계층의 세부사항은 잠시 후에 알아보기로 하고 전체 구성의 마지막인 GUI 부분을 보도록 하자. GUI 부분은 거의 모든 부분을 제어할 수 있도록 되어 있다. 이 구조는 매우 단순한 형태이기 때문에 세부적인 사양은 기록하지 않았지만 GUI가 매우 큰 비중으로 동작한다는 것을 알 수 있다.
우리가 만들 메신저의 기본 구조는 이와 동일하다. 여기에 추가적인 하드웨어를 탑재할 수도 있고 추가적인 컴포넌트를 얼마든지 추가할 수 있다. 각 모듈은 독립적으로 존재하지만 서로 연관성을 가지게 할 수도 있다. 다시 말해 프로그래머가 원하는대로 구조를 변경할 수 있는 폭이 매우 넓다. MSN 메신저뿐만 아니라 프로그램에 융통성을 부여하는 일은 긍정적인 면을 많이 가지고 온다.
다중 프로토콜 지원 위한 추상 계층
다양한 프로토콜을 동시에 지원하기 위해서는 통일된 접근 방법이 필요하다. 그렇지 못할 경우에는 수많은 명령어들로 인해서 복잡함이 이루 말할 수 없을 것이다. 추상 계층은 그런 복잡함을 없애주기 위해 존재하는 것이다. 만약 한 개의 프로토콜만을 제작한다면 추상 계층은 불필요한 존재가 된다. 하지만 확장성을 고려하거나 두 개 이상의 프로토콜 지원을 고려한다면 반드시 들어가야 하는 부분이다. 구조 자체는 매우 간단한 형태이지만 사용을 하고 안 하고의 차이는 엄청난 차이를 불러온다.
MSN 프로토콜은 수많은 명령어로 이루어져 있다. 접속하는 단계부터 채팅을 하는 것까지 다양한 명령이 존재한다. MSN 이외의 프로토콜 역시 많은 명령어들이 존재할 것이다. 하지만 모든 프로토콜의 명령어와 구조가 동일할 수는 없을 것이다. 실제로 MSN 프로토콜의 경우 처음 접속할 때부터 여러 서버를 거쳐서 접속하게 되므로 접속부터 다른 프로토콜과 차별화된다. 이런 것들을 동시에 컨트롤하기 위해서는 추상 계층을 이용하여 하나의 명령으로 묶어 주어야 한다. GUI에서는 한 개의 프로토콜이 있는 것과 동일한 상황을 만들어야 한다. 여러 개의 프로토콜 이용시에는 프로토콜 타입만 변경하면 동일한 명령으로 동작할 수 있도록 해야 한다.
추상 계층의 구현 순서
추상 계층을 구현하는 것에는 특별한 제약이 없다. 다만 추상 계층은 GUI 파트와 프로토콜 파트의 데이터를 정확하고 효율적으로 전달해줄 수 있어야 한다. 그러기 위해서는 크게 두 가지 파트로 나누어서 생각할 수 있다. 첫째는 GUI에서 프로토콜로 전달되는 메시지, 둘째는 프로토콜에서 GUI로 전달되는 메시지. 이 두 가지를 효율적으로 처리해 줄 수 있는 것이 추상 계층의 역할이다. GUI에서 프로토콜로 전달되는 메시지 구현 순서는 다음과 같다.
⑴ 프로토콜 파트 구현 : 각 프로토콜에 맞게 함수를 정의한다. 프로토콜 파트 내부에 계층 구조를 두어 최대한 간단하고 짧은 명령으로 처리할 수 있도록 구현한다.
⑵ GUI 파트 구현 : 프로토콜에 상관없이 동일한 명령을 이용한다. 사용자 ID에 따른 프로토콜 종류를 별도 처리하여 저장할 것. 프로토콜 파트로 메시지를 전송할 경우 해당하는 사용자 ID와 해당 프로토콜 종류만 선택하고 명령은 동일하게 이용한다.
⑶ 추상 계층 구현 : 프로토콜 종류에 따른 선택문으로 서로 다르게 처리한다. 각 프로토콜 특징에 맞도록 사용자 ID 값과 파라미터 값을 처리한다.
다음은 프로토콜에서 GUI로 전달되는 메시지 구현 순서이다. 이 순서를 머릿 속에 먼저 정리한 후 다음 단락에서 예제 코드를 보며 이해하도록 하자.
⑴ 프로토콜 파트 구현 : register_callbacks() 호출하고 정의된 콜백 함수들을 이용한다. 파라미터 처리는 일반 함수 호출과 동일하다.
⑵ GUI파트 구현 : 사용자 ID 값과 프로토콜 종류를 이용하여 각 콜백 함수를 구현한다. 프로토콜에 따른 선택문을 이용하여 서로 다르게 처리한다.
⑶ 추상 계층 구현
① PROTOCOL_CALLBACK(x)를 protocol_callback->x로 선언
② PROTOCOL_CALLBACK_TYPE(x)를 (*x)로 선언
③ 구조체 내에 콜백 함수들을 넣고 선언 후 전역변수 하나를 그 구조체로 선언(protocol_callback).
④ protocol_callback의 초기화
⑤ 콜백 함수를 등록하는 함수 제작 그리고 protocol_callback 변수에 콜백 함수 연결(register_callbacks).
⑥ 어댑터 함수들의 제작
GUI에서 프로토콜로 전달되는 메시지
GUI에서 추상 계층을 통하여 프로토콜로 메시지를 전송하는 것부터 자세히 살펴보자. [리스트 1]을 보면 함수명이 protocol_ command _remove_user로 되어 있다. protocol_command는 프로토콜 파트에 관한 명령임을 의미한다. 추상 계층은 기본적으로 명령어 파트와 콜백 파트로 나뉜다. 명령어 파트는 GUI에서 프로토콜 파트로 보내게 되는 각종 명령어들이 들어 있다. 가령 사용자가 친구와 대화를 시도하려고 한다면 GUI에서 사용자의 입력을 받고 통일된 명령으로 추상 계층에서 명령을 받게 되고, 추상 계층에서는 프로토콜 타입에 따라서 각 프로토콜별 명령을 하게 된다. [리스트 1]은 친구를 삭제하는 명령이다.
파라미터로 들어오는 값은 account_type, ID, userid, groupid가 있는데, account_type은 그 계정의 형식을 나타내는 것으로 프로토콜 타입을 의미한다. 대문자 ‘ID’는 사용자의 ID를 의미한다. 이는 동일한 프로토콜로 여러 사용자 계정 접속을 허용한다는 의미이다. 만약 이 ID에 대한 구분이 없다면 다중 사용자 접속은 불가능하다. ‘userid’는 삭제하고 싶은 상대방의 ID를 의미하며 ‘groupid’는 삭제하고 싶은 상대방이 속해 있는 그룹의 ID를 의미한다. 파라미터 값이 제대로 전달되었다면 프로토콜에 따라 분류되어 처리하게 된다. 각 프로토콜은 서로 다른 함수와 처리 과정을 가지지만 GUI 부분에서는 마치 하나의 명령으로 모든 것을 처리하는 것처럼 보인다. 실제로 MSN은 다른 프로토콜과 달리 ID 값 대신 사용자 ID에 해당하는 포인터 값을 필요로 한다. 이를 처리하기 위해 별도의 명령어가 필요한데 이런 처리를 GUI 파트에서 일일이 신경써야 한다면 통합하는 과정이 매우 힘들 것이다.
프로토콜에서 GUI로 전달되는 메시지
GUI로부터 내려오는 명령이 있다면 프로토콜 파트에서부터 올라가는 정보도 있다. 예를 들어서 다른 대화 상대로부터 메시지가 들어왔거나 다른 사용자의 상태가 바뀌었을 때 프로토콜에서 GUI로 메시지가 전달되어야 한다. 프로토콜 파트는 수많은 프로토콜과 다양한 사용자 계정을 동시에 지원하기 위해 모든 프로토콜을 항상 감시하고 있어야 하는데 이를 위해서 프로토콜 사이의 가장 기본이 되는 규칙이 필요하다. 그것은 바로 자원에 대한 독점 금지이다.
독립적인 모듈을 제작하다 보면 흔히 일어나는 문제점인 자원 점유 문제가 발생할 수 있다. 특히 수많은 네트워크 처리를 필요로 하는 프로토콜에서는 상대방으로부터 응답이 없거나 지연되면 그 순간은 계속 멈추어 있게 된다. 이렇게 자원을 점유하게 되고 시스템이 계속 멈추어 있다면 다중 프로토콜 지원은 불가능할 것이다. 또 다른 하나는 추상 계층의 명령어와 함께 콜백(Callback) 함수를 두어 프로토콜로부터 오는 메시지를 통일성있게 처리할 수 있도록 해야 한다. 실제 MSN 메신저 소스의 일부분을 보면서 살펴보자([리스트 2∼5]).
조금 난해해 보일 수도 있으나 간단한 원리이며 이용하기가 매우 쉽다. 여러 개의 프로토콜이 각자 서로 다른 콜백 함수를 가지고 있다면 GUI 파트에서 처리하기가 매우 번거롭다. 매번 비슷한 일을 처리해야 하는 함수가 수없이 생겨날 것이다. 프로토콜 파트에서는 단 한번 함수를 호출하지만 GUI 파트는 모든 프로토콜을 수용하기 위해서 동일한 기능을 하는 함수를 프로토콜 개수만큼 만들어 주어야 한다. 이를 줄이기 위해서 필요한 것이 추상 계층이다. 이 리스트들은 실제 소스의 일부이다. [리스트 2]부터 하나씩 살펴보자.
추상 계층을 이용한 코드 살펴보기
<리스트 2>에서 PROTOCOL_CALLBACK_TYPE(x)를 (*x)로 선언한 것을 볼 수 있다. 이것은 x의 포인터를 PROTOCOL_ CALLBACK_ TYPE으로 연결한다는 것을 의미한다. 예를 들어 abc()라는 함수가 있다면 abc()에 대한 포인터와 PROTOCOL_CALLBACK_TYPE(abc)와 동일하다는 의미이다. 다음으로 PROTOCOL_CALLBACK(x)는 protocol_callback->x 대신 사용하겠다는 의미이다. 이 선언문들은 코드를 읽기 쉽게 만드는 데 의의가 있다.
추상 계층에서는 다소 복잡해 보일지 모르나 GUI 파트와 프로토콜 파트에서는 매우 쉽게 이용할 수 있다. protocol_callbacks 안에 구조체로 콜백이 될 함수의 원형을 선언한다. 그 후 전역으로 콜백을 선언한다. 그리고 [리스트 3]에서는 콜백 함수를 등록하는 것을 볼 수 있다. [리스트 3]을 보면 특이한 것을 하나 발견할 수 있는데 #if ADAPTER 사이의 부분은 ADAPTER 값에 따라서 컴파일이 될 때도 있고 안 될 때도 있다. 이는 모듈 통합시 매우 유용하게 이용할 수 있는데 자바의 어댑터 클래스를 흉내낸 것이다. 모듈 통합 이전에는 콜백 함수의 원형은 선언되어 있지만 실제 함수가 없기 때문에 에러를 발생시켜 테스트를 할 수 없을 것이다. 그렇다고 마냥 GUI 파트에서 제작을 완료하기만 기다릴 수는 없다. 이를 위해 선택적으로 컴파일할 수 있게 하는 것이다.
만약 통합 이전에 GUI 파트와 분리되어 있다면 ADAPTER의 값을 1로 두어 컴파일되게 하고, GUI 파트와 통합된 상태에서 각 콜백 함수들의 구현이 완료된 상태라면 ADAPTER의 값을 0으로 두어 컴파일이 안 되게 하는 것이다. register_callbacks() 함수는 함수 포인터를 구조체 내로 넣어주는 역할을 한다. 그 과정을 마치면 protocol _callback이라는 전역 변수에 정적 구조체로 되어 있는 함수 포인터들이 연결된다. 그러면 함수의 구현부인 [리스트 4]에서는 추상 계층에서 선언된 함수명을 구현해 두었다. 보통의 함수와 차이가 없음을 알 수 있다. 단지 파라미터로 들어온 값에 의해서 각 프로토콜에 해당하는 처리를 약간 바꾸어 줄 뿐이다.
[리스트 5]는 콜백 함수의 호출부이다. 만약 프로토콜이 대기 상태로 있는 동안 서버로부터 메시지를 받았다면 이에 해당하는 처리를 하게 된다. 프로토콜 내부 처리를 마치고 GUI 파트로 콜백을 할 때 추상 계층에서 선언해둔 콜백 함수를 호출하면 된다. 그리고 마지막으로 중요한 것 한 가지, 프로그램 실행 최상단에 register_ callbacks ()를 실행시켜 각 함수들의 포인터를 구조체 안에 넣어 두면 추상 계층의 작업은 완료된다.
이처럼 다중 프로토콜을 지원하기 위해서는 생각해야 할 것이 많이 있다. 각 함수의 통일성 문제와 메모리 문제 등 다양한 문제들이 존재한다. 더욱이 임베디드 시스템과 같이 자원이 제약적인 환경에서는 더욱 힘들다. 보통 프로젝트 팀을 구성하여 프로젝트를 하다 보면 코딩 스타일이나 함수 원형을 하나 하나 맞추어 가며 일을 하기는 매우 어렵다. 프로토콜 자체가 서로 틀린 경우에는 더욱 어렵다. 이런 어려움을 추상 계층을 통해서 해결할 수 있고 동시에 다중 프로토콜과 다중 사용자 계정을 지원할 수 있는 구조를 만들어 낼 수 있는 것이다.
다음 호에서는 서버로 접속하기
이번 호에서는 임베디드 시스템에 메신저를 제작하기 위한 기획과 설계를 알아보았다. 메신저 프로토콜은 간단하게 생각하면 쉬울 것 같지만 실제 내부에서는 일련의 처리 작업들이 복잡하게 얽혀 있다. 게다가 비공개 프로토콜을 구현한다는 것은 더욱 어렵다. MSN은 지난 해 10월 15일 이후 MSN 클론들의 접속을 막기 위해 SSL 서버라는 장벽까지 설치해 두었다(이후 수많은 프로그래머들이 뚫어버렸지만). 그 외 다양한 문제거리들이 프로토콜 내에 존재한다. 그러나 프로토콜은 한번 이해하고 나면 그 다음부터는 매우 쉽게 접근이 가능하니 이번 기회를 통해 한번 접근해 보길 바란다. 만약 자신이 만든 프로그램이 MSN 메신저와 연동되어 사용될 경우 상업적으로도 매우 좋을 것 같다면 프로토콜을 구현하기보다는 마이크로소프트와 직접 계약을 맺으라고 하고 싶다. MSN의 프로토콜을 구현하기가 어려워서가 아니라 라이선스 때문이다. MSN과 어울리는 멋진 애플리케이션을 개발한다면 반드시 마이크로소프트와 계약을 체결하여야 한다.
다음 호에서는 MSN의 서버 접속 부분을 구현하겠다. 조금 더 복잡하고 심오한 이야기로 빠져들 것 같다. 프로토콜의 규칙과 여러 가지 서버들 그리고 OpenSSL에 관해 이야기를 할 것이다. 기본은 어디까지나 TCP/IP 통신이다. 하지만 통신 규약이라는 것을 이용한 통신과 자기가 정해서 이용하는 통신은 거리가 있다. 호환성을 유지하는 일은 상당한 작업을 필요로 한다.
임베디드 시스템을 어렵게 보지 말고 하나씩 알고 있는 부분부터 조금씩 접근을 해 본다면 어느새 임베디드 시스템에 대해 견문이 넓혀져 있을 것이다. ‘시작이 반’이라는 말은 정말 임베디드 시스템을 두려워하는 프로그래머들에게 해 주고 싶은 말이다. 가장 먼저 금전적인 문제부터 걸리겠지만 과감하게 투자할 수 있길 바란다. 투자한만큼 성취도 돌아올 것을 확신한다. @
참고자료
① 팜팜테크 사이트
② Embedded Linux인 Qplus-P 관련 정보
③ Korea Embedded Linux Project
* 이 기사는 ZDNet Korea의 자매지인 마이크로소프트웨어에 게재된 내용입니다.
지금 뜨는 기사
이시각 헤드라인
ZDNet Power Center










