꽃미남 프로그래머 김포프가 창립한 탑 프로그래머 양성 교육 기관 POCU 아카데미 오픈!
절찬리에 수강생 모집 중!
프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 알 수 없는 사용자


최초로 만들어진 전자 게임 ‘퐁(PONG)’ (그 이전에 오실로스코프 버전이 최초라고 하지만 상업적 성공을 거둔 게임이 아니니까 퐁이 최초라고 치자) 과연 퐁을 만들 때부터 게임의 품질관리는 시작됐을까?
 
그건 모르는 일이다. 아마도 퐁을 만든 놀런 부쉬넬만 알지도 모른다. 하지만 품질관리를 하기에 퐁은 너무나 단순한 게임인것 같다.
 
그렇다고 게임 품질관리의 역사가 ATARI2600 같은 최초의 가정용 게임기부터 시작하지는 않는다.
 
오히려 게임 품질관리가 대두된것에는 ATARI를 원인으로 꼽을 수 있을 것 같다.
 
1982년 미국에서는 아타리 쇼크 사건이 벌어졌다.

아타리 쇼크 사건의 개요는 이렇다.

당시 ATARI2600의 성공으로 비디오 게임 시장이 커지자 여기저기서 생기기 시작한 다른 콘솔 개발회사들을 견제하기 위해 아타리는 게임 소프트 물량으로 밀어 붙이는 전략을 내보였다. 게임 퀄리티를 무시한 이런 처사는 당시 비디오 게임 시장과 맞물려 많은 개발사들이 ATARI2600용 게임을 내놓았으나 대부분이 쓰레기와 같은 수준의 게임들이었고 게임 퀄리티에 대한 불신은 곧 구매자들의 구매 욕구 감소로 이어졌다. 그리고 그 최후는 스티븐 스필버그 감독의 영화 ‘E.T’의 게임 패키지에서 폭발했다. 성공한 영화 E.T의 게임화를 위해 다른 경쟁사와의 경쟁에서도 이기기 위해 비싼 라이센스를 지급 그리고 크리스마스 시즌을 노린 5주간의 짧은 제작기간, 아무런 퀄리티에 대한 보장이 없음에도 불구하고 대량으로 만들어낸 패키지는 결국 구매자들도 외면해 대부분이 반품 내지 제작비를 못 뽑아낼 정도의 헐값으로만 팔려나갔다.

재미있는 일화로 아타리는 반품된 E.T 게임 패키지를 사막에 파묻었다고 한다.


(사막에 묻은 E.T 게임을 찾아나선 사람들의 영상을 볼수 있다. -_-;;;)


위 사건으로 미국의 게임 시장은 30억의 가치를 가진 시장에서 1억으로 한번에 붕괴되었다고 한다.

아타리 쇼크로 인해 미국에서 게임을 개발하던 회사들은 전부 관련 부서를 매각하거나 없앴다고 한다.  그렇게 시작된 암흑기는 닌텐도에서 패미컴(NES)이 나올 때까지 지속되었다.

1985년 일본의 닌텐도는 패미컴을 NES란 이름으로 바꾸어 ‘뽀빠이’, ‘동킹콩’과 함께 미국에 발매했다.

아무래도 닌텐도야 말로 게임 QA의 시초라고 할 수 있을 것 같다.

아타리 쇼크를 교훈 삼아 닌텐도가 행한 것은 서드 파티의 개념 확립과 철저한 라이센스 관리였다.

닌텐도에는 그 당시부터 품질관리 부서를 만들어 저질의 게임에는 라이센스를 발급하지 않아 발매를 하지 못하게 하였다.

게임의 퀄리티가 하드웨어의 판매를 정한다는 법칙을 당시 라이벌 회사가 없음에도 불구하고 닌텐도는 알고 있었던 것이다.

그 뒤 가정용 게임기의 역사가 진행되면서 지금은 닌텐도, SONY, MS라는 3대 회사가 자사의 게임기들을 가지고 경쟁하고 있다.

이 세 회사는 모두 각자의 품질 관리를 위한 checklist를 가지고 있다.

MS는 TCR(Technical Certificatotion Requirements), SONY는 TRC(Technical Requirements Checklist), 닌텐도는 Lot check 라는 checklist를 가지고 있다.

물론 위의 것들은 모두 자사의 Hardware에서 게임 구동을 위한 최소 확인 조건 문서이다.

그들의 콘솔로 게임을 발매하기 위해서 개발사는 저 checklist들을 패스해야 한다. checklist는 단순히 콘솔에서 발생하는 문제점을 잡기 위한 항목 뿐만이 아니라 이용자들을 위한 UX 관점의 항목도 있다고 한다. 예를 들면 PS3의 컨트롤러에서 O는 무조건 확인 X는 무조건 취소 명령을 내린다던가 XBOX에서는 녹색 버튼이 확인, 빨간색 버튼이 취소와 같은 식으로 말이다.

MS의 TCR은 XBOX 시절까지만도 500개에 가까운 문항들(이게 최소 조건이다.)이 있었으며 그 조건이 너무 까다롭기도 해 XBOX360으로 넘어온 뒤에는 항목을 300개 가량으로 줄이기도 했다고 한다.

현재까지 발매되고 있는 콘솔 게임들의 발매량이 그렇게 많음에도 최악이라 부를 정도의 퀄리티를 가진 게임이 그다지 많지 않은 이유는 위 회사들이 모두 철저한 품질관리를 하고 있기 때문이라 봐도 좋을 것이다.


p.s 왠만하면 새 글을 작성해서 올릴려고 했는데 요새 회사가 크런치 기간이라 시간이 없네요(....)
예전 글을 우선 올려봅니다. 현재 작성하고 있는 글은 게임 회사 QA는 무슨 일을 하나에 대한 것입니다.
완성하는대로 올릴 수 있도록 하겠습니다. :) 

반응형
,
Posted by 알 수 없는 사용자
* 본문에는 경어가 사용되지 않습니다. 그러니, 문어체에 알레르기가 있는 분은 일단 돌을 던지고 나서 읽기 시작 하소서 *

서비스를 수행하지 못하도록 하는 목적(DDoS)이 아니라 데이터 수정, 사용권한 획득 등의 어떠한 형태의 이득을 얻으려 하는 공격자들에 대해 이야기 해보겠다.

C/S 환경에서 해킹 공격의 대상이 되는 부분은 당연하지만 세군데 이다. 클라이언트, 서버, 그리고 네트워크 이다. 서버의 경우에는 기계도 회사에 있고, 관리도 회사에서 하기 때문에 C/S환경에서는 앞서 말한 방식의 공격을 당하기가 쉽지 않다. 서버가 공격 당해서 서버에 있는 게임의 데이터가 조작되고, 권한이 변경되어 특정인에게 이득이 갈 수 있는 작업을 할 수 있을만한 환경이라면, 그 회사는 언제 무너져도 이상하지 않은 상태라 말할 수 있겠다. 우좌지당간에, 그래서, 서버가 공격 당하는 경우는 일단 배제하고 이야기 해보겠다.

** 클라이언트
클라이언트는 공격자가 소유한 컴퓨터에 설치되기 마련 이므로 가장 쉽게 공격 당할 수 있는 부분 이기도 하다. 클라이언트에서 저질러 질 수 있는 공격의 방법은 수백~수천가지가 되겠지만 그걸 분류 하면 대충 다음과 같은 세 가지 타입 정도로 나눌 수 있을 것 이다.

1. 바이너리 코드 혹은 저장된 데이터 파일의 확인 / 수정
공격자의 컴퓨터에 설치되어 있기에 바이너리 코드를 까서 리버스 엔지니어링 툴로 돌리면 기본적인 데이터들은 줄줄줄 흘러나오기 마련이다. 아무리 데이터를 암호화 해서 저장하고, 보안 툴로 도배를 해도 결국에는 까발려진다. 정교하고 복잡한 방법을 사용하면 까발려지기 까지의 시간을 벌 수 있을지는 모르겠지만, 모든 필요한 정보는 공격자가 가지고 있기 때문에 언젠가는 까발려진다. 믿어라.

2. 후킹 & 메모리 내용 확인 / 수정
공격자는 컴퓨터에서 실행되는 모든 프로그램의 정보를 읽을 수 있다. 모두들 잘 알고 있듯이 메모리에 올려져서 실행중인 모든 프로그램은 머리 가슴 배로 이루어져 있고, 머리에는 실행 코드와 스태틱 데이터가, 가슴에는 힙이 그리고 배에는 스택이 있다. 그리고 이 모든 것은 메모리에 들어 있으니 언제든지 확인 할 수 있다. 할당 했던 메모리를 반납 한다고 데이터가 사라지는 게 아니다. 메모리를 반납하고 가베지 컬렉션이 끝났다고 해서 조금전에 아이디와 패스워드를 암호화하기 위해 사용했던 키가 사라지는 건 아니다. 반납되어 메모리 풀에 포함된, 현재 사용하지 않는 메모리에 있던 정보들도 여전히 남아있고, 공격자는 볼 수 있다. 보안 프로그램을 덕지덕지 발라도 시간을 투자하면 결국에는 볼 수 있게 된다. 게다가 보안 프로그램과 해킹 프로그램은 종이 한장 차이다. 그러므로, 내 프로그램이 알고 있는 모든 것은 공격자도 안다. 믿어라.

참고자료: 후킹중인 후커들, 그녀들은 마누라에게 가야할 남자들을 후킹해서 마누라에게 가지 못하게 한다.
API에게 가야할 내 클라이언트를 가로채서 딴짓을 하게 만드는 컴퓨터의 후커와 다를 바 없다.


3. 사기, 공갈, 협박 (응?)
이건 또 뭔 쉰소리냐 라는 생각이 절로 들만한 타이틀 이긴 하지만, 가장 오래되고 가장 확실하고 가장 쉬운 해킹 방법이기도 하다. 요즘 유행(?)하고 있는 피싱도 이 분야에 해당된다. 가장 쉽게 써먹을 수 있는 기술은 '"레벨 99 보안구역에서 근무하는 근무자 인데, 급하게 나오느라 출입증을 자리에 놓고 나왔는데 잠시 문좀 열어주면 안될까요?"라고 구라를 떨어서 보안 근무자를 속인다', '머리에 총을 대고 "당장 문을 열지 않으면 머리에 바람 구멍을 내주겠다"라고 외친다', 그리고 '출입 가능자의 눈깔을 뽑고 손목아지를 잘라서 보안장치에 올려 놓는다' 등이 있다.

이건 막을 방법이 없다. 끊임없이 근무자들을 '첨보는 놈이 말걸면 그냥 쏴죽여라'고 세뇌하고 CCTV에 연동된 발칸포와 CCTV 한 대당 세 사람의 근무자를 배치한 완전 무결한 보안 시스템을 갖춰... 도 못 막는다. 그냥 노력 했다는 것과 미션 임파서블의 탐크루즈 레벨의 잘난 놈이 아니면 쉽게 뚫지는 못한다 정도에 만족해야 한다. 이런 시스템도 두 달정도 배달 아르바이트로 신분을 위장한 멍청한 스파이에게 어이없이 뚫리기도 한다.

이렇게 잘난놈을 어찌 막는단 말이냐!

** 네트워크
1. 스니핑, 스푸핑
스니핑과 스푸핑은 각각 '훔쳐 보다'와 '통신내용 위조'에 해당된다. 스니핑과 스푸핑 자체는 공격 방식으로서의 파괴력을 갖는다기 보다는 2번과 3번의 공격을 성립하게 만드는 도구라고 봐도 된다. 물론, 이 두 공격은 권투로 보면 잽에 해당되는 것으로 다른 공격의 기본일 뿐 아니라 자체로도 상당한 파괴력을 갖는다. 두 공격 방법은 네트워크 장비에 따라 다른 방식을 사용하게 되는데, 일반적인 허브(HUB)를 사용하는 경우에는 별다른 조작 없이도 동일한 네트워크에 돌아다니는 정보를 모두 처리할 수 있으며, 스위칭 장비를 사용하는 경우에는 ARP 스푸핑 이라는 방법을 사용한다.

ㄱ. 스니핑
스니핑은 한마디로 이야기 하자면 도청에 해당된다. 보통 자신이 포함된 네트워크에 흘러다니는 데이터를 도청하게 된다. 웹 통신에 사용되는 HTTP 는 입력된 정보가 텍스트 상태로 돌아 다니게 되므로, 스니핑을 이용하면 사용자가 입력한 정보를 하나도 빠짐없이 깔끔하게 빼낼 수 가 있다. 그러므로 최소한 HTTPS 를 사용하는 사이트의 패스워드와 HTTP 를 사용하는 사이트의 패스워드는 다른 걸 사용 하는걸 권한다. HTTP 를 사용하는 사이트의 패스워드는 내 것이 아니다. 인터넷 회선 회사에서 제공하는 보호책이 전혀 없다면 옆집이랑 우리집이 같은 인터넷 회사 서비스를 사용하는 경우, 옆집에 사는 해커놈이 자기집 컴퓨터로 내 컴퓨터에서 입력되는 정보를 빼내는 것도 가능하다. 그것도, 숨쉬는 것 만큼 편안하게 빼갈 수 있다. (인터넷 회선 회사에서 나를 위해 돈쳐들여 보호책을 마련해 줄리는 없잖아? 그러니까 아마 우린 안될거야)

열심히 스니핑 중이신 바리스타 아자씨


ㄴ. 스푸핑
스푸핑은 한마디로 이야기 하자면 가짜정보 혹은 문서 위조에 해당된다. 가짜 정보는 일반적인 데이터에 대한 정보의 조작 일 수 도 있고, 네트워크를 관리하는 장비를 혼란시키기 위한 정보의 조작 일 수 도 있다. 해커들이 가장 많이 사용하는 공격 방식은 ARP 스푸핑과 DNS 스푸핑이 있는데, 둘 다 희생자로 하여금 공격자가 정상적인 통신 대상인 것으로 착각 하게 만드는게 주 목적이다.

ㄷ. 스니핑 / 스푸핑 공격의 원리
스니핑/스푸핑 공격이 가능한 이유는, TCP/IP 프로토콜 자체가 보안에 대한 고려가 전혀 없기 때문이다. TCP/IP를 통해 전달되는 모든 정보는 그냥 눈에 보이는 그대로 주고받는다. 그렇기 때문에 상황에 따라서는 아주 단순한 방법으로 통신내용을 엿보고 조작 할 수 있다.

요즘은 대부분의 네트워크에서 스위칭 장비를 사용하기 때문에 허브를 사용하던 시절만큼 간단하게 내 정보를 뽑아 가는 짓은 할 수 가 없다. 그러나 여전히 그다지 많이 어렵지는 않다.

a. 허브를 사용하는 네트워크의 경우엔
그 어떤 공격 기술 없이 단순히 네트워크 트래픽을 확인하는 정상적인 툴 만으로도 스니핑이 가능하다. 이러한 공격이 가능한 이유는
 
. TCP/IP가 통신을 수행할 때 텍스트를 그대로 전송하는 방식을 사용하고
. TCP/IP의 하단에서 사용되는 이더넷(Ethernet) 프로토콜이 CSMA/CD 라는 방식을 사용하기 때문이다.
 
CSMA/CD 방식을 간단하게 설명하자면 '일단 동네사람 다 듣게 소리질러 놓고 못 알아 들었는지 확인하는' 방식이다. CSMA/CD 방식에서는 컴퓨터 A에서 B로 데이터를 전송하고자 하는 경우, 컴퓨터 A는 네트워크를 다른 컴퓨터가 사용하는지를 확인 한 다음에 네트워크에 정보를 그냥 뿌린다. 네트워크에 연결되어 있는 컴퓨터들이 네트워크에 뿌려진  정보를 받아서 정보에 기록된 받는 측 IP주소 가 자신의 것 이면 받아서 처리하고, 아니면 그냥 버리는 방식이다.

텍스트로 데이터가 전송되고, 모든 컴퓨터가 데이터를 일단 받은 다음에 자기 것이면 쓰고 아니면 버리는 방식이기 때문에 IP 단의 프로그램을 작성해서 자신의 IP든 아니든 상관없이 그냥 다 모으도록 해주면 된다. (프로그램을 짜는게 귀찮다면, 네트워크 관리자라면 한번쯤은 써 봤을 만한, 아주 대중적인 툴 중에 같은 네트워크에 돌아다니는 모든 정보를 모아서 필터링해 보여주는 tcpdump 라는 놈도 있다.) 그러면 그냥 스니핑 성공~. 만약 공격대상이 통신하는 내용을 조작하는 공격인 스푸핑을 하려고 하는 경우에는 ARP 스푸핑 혹은 ARP Redirect라는 방식을 사용해 주어야 한다. 그건 b. 에서 설명 하겠다.

b. 스위칭 장비를 사용하는 경우
약간, 아주 약간 복잡해 지는데, 스위칭 장비는 받는 측 네트워크 카드의 주소(MAC)를 확인해서 해당 MAC에 해당하는 컴퓨터가 연결된 회선으로만 데이터를 쏴주기 때문에 위에서 언급한 허브를 사용하는 네트워크에서 하듯이 숨쉬듯 스니핑이나 스푸핑이 가능하지는 않는다. 그러나 손가락 끝을 조금 움직여 주는 정도의 노력만 기울이면 문제가 해결된다.

먼저, 어떻게 사용자가 IP 를 이용해 통신을 시도해도 통신이 되는지를 알아보자. IP 레이어에서 사용되는 자료 구조중 ARP 테이블 이라는 것이 있다. 이놈이 논리적 주소인 IP와 물리 주소인 MAC을 연결해주는 테이블 되시겠다. 이 테이블의 역할은 특정 IP 주소로 전달을 요구 받았을 때 그 데이터가 어느 기계로 전달 되어야 하는지를 알려주는 역할을 한다. 도메인 네임 -(DNS)-> IP 주소 -(ARP)-> MAC 이라고 생각 하면 오케이!


ARP의 동작방식

(1) 통신 상대의 IP 주소에 해당되는 MAC이 자신의 ARP 테이블에 있는지 확인한다.
(2) ARP 테이블에 해당 IP가 없다면, 네트워크에 있는 단말 들에게 ARP Request를 전송하여 지정한 IP를 사용하는 단말기의 IP를 요구 한다.
(3) 지정 IP를 쓰는 단말기는 자신의 MAC 주소를 ARP Reply 에 담아서 보내준다.
(4) 둘은 쎄쎄쎄(Three-way handshaking) 하고 통신한다
 
공격이 가능한 기본적인 이유는, 이 ARP가 네트워크를 통해 전달되는 정보를 기본으로 만들어지기 때문 이다. 다시 말해서 공격자가 공격 대상 에게, ARP Reply 패킷에 가짜 정보로를 담아서 '내가 게이트웨이야'라고 주기적으로 주장해 대면 공격 대상은 공격자의 장비를 게이트웨이로 인식하고, 모든 패킷을 공격자에게 보내게 된다. 마찬가지로 게이트웨이 장비를 속여주면 공격자는 피 공격자가 보내고 받는 모든 데이터를 제 마음데로 변조할 수 있게 된다.

추가적으로 스위칭 장비를 무력화 하기 위해서 사용되는 기법중에 'Switch Jamming'이라는 기법이 있는데, 대부분의 스위칭 장비가 안전 보다는 효율을 우선으로 하고 있어, ARP 해석에 문제가 발생하면 트래픽을 전달하기 위해 a. 에서 언급한 더미 허브처럼 동작하게 된다는 점을 이용하는 공격 기법 이라고 할 수 있다.

Note. 이런류의 찝적거림을 막기 위해 공유기가 꼭 필요하지 않은 경우라 해도 공유기를 쓰고, 공유기의 공인 IP에 해당되는 게이트웨이의 MAC을 고정시켜 사용한다. 실제로, 옆집이 우리집이랑 같은 인터넷 회사의 회선을 쓰면, 옆집에선 별 노력 없이 내가 인터넷을 통해 보내고 받는 모든 정보를 제 마음대로 조작할 가능성이 있는데, 일반적으로 옆집과 우리집이 같은 IP 대를 쓰고, 공통의 게이트웨이를 쓸 확률이 아주 높고, 인터넷 회선을 제공하는 회사에서 일반 가정집에 들어가는 회선에 보안 장비를 넣을 이유는 별로 없기 때문이다.

2. Replay
Replay 공격은 말 그대로 '재전송' 공격이다. 예를 들어 아이디와 패스워드를 암호화 해서 보내는 C/S 환경이 있다고 하자. 현실에 존재하지 않는, 절대로 깰 수 없는 암호화 방식을 사용해서 아이디와 패스워드를 암호화 해서 보낸다 해도. 전달되는 암호화된 ID와 패스워드를 스니핑을 이용해 저장해 두었다가, 공격 하고 싶을때 단순히 보관되어 있는 암호화된 ID와 패스워드를 전송만 해줘도 로그인이 된다. 실제 ID가 뭔지, 패스워드가 뭔지 알 필요도 없다.

3. Man In The Middle Attack (MITM)
통신하는 두 당사자 사이에 끼어서 데이터를 중계 함으로서 수행하는 공격을 말하며, SSL 같은 공개키 방식의 암호화 통신을 공격하기 위해 사용된다. A와 B가 통신하는 경우, 공격자 M이 MITM 공격을 하는 방법은 기본적으로 다음과 같다:
 
0. ARP 스푸핑을 이용해 통신하는 두 당사자 A와 B를 속인 후 A가 보내는 데이터를 M이 받아서 B에게 전달하면 끝! (응? 그냥 스푸핑 이잖아?)
 
자자, 흥분을 가라 앉히고, 좀 더 들어 보라. MITM의 기본 전제인 공개키 방식의 통신을 위의 설명에 끼워 넣어 풀면 된다.
 
ㄱ. A가 B에게 자신의 공개키를 전송한다.
ㄴ. M은 ㄱ에서 전달된 A의 공개키를 가로채 저장하고, 자신의 공개키를 B에게 넘겨준다.
ㄷ. B는 A의 것 이라 믿어지는 공개키를 받고, 자신의 공개키를 A에게 보낸다.
ㄹ. M은 ㄷ에서 전달된 B의 공개키를 개로채 저장하고, 자신의 공개키를 A에게 넘겨준다.
ㅁ. 공개키 방식의 강력하고 안전한 보안 통신이라고 믿는 A와 B의 통신을 유유히 가지고 논다.
 
실제로 MITM은 SSL 통신에도 통하는 경우가 있다. ' 미리 브라우저 등의 클라이언트에 임베드 되어있는 잘 알려져 있는 기관의 인증서를 사용하는 것이 아닌' SSL 통신은 MITM 공격에 의해 뚫린다.


MITM 공격 결과, 뭐 글자를 지우고 스푸핑 공격 결과라 우겨도 된다

다음 번 부터는 이러한 공격들에 대해 그나마 저항력을 가질 수 있는 방법들에 대해 설명해 보도록 하겠다. 이 팀 블로그에 오는 대부분의 사람들은 '보안' 자체에 관심이 있다기 보다는 '어떻게 하면 해킹하는 찌질이들에게 좀 덜 시달려 볼까' 혹은 '혹시 잘하면 봇을 막을 수 있지 않을까' 쪽에 관심을 가지고 있을 터이니, 공격 방법이나 회피 방법에 대한 설명 보다는 해킹 공격에 저항력 있는 코드를 만드는 방법들에 중점을 두고 쓰도록 노력해 보겠다.
 
*   *   *

사실, 보안과 게임은 뗄래야 뗄 수 없는 관계에 있긴 하지만, 그렇다고 게임업계에서 보안 자체에 관심을 가지고 있는 경우가 그닥 많지는 않지요. 그래서 치명적인 실수가 될 수 도 있는 부분에 한해서 두세번 정도 특별기고(?) 형태로 매번 얻어 먹는 귀중한 지식에 대한 앙갚음(!)이라도 할 까 해서 포프님에게 제안을 했습니다. 그런데 덜컥 날자를 할당해 주시는 바람에 게임 프로그래머들에게는 재미 없을 확률이 아주 높은 보안과 관련된 글을 주기적으로 쓰게 되었습니다.

글은 가능한 한 공격 방법 - 해결책 쌍을 제시해 보도록 하겠습니다. 뭐, 나의 주 관심사는 '안전한 통신 프로토콜'에 쏠려 있기 때문에 그 외의 영역은 쬐끔 분량이 적을지도 모르겠습니다. 그래도 주 연구 분야가 '연산 능력이 부족한 가벼운 장비들 간의 보안통신' 이기 때문에 많은 패킷을 빠르게 주고 받아야 하는 게임 서버/클라이언트 간에 보안 통신을 하는 방법에 대해 조금은 도움이 되지 않을까 하고 자위해 봅니다. ㅡ,..ㅡa
반응형
,
Posted by 밥을먹는선비


0. 그냥 일단 변명부터 ㅜ.ㅜ;

안녕하세요 마감일을 지키려했지만 결국 실패한듯하네요. 원래는 21일날 올리려한 글이지만 6일로 미뤄서 오픈합니다.
작년 12월23일부터 4주간 매일 8시간 html5 수업을 강행군을 했더니 몸과 마음이 모두 지친거같네요 ㅜ.ㅜ; 

이번 시간에는 화면에 간단한 도형을 띄워보는 예제를 다뤄가면서 일리히트의 기본 랜더링 파이프라인 대해서 알아보겠습니다.

1. 디바이스 생성하기

일단 일리히트엔진의 시동을 걸기위해서 다음과 같이 한줄의 코드가 필요합니다.

    irr::IrrlichtDevice *pDevice = irr::createDevice(irr::video::EDT_OPENGL);


방금 여러분은 오픈지엘 랜더러를 사용하는 디바이스(게임기 비스므리?)를 생성한것입니다.
자~ 그럼 일단 시동을 걸어야하는데 일단 연료를 주입할 먼가가있어야 하겟죠?
연료 주입구라고 할수 있는 비디오드라이버 객체를 얻는것입니다. 

irr::video::IVideoDriver *pVideo = pDevice->getVideoDriver();

pVideo 이것이 바로 연료 주입구 입니다.

게임엔진을 차에 비유해서 굳이 억지로 설명하자면 일단 엔진을 돌리기위해선 연료가 필요한데 그게 바로 그래픽 데이터들입니다. 엔진을 그것을 먹고 결과를 출력하죠 자동차엔진이 화석연료를 태워 스피드라는 결과 물을 출력하듯이요.

여기서 우리의 약간의 딜래마가 있습니다. 엔진의 성능이라는 이슈인데요.

좀허접한 엔진에 최고급 항공유를 넣은것과 완전 최고급엔진에 허접한 유사 휘발유를 쓰는 것인데요.

성능이 좋은 엔진이라면 유사휘발유를 먹고도 아주 좋은 스피드를 내길 바래야겟죠. ^^?
머 아님말구요.

그러나 현실은 좀 엔진이 허접하더라도 연료가 우수(폭팔성강한)하면 결과가 거의 무조건 일반인들(스피드라는 것..)이 보기엔 만족 스럽다는겁니다.(이건 자동차 애기입니다. 게임엔진은 알아서 생각하시고요^^) 물론 나중에 항공유의 폭발성을 견디지못하고 엔진이 터지고말겠지만 머 당장은 그럴듯하죠.

그리고 또 어떤게 성능일것이냐 하는 문제도 있습니다. 즉 얼마나 폭발성 강한 연료를 잘소비하느냐에 관점을 둔 엔진이 있겠고 얼마나 연료를 아껴가며 연비를 최대한 높이려는 관점의 엔진이있을 수 있습니다. 
게임엔진도 비슷합니다. 상용엔진은 전자의 경우겠고 일리히트엔진처럼 오픈소스 공개엔진의 경우엔 후자에 좀 가깝습니다. 전자에 가까운 공개엔진도있고 후자에 가까운 사용엔진도 물론있습니다. 그냥 그런 경향이 있다는 것이라 생각하시면 될듯합니다.

암튼 이야기가 잠시 삼천포로 갔었는데요 일단은 pVideo를 통해서 엔진에 에너지를 주는거라고 생각하시면 됩니다.


2. 버텍스 데이터 만들기

일리히트엔진은 자체적으로 컨테이너(array,map,list)를 가지고 있습니다. STL과 거의 유사한 사용법을 가지고있으므로 stl을 평소에 사용하시는 분들이라면 쉽게 사용하실수 있습니다.

irr::core::array<irr::video::S3DVertex> Vertices;

위와같이 버텍스 배열을 선언해줍니다. 사용법은 std::vector와 거의 같습니다.

 1---------2

 |              |

 0---------3


이런식의 도형을 그려 보도록 하겠습니다.


일리히트엔진은 버택스포멧이 기본적으로 3종류가 있습니다. 그중에서 가장 기본이 되는 것이 S3DVertex 입니다.
여기서는 이것을 사용했습니다.

정점위치,법선,컬러,텍스춰 좌표 등을 가지고 있는 포멧입니다.

형식은 다음과 같습니다.

irr
::video::S3DVertex(
                                 정점X죄표,정점Y
죄표,정점Z좌표,
                                 법선X죄표,법선Y죄표,법선Z좌표,
                                 정점컬러,
                                 텍스춰 U,텍스춰 V);

다른 두가지포멧과 이것을 확장하는 법은 다음에 다루도록 하겠습니다. 

그 다음으로 인덱스 정보를 만듭니다.


 
위와 같이 삼각형 두개를 조합해서 사각형을 만들어 보았습니다.


자 이렇게 해서 일단 기본 도형을 그리는 데필요한 정점(
Vertices)과 인덱스(Indice4TriList) 데이터를 만들어 보았습니다. 


3. 변환 다루기

변환은 일반적으로 월드,뷰,투영 변환 이렇게 3가지로 나누어집니다. 변환에 대한 자세한 내용은 김용준 교수님이 쓰신 명저 해골책을 참고 하시면됩니다. 
일리히트엔진에서 변환을 다루는 함수는 irr::video::IVideoDriver의 
setTransformsetTransform 입니다.
이 함수는 변환의 종류와 변환이 들어있는 행렬을 매개 변수로 받아서 해당 변환을 파이프라인에서 적용하도록 처리를 해줍니다.

irr::video::ETS_VIEW
irr::video::ETS_PROJECTION
irr::video::ETS_WORLD 

첫번째 인자로는 이와 같이 3개의 변환을 선택해서 넣어줄수있습니다.

두번째 인자에 변환의 내용이 담겨있는 행렬을 넘겨줍니다.

이제 행렬을 만들어서 넘겨줘야하는데요.
행렬객체를 직접 초기화한다는건 매우 귀찬은 일중에 하나겠죠?
그래서...
일리히트엔진은 다이랙스엑스에 있는 행렬만들기 함수와 같은 행렬생성 유틸리티 함수들을 가지고 있습니다.

먼저 투영행렬을 만들어 파이프라인에 등록하는 것을 해봅시다.


buildProjectionMatrixPerspectiveFovLH 함수는 왼손좌표계 기반의 원근투영 행렬을 만들어 주는 함수입니다.

첫번째 인자인 fov는 시야각입니다.  값이 하나 이므로 가로 세로 시야각을 따로 계산한 피라미드형이 아니라 원뿔형의 시야각을 생각하시면됩니다.

두번째 인자인 ratio 는 화면의 종횡 비율입니다. 정비율을 만들고 싶다면 현재 화면해상도의 넓이/높이 값을 넣어주면됩니다.

마지막 두개의 인자는 절두체 범위의 원근값입니다. 1은 가장 가까운 거리이고 3000은 절두체의 최대끝 범위입니다. 이 이상거이에 있는 물체는 잘려서 않보이게 됩니다.


그 다음은 뷰변환 들어갑니다.

일명 카메라 변환 입니다.

buildCameraLookAtMatrixLH 함수로 왼손좌표계 기반의 뷰변환 행렬이 만들어 집니다.
눈치 체셨겠지만  LH는 토지 주택공사의 약자가 아니라 왼손의 약자입니다.

첫번째 인자는 카메라의 위치 입니다.

두번째 인자는 바라보는 시점의 위치입니다.
방향이 아닙니다. 
시야의 방향벡터를 구하려면 두번째에서 첫번째를 빼주시면됩니다.

마지막은 상방벡터입니다.

마지막으로 도형을 그리기 전에 최종적으로 도형의 위치를 정하는 월드 변환입니다.

왜 마지막에 월드변환인가 하면 랜더링 루프내에서 대부분 투영변환과 카메라 변환은 월드 변환에 비해서 빈번하게 바뀌지 않습니다.
그래서 코드 순서는 그리기 직전에 월드 변환을 하는것이 일반적인 순서입니다.



월드 변환은 이동,회전,크기 변환을 조합하여 만들수있습니다.
위예제에서는 단순히 원점에 위치시키는 변환아닌 변환이 되었습니다. 

setTranslation 에서 인자로 받는 벡터클래스는 3차원 위치를 나타낼때 빈번하게 사용됩니다.

irr::core::vector3df(x,y,z)

이렇게 해서 변환을 위한 준비는 모두 마쳤습니다.
 

4. 재질 다루기

3D하면 또 하나 중요한것이 재질입니다. 지난 20세기가 폴리건의 시대였다면 21세기는 재질과 물리 레이트래이싱 머 그런 등등의 시대일것입니다.


일리히트엔진은 SMertial 구조체로 재질에 대한 모든것을 다 처리합니다. 이 안에 쉐이더라든지 텍스춰등의 모든 정보가 들어 있습니다.

특별히 값을 지정하지않아도 선언과 동시에 초기값들이 지정이됩니다.
일단 조명은 나중에 사용할것이므로 조명속성을 OFF 시켜둡니다.

그리고

텍스춰를 지정합니다. 일리히트엔진은 기본적으로 텍스춰 4개를 동시에 조합할수있습니다.
더 필요하다면 TextureLayer 의 배열수를 늘려주고 엔진을 다시 빌드해주면됩니다.

일단 1개를 기본으로 사용하므로 첫번째 레이어에 텍스춰를 로드해줍니다.

비디오드라이버의 
getTexture함수는 텍스춰 파일이름으로 텍스춰정보를 관리합니다. 만약 이미로딩이 되어있다면 중복하여 로딩하지않고 이미 로딩된 데이터를 map구조로된 컨테이너에서 찾아 반환합니다.

setMaterial 함수로 재질을 등록 해줍니다. 그러면 다른재질로 이함수를 호출하기전까지 이 재질의 속성이 그대로 유지됩니다.


5. 프리미티브 그리기 함수 사용하기

모든게 준비 되었고 이제는 그리는 것만 남았습니다.




 첫번째 인자는 정점 버퍼의 포인터 입니다.
 (irr::video::S3DVertex *) (Vertices.pointer())  를 사용해도 같은 결과를 얻을수 있습니다.

두번째 인자는 정점갯수입니다.

세번째 인자는 인덱스버퍼의 포인터입니다.
네번째 인자는 인덱스의 갯수입니다.

다섯번째 인자는 정점형식입니다.
여섯번째 인자는 정점을 이어주는 방식입니다.


위와 같은 종류 들이 있습니다.


이번에는 여기까지 하도록 하겠습니다.

소스 파일 첨부합니다. 조만간 구글 코드 같은곳에 SVN을 하나 열어두겠습니다.





 
반응형
,
Posted by ozlael

게임 개발을 하기 위해 필요한 것

 " 게임 개발 어떻게 하나요? "

게임 개발에 관심을 보이기 시작하면 으레 이러한 질문을 많이 물어보게 되지요. 게임 시장이 IT 버블을 이겨내고 발전함에 따라 게임 개발에 관심을 보이는 학생들 역시 점점 많아지고 있는 것이지요.그런 만큼 게임 개발 방법에 대한 질문과 대답 글 또한 인터넷에 많이 존재합니다.

구글에서 "게임 만드는 방법" 검색 결과


이러한 질문에 대한 답은 대부분 비슷합니다. 공부를 열심히 하고 많이 배우는 것이죠. 일단 기본적으로는 전반적인 게임 기획 이론을 알아야 할테고 게임에 대한 철학 및 재미 요인을 분석할 줄 알아야겠지요. 그리고 각 파트에 맞는 전공 지식이 많이 필요할 것입니다. 프로그래머라면 C/C++이나 JAVA 등 객체지향 언어는 공통적으로 알아야 할테고, 클라이언트 프로그래머라면 Windows API와 DirectX 그리고 각종 스크립트 언어 등을 알아야 하지요. 서버 프로그래머라면 Linux OS, DB, Query 등을 알아야 하지요. 경우에 따라서는 Action Script, , Objective-C 등을 배워야 할 수도 있습니다. 다른 패러다임의 언어들을 알아두면 금상첨화겠지요. 이처럼 게임을 개발하기 위해서는 많이 배우고 많이 공부하여 실력을 키워야 하는 것은 더할 나위 없이 당연한 소리입니다.

알콜코더님의 KGC2011 강연 내용 중



불여락지자(不如樂之者)

하지만 저는 거기에 하나 첨언을 하고자 합니다. 어찌보면 공부보다 더 중요한 것이지요.
 

 " 지지자(知之者)는 불여호지자(不如好之者)요 호지자(好之者)는 불여락지자(不如樂之者)라 "

어떠한 일에 대하여 지식이 있는 사람은 좋아하는 사람을 이기지 못하고, 좋아하는 사람은 즐기는 사람을 이기지 못한다는 뜻입니다. 제 좌우명이기도 하지요.
 게임을 만든다는 것은 정말 즐거운 일입니다. 대부분의 게임 개발자들은 그 이유로 이 산업에 뛰어들어 개발을 하고 있지요. 게임 개발을 꿈꾸는 사람이라면 게임을 간단한거라도 만들어보면서 그 즐거움을 느끼길 바랍니다. 복잡하게 DirectX 3D 게임이 아니라도 좋습니다. UDK로 거창하게 만든 것이 아니라도 좋습니다. 간단한 유즈맵이라도 좋고 RPG 쯔끄루로 만들어도 좋습니다. 게임 제작이라는 즐거움을 절실히 느끼길 바랍니다. 저 역시 초등학교때 베이직으로 가위바위보 게임을 만들면서 시작을 했지요.
 작게 혹은 크게 게임 제작의 즐거움을 느끼길 바랍니다. 재미를 붙이게 되면 더 제대로된 게임을 만들고 싶은 욕심이 생기고 배움의 가속도가 저절로 붙게 되지요. 앞서 언급된 여러가지를 공부할 수 있는 것도 그 덕분이지요.


국내 게임 산업의 현실

제가 게임 개발의 재미를 강조하고 있습니다만, 그 반대로 재미를 느끼지 못한다면 단념하시길 권장합니다. 국내 게임 산업은 아직은 이러한 즐거움이 없이 뛰어들기에는 힘든 곳입니다.
 국내 게임 산업은 90년대 들어 수 많은 젊은이들이 게임 개발에 뛰어들어 청춘을 바치기 시작하면서 성장하게 되었습니다. 많은 젊은이들이 청춘을 바치고 건강도 못챙겨가면서 산업을 키워놨지만, 그 젊은이들 중 아직까지 남아있는 사람들은 몇 되지 않습니다. 산업에 뛰어든 젊은이가 안정적으로 근무하다 훗날 정년 퇴임을 하는 주기를 돌아야 산업도 안정적이 될 수 있습니다. 대마왕J님은 이러한 싸이클을 강조하며 산업이 자리를 잡는 싸이클이 도는 것을 직접 보여주고 싶다고도 하셨지요. 국내 게임 산업은 어마한 산업 매출 규모에 비해 아직은 내실이 부족한 산업입니다.

이 숫자들은 게임 업계에서는 꿈의 숫자이죠. 저 역시 서른이 넘으니 정년 퇴임이 걱정 되기 시작합니다.


게다가, 100억 던져주면 닌텐도 나오는 줄 아는 사람이 대통령입니다. 정부는 도깨비 방망이를 휘두르면 안드로이드 OS가 나오는 줄 알고 있습니다. 게임 산업에 대한 인식은 이전 세대들이 컵라면으로 끼니를 때워가며 개발하던 시절과 크게 달라진게 없습니다.
최근에는 게다가 황금알을 낳는 거위의 배가르려는 세력들도 생겨나기 시작했습니다. 여러 정부기관들이 게임 산업 규제를 하기 시작하고, 돈을 갈취하려는 움직임도 있습니다. 언론에서는 청소년 문제의 모든 원인을 게임에 덮어 씌우며 마녀 사냥을 하고 있습니다. 대통령고 그 마녀 사냥에 동참하기 시작했지요.
 그러므로, 게임 개발에 대한 열정과 재미를 느끼지 못하고 안정적인 직업을 원한다면 이 산업은 단념하시길 권장합니다.

이랬던 양반이 이제는 ... ㅉㅉㅉ (이미지 출처는 여기)



하지만

하지만, 정말 게임을 만드는 것이 즐거워서 이 직업을 천직으로 삼고 싶다면 절망하지말고 희망과 기대를 안고 산업에 입성해 주길 부탁합니다. 현 세대들이 싸워서 이기고 이 산업을 보호해서 후 세대들이 고생하지 않도록 최대한 노력하겠습니다. 자신이 만드는 것이 마약이 아닌 건전한 여가문화임을 자부할 수 있도록 가꾸어 놓겠습니다. 최소한 먹고사는 걱정 없이 즐겁게 개발 할 수 있도록 키워놓겠습니다. 저도 훗날 내 자식이 게임 개발을 하고싶다하면 기쁜마음으로 지지해줄수 있는 아버지가 되고 싶습니다. 현재만 보지 말고 미래에 대한 희망과 기대를 안고 산업에 입성해주길 부탁합니다. 자신의 직업을 후회하지 않게 만들도록 노력하겠습니다. 약속드립니다.

여러분은 성목이 될 때 까지 우리가 보호해야 할 게임 산업의 새싹입니다.



현업인들에게 고함

마지막으로 현업에 계신 분들께 부탁의 말씀 드리고자 합니다. 현재 게임 산업이 많은 억압을 받고 있지만 신경 쓰지 않는 사람들도 많습니다. 자신의 연봉 올리는 것에만 신경 쓰고 산업 돌아가는 흐름에는 관심 없는 사람들도 많습니다. 하지만 이제는 너드(nerd)가 골방에 틀어박혀 개발만 해도 되는 시절은 지났습니다. 정책에 목소리도 내고 돌아가는 정국에 활발한 관심을 가져야 합니다. 전 세대들이 피땀흘려 가꾸어 놓은 산업을 후 세대들에게 안정적으로 넘겨주기 위해서는 지속적인 노력이 필요합니다.
 그렇지 않으면 어떻게 되는지는 불 보듯 뻔합니다. 국내 만화와 에니메이션 산업을 보십시요. 과거의 억압을 이겨내고 현재 규모로 성장하기 위해서 수 많은 시간과 노력이 필요했습니다. 억압 기간만 없었다면 미국과 일본보다 훨씬 높은 위치에 있었을지도 모릅니다. 이를 타산지석으로 삼아 우리도 봉기해야 합니다.
 그러므로 약간의 관심이라도 가져주십시요. 지금 당장의 자신의 앞만 보지 말고 산업의 미래도 신경을 써주십시요. 현 상태로 가다가는 20년후에는 이 산업을 지킬 사람이 없을지도 모릅니다. 현재의 우리가 미래에 기업의 오너가 되어도 직원이 없어서 혼자 코딩하고 혼자 모델링 해야 할 지도 모릅니다. 교수가 되어도 게임 개발을 희망하는 학생이 없어 텅 빈 강의실에서 혼자 떠들어야 할 지도 모릅니다. 산업의 미래가 자신의 미래라는 점을 인식하고 현재의 자신만 보지 말고 산업의 미래도 봐 주시길 부탁드립니다.

게임 학과의 건물은 텅텅비게 되겠지요. ( 사진출처 : 여기)

반응형
,
Posted by 알 수 없는 사용자
안녕하세요. 엘키라고 합니다. (절대 베르트랑 따라한거 아님!!)

제가 즐기는 게임은 제 블로그를 통해서 확인하실수 있으니, 저와 같이 플레이하실분 늘 환영합니다 ^^ (이렇게 홍보해도 캡파말고는 아는척 하는분 한분이 안계시더라는....쿨럭!!!)


이 블로그를 보시는 분들 다들 뛰어나고 다양한 경험을 많이 갖춘 분들이시겠지만, 제 경험담을 바탕으로 디버깅에 대해 알아보는 시간을 가져보고자 이렇게 나섰습니다. ^^

우리는 모두 사고 뭉치입니다. 사람이란 실수할 수도 있다는 것을 전제로 이 글을 작성 하고자 마음 먹었죠. (정확성이 떨어지는 발로 하는 스포츠인 축구계의 명언에서 인용했습니다.)

그래서~ 언제나 실수할 여지를 갖고 있는 우리 모두를 위해, 실수를 했을 때 이를 빨리 수습하기 위해 해야 되는 작업이 디버깅이라는 의미로, 사고뭉치들을 위한 디버깅 방법이라 이름을 지었습니다.


흔히 디버깅이라하면, VS Debugger, Windbg, Ollydbg 등의 디버거를 이용하는 것에만 집중 하시는데요, 이 글에서는 디버깅 툴에 의존하지 않는 범용적인 디버깅 과정에 대해 썰을 풀어볼 계획입니다.

이런 창을 보여주지 않는 코딩에 대한 글은 절대 아닙니다. 이런 상황의 원인을 찾고 해결하기 위한 글입니다.



프로그래머가 디버깅을 하게 되는 상황은 주로 다음과 같습니다.

1. 누군가에서 버그 상황을 전달 받는다. (혹은 자동화된 시스템을 통해)
2. 직접 겪는다.


그렇다면, 디버깅 해야 될 상황은 어떤게 있을까요?


1. 프로그램이 비정상 종료 내지는 멈춘다.
2. 사용자가 기대하지 않은 상황과 맞이한다.


비정상 종료 내지는 멈췄을 땐 어떻게 해결 해야 될까요?

1. 덤프가 남았는지 확인한다.
2. 로그를 확인한다.



덤프가 안남았을땐, 무한 루프에 빠지거나 dead-lock 에 빠지지 않았는지 확인해야 합니다.

dead-lock : 코어 점유는 없고, 데드락이 걸린 스레드 몇개만 잠긴다.
무한 루프 : 코어 1개를 점유 하고 있음.


그래서 dead-lock 을 회피하기 위해 모든 스레드를 잠깐씩 거치는 falling-thread를 놓고, 해당 thread가 잠겼는지 확인하는 방식으로 구현하기도 합니다.

falling-thread가 멈추면 어떠한 특정 thread 인해 dead-lock이 일어났다고 판단할 수 있기 때문입니다.

물론 dead-lock 상황은 userdump와 같은 프로그램을 통해 덤프를 생성함으로써 확인 가능하지만 이보다 빠른 대처와 판단이 가능해지는 장점이 있지요.

한가지 팁을 드리자면, 모든 thread는 생성시 thread의 역할과 thread-id 를 로그로 기록하는 것이, 디버깅시 여러모로 유용합니다.

windbg 등의 툴이나 로그등에서 확인할 때 이 정보는 매우 유용해 지죠. (스레드별 로깅을 하는 방식도 나름 괜찮음)또한 크리티컬섹션(CRITICAL_SECTION)객체에는 Ownering Thread 정보가 존재하기에 이를 바탕으로 한 잠긴 Thread를 확인할수 있기 때문이죠.


어쨋거나 dead-lock, 무한루프 모두 dump를 생성하거나 debugger로 attach해서 원인 파악이 가능합니다.


만약 덤프가 남았고 크래시 내지는 예외 발생 후 스택 되감기(Stack Unwinding)를 통해 정상 동작하고 있을땐 어떻게 해야 될까요?


덤프가 남았지만 정상 동작하는 상황
-> 스택 오버 플로우가 났을 때 (새로운 Thread를 만들어서, 기존 익셉션 정보를 처리해야함. ExceptionProcess를 위해 스택을 구성하는 과정에서 오류가 생기기 때문)
-> 잘못된 함수 포인터 콜
-> 스택 메모리 덮어썼을때 (스택 깨먹었다고도 하죠)
-> Divide Zero
-> NULL 포인터 접근
-> 같은 메모리에 delete 두번


크래시가 나는 상황 (절대적이진 않음)
-> 스택 되감기 도중 예외 발생.
-> 잘못된 포인터 캐스팅을 통한 가상 함수 콜

-> 잘못된 함수 포인터 콜
-> 변수 값 덮어 썼을때 (주로 가상함수 포인터 테이블을 덮어썼을때 크래시가 남.)
-> 잘못된 포인터 접근


덤프가 남았을 경우는 대부분이 단순 실수가 많습니다. NULL 포인터 참조 오류와 같은 경우나 잘못된 포인터 참조는 꽤나 자주 겪게 되는 단순 실수에 해당 되기 때문에, 발견하게 되면 바로 고칠 수 있는 단순 버그에 속합니다.

당연한 얘기겠지만, 스택 되감기란 아주 단순한 동작이 아니기 때문에 이로 인한 무한 루프에 빠지는 경우도 종종 생깁니다.

예외 처리를 위해 감싸는 로직의 단위를 잘 판단할 필요가 있습니다.


애매모호한 동작을 보이지만 잘못된 포인터 캐스팅은 상대적으로 찾기 쉬운 편입니다. 해당 포인터를 강제 캐스팅 해야 될 만큼 잘못된 설계가 되어있는 경우가 대다수지만, 피치 못할 사정 상 그렇게 구현 했다고 해도, 캐스팅을 위한 검증 값 체크만 잘하면 적어도 크래시가 나지 않게 동작 시키는 것은 무리가 아니지요.

덤프가 남았는데, 콜스택이 영~ 이상하다. 이럴 때 참 난감합니다.



이러한 상황을 만드는 데에는 변수 값 덮어쓰기가 주범이 되곤 합니다.

덮어 써진 메모리가 유효한 위치 (프로그램 내에서 할당된 영역)이라면 예외가 발생하지 않습니다.

이런 상황을 감염이라 부르는데, 문제가 생긴 곳에서 바로 증상이 생기지 않고, 영~ 쌩뚱 맞은 곳에서 오류가 생기기 때문입니다. (버그로 발현되기도 하고, 크래시가 되기도 함)

그래서 흔히 감염이 최악의 버그라고 평하곤 하지요.

가장 주의해야 될 버그이고, 가장 찾기 힘든 버그입니다. 그래서, 좋은 프로그래밍 습관을 필요로 하지요.

흔히 c스타일의 코딩(memcpy, strcpy, 포인터 직접 조작 등)에서 자주 발생하는 문제입니다. 코어 레벨의 코딩에서는 여러가지 상황으로 인해 포인터 조작이나 memcpy를 할 수 밖에 없다고 하더라도, 컨텐츠 단에서는 반드시 safe한 함수를 사용할 것을 권장합니다.

이외에도 예외를 발생 시키지 않는 프로그래밍 습관에 대한 이야기도 해보고 싶은데 이 글의 주제를 벗어나기 때문에 기회 되면 따로 글을 작성해보고 싶네요.


자~ 여기까지 내용이 서론이었습니다. 진짜 하고 싶은 이야기인 잡기 힘든 버그를 해결하는 과정에 대한 썰을 다음 글에서 풀어보고자 합니다.


다음 시간에 만나요~ 제발~~~


반응형
,

SKY Color에 대하여.

아트 2012. 2. 5. 01:55
Posted by 알 수 없는 사용자

T모사의 뭐든 궁금해 하는 배경아티스트/TA Silverchime 입니다. 1월에 프레넬에 대한 글을 쓰고 나서 심하게 앓은 덕분에 중간에 본의아니게 심한 감기에 걸려 한번 쉬게 되었네요. (7킬로나 빠지는 대 난관이었습니다! ㅠㅠ) 요즘 날씨가 많이 춥습니다.  건강이 최고에요 훌쩍...

오늘은 하늘의 색에 대해서 알아보도록 하겠습니다. 배경하시는분들은 최근 Time of day라던지 해서 직접 칼라를 잡으실 일도 많지요. 월드라이팅 할때 스카이 컬러를 어떤식으로 잡을지 고민을 많이들 해보셨을 듯 합니다. 혹시나 저처럼 궁금하셧을 분들을 위해 하늘, 또는 대기의 색이 어떤식으로 발현되는지에 대해 알아보겠습니다.

대기란

대기란 가스분자와 다른 지구를 둘러싼 물질들의 혼합체입니다. 질소(78%) 산소(21%) 아르곤, 그 외에  수분(기화상태, 물방울, 눈입자로 존재) 등이 있습니다. 미량의 다른 개스들과, 작은 고형입자들, 먼지나 그을음, 재, 꽃가루,심지어 바다에서 나온 염분도 포함됩니다.

대기의 구성 성분은 위치에 따라서도 다르고 날씨나 다른 조건에도 영향을 받습니다. 공해는 그을음이나 먼지, 다른 개스등을 추가하며, 화산, 근처에 물이 있거나 눈비 오는 상태에 따라서도 달라지기때문에 딱히 대기! 라고  한번에 말하기엔 약간 추상적일 수도 있습니다.

중요한 점은 대기는 중력의 영향을 받으므로 지상에 가까울수록 밀도가 높아지고 고도가 높아질수록 극히 희박해진다는 점입니다.( 이러한 이유로 사실상 어디까지 대기이고, 우주인지 명확한 구분점이 없습니다.) 또한 균일하게 희박해지는것이 아니라, 지표면 근처에 대부분이 존재하고 고도에 따라 빠르게 감소하죠.

빛의 성질 : 라이트웨이브

빛은 파동상태로 방사되거나 이동하는  에너지의 한 종류입니다. 많은 종류의 에너지가 파동상태로 이동합니다. 일례로 음파는  공기의 파동입니다. 마찬가지로 빛은 전자와 자기장의 파동(전자기파 Electromagnetic radiation)으로 설명할 수 있습니다.
가시광선을 비롯한 여러 파장의 빛은 전자기파의 일부인 것입니다.  말이 어려운데 이 글에서는 그냥 빛은 파동이라고 생각하시면 되겠습니다 ^^ 양자물리학은 약간 접어놓기로 하죠.

전자기파는 공간을 약 초속 30만km로 이동합니다 이걸 광속lightspeed이라고 부릅니다.

방사되는 에너지는 파장과 진동수로 표현됩니다. 파장은 사이클의 한 반복, 즉 톱또는 보톰사이드간의 거리가 되겠습니다. 진동수는 초당 몇번 진동하느냐 겠지요. 파장이 길어질수록, 진동수는 낮아집니다. 그리고 상대적으로 적은 에너지를 가지게 됩니다.


빛의 색

가시광선은 위에서 언급한 전자기파 중 우리 눈이 감지할 수 있는 스펙트럼 부분을 말합니다. 태양빛이나 전구의 빛을 프리즘으로 분리하면 여러가지 색의 빛이 나오지요. 흔히 말하는 무지개 색입니다.

분리된 색상은 연속적으로 이어지며 블렌드 됩니다. 색이란 결국 다른 파장wavelength과 진동수frequency, 그리고 다른 에너지량을 의미합니다.
보라색은 가시광선중 가장 짧은 파장을 가지며 가장 높은 진동수와 에너지를 가지고 있다고 할 수 있습니다. 반면에 적색은 가장 긴 파장을 가지며 가장 낮은 진동수와 에너지레벨을 가집니다.


내 푸른색 광선검 에너지 레벨이 더 높다고! 붉은색 꺼져 시빠!
(뻥입니다... Orz)

공기중의 빛의 이동

빛은 진공에서 방해받지 않는 한 직진합니다. 그러나 공기 중, 대기를 이동할 때에는 가스 분자들과 먼지등과 계속해서 충돌합니다. 그리고 그 충돌하는 대상의 크기에 의해 여러가지 다른 형태로 반응하게 됩니다.

물방울은 가시광선 파장보다 큽니다. 이러한 큰 파티클에 부딛치게 되면, 여러 방향으로 반사되거나 튕겨나가게 됩니다. 이렇게 큰 분자에 대해서는 다양한 색의 칼라가 모두 다 공통되게 반사되므로 이러한 형태의 반사된 빛의 색은 흰색으로 보입니다. (맑은 날 구름의 색을 기억해 보세요.)

기체분자는 빛의 파장보다 작습니다. 이런 작은 크기의 입자에 빛이 부딛히게되면 다른식으로 반응합니다. 충돌했을 때, 일부가 흡수되고 잠시 후 기체분자에서 다시 방출됩니다. 이때 반사되는 색은 흡수한 색과 동일하며 여러가지 색이 다 다르게 흡수와 방출을 하게 됩니다. 여기에는 법칙이 하나 존재하는데, 높은 진동수(푸른색)이 낮은진동수, 즉 적색보다 더 강하게 산란됩니다. 이것을 레일레이 스캐터링 Rayleigh scattering 이라고 부릅니다.

대기에서 레일레이 스캐터링의 공식은 다음과 같으며,
중요한 내용은 빛의 산란의 강도는 파장의 네제곱에 반비례한다는 것입니다.

즉 파장이 길수록, 진동수가 낮을수록(적색,오렌지색 계열) 적게 산란되며(투과됨)
파장이 작고 진동수가 높고 에너지가 클수록(푸른색 계열) 강하게 산란 되겠지요.


왜 하늘은 푸를까요?

레일레이 산란공식에 따르면, 빛이 대기중을 이동하면서 파장이 긴, 적색, 오렌지색, 노란색의 빛은 거의 투과되어 버립니다. 그러나 짧은 파장인 푸른색은 기체분자에 흡수되었다가 다시 전방위로 방출하면서 흡수된 색을 다시 내보냅니다. 이러한 이유로 하늘, 대기의 색은 푸른색으로 보입니다.

 그러나 지평선에 가까워지면서 파란색은 점점 약해집니다. 이유는 지평선에 도달하면서 더 많은 대기를 투과해야 하므로 그 과정에서 또다른 산란과정을 거치게 되고, 눈까지 도달하는 푸른색의 일부분이 소실되어버립니다. 지평선에 가까워질수록 흰색에 가깝게 옅어집니다.



우주에서는 충돌해서 산란될 기체분자가 없으므로, 우리눈에 도착하는 산란된 색상의 빛도 없습니다.
우주에서 빈 우주가 검은색으로 보이는 이유입니다.
 

우주가 어두워서가 아니라, 단지 방해하는 것이 없어 산란되지 않을 뿐...
거기에도 빛은 당연히 존재합니다.

왜 그렇다면, 보라색 하늘이 아닌가요

파장이 더 짧은 바이올렛 웨이브는 더 빨리 산란되어 소실되는데다가, 인간 눈의 보라색의 응답도가 비교적 낮은 부분도 역할을 합니다. 안그래도 약한 보라색 칼라 강도인데다 보라색은 Blue+Red의 조합이므로 파란색에 미세한 붉은기가 첨가된 정도로밖에 느껴지지 못하게 됩니다.

실제 무지개에서도 보라색은 선명하게 보이지 않습니다. 

Response curves for the three types of cone in the human eye
파장에 따른 인간 눈의 시각적 민감도

저녁 노을이 빨간 이유

하루의 시간이 지나 태양의 고도가 낮아지게 되면, 빛은 우리 눈에 도착하기 위해 훨씬 더 두텁고 긴 대기층을 통과해야 합니다. 위 대기항목에서 언급한 것처럼 대기는 균일하게 분포되어 있는 것이 아니며 낮은 곳에 대부분의 공기가 존재하는 이유로 더 극대화된 결과를 냅니다. (대략 낮보다 약 40배를 통과해야 합니다!) 그 결과로 푸른색은 거의 산란되어 우리 눈에 닿지 않게 되고 파장이 긴 붉은색,, 오렌지색, 노란색만이 우리 눈에 들어오게 됩니다.  


담배연기의 색

담배연기색을 혹시 기억하시나요.
보통 하얀색이라고 떠올리시는 분들이 많은데, 사실 담배연기의 색은 옅은 푸른색을 띱니다.
(인터넷에 tobacco smoke라고 검색해 보세요 ^^)

자세히 빛을 주고 관찰하면 옅은 파란색+그레이를 합친 색입니다.
이 역시 빛이 산란하면서 파장이 작은 푸른색이 산란되면서 나타나는 현상입니다.

단지 빛이 산란된 칼라이므로 입자의 본래 칼라를 반영하지 않습니다.
실제의 담배연기 입자는 노란색입니다. 손수건에 불어 본 예.

아주 미세한 공기 분자에 산란되는 현상은 레일레이 공식을 따르지만,
위에서 예시한 담배연기와 같은 에어로졸이나 콜로이드와 같이 공기분자보다는 크지만, 여전히 빛의 파장에 따라 빛이 색상이 다르게 산란되는 현상을 틴들 현상/산란Tyndall scattering 이라고 합니다. 틴들 산란은 일반적으로 레일레이 산란보다 훨씬 강력하게 나타납니다. 틴들 이펙트는 레일레이 공식과 ‘비슷하게’ 나타나지만 입자크기와 각 형상이 너무나 다르므로 수학적으로 이를 정확히 규정하는 '확실한absolute 공식'은 존재하지 않습니다.



구름의 색

40나노미터 급의 공기분자나 콜로이드 에어로졸 등은 빛의 파장보다 낮으므로 다르게 투과 또는 산란되며 칼라에 영향을 받았습니다. 그러나 공기중에서 구름을 구성하는 water ice는 빛의 파장보다 훨씬 큽니다. (90-100나노미터) 이런 경우에는 파장의 길이에 영향을 거의 받지 않고 모든 빛 성분이 반사됩니다. 이를 Mie scattering 미 산란 이라고 하며 하얀색으로 산란됩니다. 이런 이유로 구름은 일반적으로 하얀 색을 띠게 됩니다. 아주 두터운 먹구름은 그림자를 드리우므로 검습니다만...


모래먼지의 색

40 나노미터 이하부터 물 입자 크기까지 알아보았습니다.  자 그럼 공기중에 이보다 더 큰 입자가 있을까요?
네 당연히 있습니다. 바로 샌드 / 더스트 들입니다.
750 나노미터급 이상이 되면 이때부터는 Mie 산란도 아닌 파티클 본연의 칼라에 영향을 받게 됩니다. 

시드니를 덮친 먼지는 철Fe성분이 많이 들어간 적색 먼지입니다. 아래는 말그대로 모래폭풍(샌드스톰)이지요.
이는 빛의 산란과는 관계없는 입자 본연의 색이 표현된다고 보시면 됩니다.

많이들 보셨겠지요 ^^ MI:3 중의 샌드스톰입니다. 모래의 노란색 이지요.

결론

-빛은 에너지레벨, 파장, 진동수에 따라 특정 가시광선대역을 가진다.
-공기중 입자의 크기가 아주 작은 기체분자 Gas molecules에 충돌하면 레일레이 공식에 따라 짧은 파장(푸른 계열)의 산란이 더 크게 나타나며, 이것이 하늘의 색을 푸르게 보이게 한다.
-에어로졸이나 콜로이드급 역시 위와 같은 이유로 푸른색으로 보이며 이를 틴들 산란이라 한다.
-라이트웨이브보다 큰 경우 Mie 산란이라 하며 모든 칼라를 반사, 하얀색으로 산란된다.
-750 나노미터 이상의 큰 공기속의 입자는 파티클 본연의 칼라를 가진다. 


산란될 것이 없는 검은 우주부터, 공기가 산란되기 시작하는 푸른 부분,
지평선 부분의 옅은 푸른색들이 보이신다면 이미 오늘 내용은 마스터하신거네요.

맑은 하늘만큼 가슴시원해지는 것도 없겠지요. 오늘도 즐거운 주말, 행복한 하루 되세요 ^^ 


P,S 화성은 산화철이 많이 함유된 모래폭풍 때문에 하늘이 붉지만,
이산화탄소로 이루어진 대기가 '매우 희박'하기 때문에 노을은 오히려 파랗다는 보고가 있네요.

화성의 파란 노을. 출처 : NASA




 

 

반응형
,