'분류 전체보기'에 해당되는 글 20건

  1. 2007.12.30 파이썬용 스프링노트 모듈
  2. 2007.12.29 파이썬에서 스프링노트 API 사용 (1)
  3. 2007.12.15 메모리가 주륵주륵
  4. 2007.11.20 삼각형 - 평면 충돌
  5. 2007.06.13 C++ 추상 클래스와 포인터 캐스팅, 다중상속 ㅅㅂㄹㅁ (11)
  6. 2007.05.16 [기사] "내 꿈은 골방에 처박힌 프로그래머" (1)
  7. 2007.05.03 또다른 지식의 성전 리메이크된다
  8. 2007.04.24 Win32API 자작게임 배포
  9. 2007.04.02 게임지와 정품부록, 게임시장
  10. 2007.03.29 블록버스터 게임과 Independancy

파이썬용 스프링노트 모듈

프로그래밍 2007. 12. 30. 21:16

설명

  • 파이썬스프링노트 모듈로 CRUD만을 지원하는 간단한 구조입니다.
  • CRUD 작업 함수는 요청된 페이지를 문자열로 반환합니다. (XML 텍스트)
  • Delete의 경우에는 반환값이 없습니다
  • 사용자 설정을 위한 springnote.conf 파일이 필요합니다.
[springnote]
open_id: open ID
user_key: user key
app_id: application ID
app_key: application key

멤버함수

  • httpReq(method, uri, data=None): 스프링노트에 대한 HTTP REQUEST
  • createPage(): 사용자 노트에 새 페이지를 만듭니다.
  • getPages(): 사용자 노트의 페이지 전체(pages)를 읽어옵니다.
  • getPage(page_id): page_id에 해당하는 페이지를 읽어옵니다.
  • updatePage(page_id, title, memo): page_id에 해당하는 페이지의 제목을 title로, 내용을 memo로 변경합니다
  • deletePage(page_id): page_id에 해당하는 페이지를 삭제합니다
  • getTop(): 사용자의 시작 페이지(모든 페이지의 상위 페이지)의 id를 얻어옵니다.

페이지 생성

  • createPage() 는 현재시각을 제목으로 하여 새 페이지를 생성하고 생성된 페이지의 내용을 문자열로 반환합니다.

예제

  • 새 페이지를 생성하고 일련의 내용을 채워넣는 코드 (python 2.5 에서의 ElementTree를 이용하여 XML 파싱을 하였습니다.)
comm = SpringNote()
no_newpage = XML(comm.createPage()).findtext('{http://api.springnote.com}identifier')

title = '솔로라서'
memo = '행복해요ㅠㅠ'
comm.updatePage(no_newpage, title, memo)

소스코드

이 글은 스프링노트에서 작성되었습니다.


 파이썬용 모듈이 페이지 생성이 불가능하길래 새로 작성해보았다. 스프링노트에 블로그로 보내기가 있길래 한 번 티스토리로 쏴봤는데 의외로 놀라울 정도의 퀄리티였다. 하지만 코드블럭에서 조금 문제가 발생. 결국 조금 손을 봐주는 걸로 끝냈다. 사실 참고가 된 소스를 살짝 리버전한 정도에 불과하다. 반성! 파이썬이 참 재밌다. 취직하고싶다.

Trackbacks 0 : Comments 0

Write a comment


파이썬에서 스프링노트 API 사용

프로그래밍 2007. 12. 29. 02:54
링크 : http://nakada.springnote.com/pages/400945

 스프링노트 메쉬업을 작성해보기 위해 파이썬 스프링노트 API 모듈을 찾아보았다. 오픈마루 스프링노트 API 공식 도큐멘트에 링크되어 있는 파이썬 예제는 9월자로 스프링노트 인증방식이 바뀌기 전의 예제였다. 약간의 구글링 끝에 링크에 위치한 문서를 찾았지만 실제로는 ElementTree의 Element의 tag가 "{http://api.sptringnote.com}tagname" 같은 식으로 되어 있어서 위 문서 그대로는 ElementTree.findtext()를 통해서 제대로 파싱이 되지 않는 문제가 있었다. (왜일까?)

 PyDev를 쓰고 있어서 디버거를 돌려 볼 수 있었기에 망정이지 텍스트 에디터만 꼴랑 가지고 작업하고 있었으면 백날 삽질해도 알아차리지 못할 문제였다. 후덜. 갈 길이 멀다. 컴팩트한 프로젝트니까 후딱 끝내야지.


Trackbacks 0 : Comments 1
  1. Favicon of https://kkamagui.tistory.com BlogIcon kkamagui(까마귀, 한승훈) 2007.12.29 12:16 신고 Modify/Delete Reply

    와우~ 감사합니다. ^^)/~ 안그래도 파이썬에서 스프링노트에 접근하는 방법을 찾고있었는데... 좋은 자료네요 ;)
    감사히 잘 쓰겠습니다.

Write a comment


메모리가 주륵주륵

프로그래밍 2007. 12. 15. 10:49
MFC에서 부득이한 경우로, vector 나 기타 메모리 관리 클래스를 거치지 않은 채로 동적할당을 이용해서 객체를 사용하던 중 문제가 발생했다. 동적할당한 객체를 가리키건 포인터를 delete 하거나, 동적할당을 반복하던 중에 포인터가 붕 떠버리는 (dangle) 현상이 일어난 것.

거기다 이 객체들이 다른 힙까지 침범을 하는 건지... 이상한 부분에서 오류가 발생하기도 하고, 포인터가 엉뚱한 곳을 가리키기도 하고, 그래서 delete 가 말을 듣지 않는 등 일대 패닉이 일어났다. (heap overrun)

내가 싸질러 놓은 객체의 생명주기 하나도 관리하지 못하는 걸까 하고 좌절했지만 결국 객체의 멤버 초기화 함수 Clear() 를 정의하여 delete 직전에 호출해주기로 했다.

하지만 여전히, 안된다.

동적 할당 부분을 추가한 걸로 봐선 아무래도 힙 문제일 가능성이 높다. OTL

Trackbacks 0 : Comments 0

Write a comment


삼각형 - 평면 충돌

프로그래밍 2007. 11. 20. 22:31
며칠간 3차원 벡터로 정의되는 세 정점으로 이루어진 삼각형과 임의의 평면과의 교점들을 찾기 위해 고군분투하고 있었습니다. (삼각형-평면 충돌) 평면과 각각 정점과의 거리를 구한 값들(각 정점에 해당하는 세 개의 값)의 부호를 검사하는 것은,

#define ISALLSAMESIGN(x, y, z) ( ((x > 0) == (y > 0)) && ((y > 0) == (z > 0)) )

과 같은 식으로 처리할 수 있었는데, 이것만으로는 어떤 정점이 평면의 다른 방향에 존재하는지(세 값 중에 어떤 값이 나머지 두 값과 다른 부호를 가지고 있는지) 알 수가 없더라구요. 흑흑.

그래서 과연 어떤 값이 혼자 튀는지 검사할 수 있는 방법을 몇가지 생각해봤습니다. 매크로로 나타낼 수 있을 정도로 간단하면 좋을텐데. a, b, c를 넣으면 결과값으로 n번째 수가 부호가 다르다고 말해줄 수 있는 그런 놈이요. 일단 간단하게 생각해서 세 값의 부호를 각각 0과의 비교를 통해서 boolean으로 나타낼 수 있다고 생각했습니다. 그리고 세 개의 boolean 을 나열하면 3bit의 정수(0 ~ 7)로 나타낼 수 있겠죠.
세 부호가 같은지 판별하기 위해서는 이 결과값이 111(7)이나 000(0)인 경우만 추려내면 될 겁니다. ( result%7 == 0 ) 하지만 문제는 그 반대에서 조금 더 뻗어나가죠. 세 개의 bit 중에서 다른 두 bit 와 다른 bit 의 서수(ordinal)을 알아내야 합니다. 어쩌죠? (….)

#define WHOISTHECRIMINAL(a, b, c) ( (a*b < 0) + (b*c < 0)*2 + (c*a < 0)*4 )

생각한 방법은 결과값 3bit 를 가지고 0과 7과의 비트연산을 통해서 2bit의 값(0, 1, 2)을 얻어 그것을 서수로 사용하는 것이었습니다. 이것 역시 비교문을 쓰지 않기 위해서 생각해 낸 방법입니다. 하지만 대체 어떻게 연산해야 001 ~ 110 의 값을 차례대로 서수로(그것도 순차적인 서수가 아닌 0, 1, 2, 2, 1, 0 의 순으로) 바꿀 수 있는 걸까요? 적잖이 생각해보았지만 이건 좀 어려울 것 같습니다.

그런데 문제는 이거죠. 구현도 중요하지만 성능도 중요한 게 문제죠. CPU 비용이 얼마나 작은지. 결과값의 신뢰도가 어느정도인지. 고심(하면서 딴짓)하던 끝에 ary[] = { 0, 1, 2, 2, 1, 0 } 으로 배열을 선언하고 위의 결과값을 배열의 첨자로 사용하는 방법으로 결정했습니다. 제가 만들고 있는 프로그램은 데스크탑에서 실행될 거고, 메쉬의 모든 삼각형에 대해서 행해질 연산이니까요. 네.


Trackbacks 0 : Comments 0

Write a comment


C++ 추상 클래스와 포인터 캐스팅, 다중상속 ㅅㅂㄹㅁ

프로그래밍 2007. 6. 13. 22:41
상황설명

A라는 부모 클래스를 만들고, 이 A라는 클래스의 포인터인 A* pA 를 인자로 하는 foo(A* pA)를 정의해서 사용중이었다. 이 함수의 인자로는 A를 상속한 B나 C클래스를 예상할 수 있으며, 이 B와 C클래스는 I라는 순수 가상함수를 상속한 다중상속 객체들이었다. I는 순수가상함수인 Vfoo()를 가지고 있었다. C는 생성자에서 A의 함수(가상함수가 아니다)를 호출한다.

사용자 삽입 이미지

이런 상속관계 (수정)


vector<I*> vt;

...

C* pC = new C;
I* pI = (I*)pC; // C* -> I*
vt.push_back(pI);

...

A* pA = (A*)vt[0]; // C* -> I* -> A*
foo(pA);

...

foo(A* p_pA)
{
    I* pI = (I*)p_pA; // C* -> I* -> A* -> I*
    pI->Vfoo(); // 여기서 문제발생
}

문제발생

문제는 C형 인스턴스를 가리키는 A형 포인터 pA_dir_C를 foo(A* pA)의 인자로 넘겨주면서 일어났다. foo(A* pA)함수 내부에서는 인자로 받은 pA를 (I*)pA 로 형변환하여 Vfoo()를 호출하는 루틴이 들어있었는데, 여기서 에러가 발생한 것이다. (6025 pure virtual function call)

Watch를 통하여 살펴보니 vftable의 문제였는지, Vfoo()가 아닌 엉뚱한 함수가 불려오더라. (다른 추상 클래스 I2에서 오버라이딩 된 가상함수였다.) 포인터 형변환에서 가상함수 테이블에 변화가 오는 것일까?

해결책

결국 C* -> I* -> A* -> I* 와 같은 여러 번의 형변환을 거치지 않고 C* -> I* 상태에서 pI->Vfoo() 식으로 형변환 단계를 줄여서 사용하였다. 정확히 말하면 문제를 해결한 것이 아니라 회피한 것이나 마찬가지다. 하지만 적당한 레퍼런스도 없고, 도와줄만한 사람도 없고 해서. 코드 길이는 좀 길어질지 몰라도 저런 식으로 함수를 통하는 단계를 줄여버렸다.

감상

쩐의 전쟁이 너무 재밌다.


Trackbacks 1 : Comments 11
  1. ProgC 2007.06.14 02:24 Modify/Delete Reply

    음... 추상화 인터페이스를 이용한 설계를 하시는거 같은데
    그림이 좀 잘못된 것 같습니다. 그림상으로 보면 I인터페이스가 B, C를 구현하는걸로 되어 있네요. 그 반대가 되어야 할 것 같습니다.

  2. 동숙이 2007.06.14 12:23 Modify/Delete Reply

    정확한 소스를 어떻게 되나요?
    궁금해서 코드를 만들어 봤는데..

    제가 한봐로는 문제가 없는거 같은데요.

    • Favicon of https://axnoah.tistory.com BlogIcon AxNoah 2007.06.14 18:54 신고 Modify/Delete

      그럼 저 자체로는 문제가 없다는 걸까요.
      6025 pvfc 문제는 생성자에서 가상함수 테이블 관련해서 일어나는 문제라고 하던데, 형 변환 과정에서 가상 테이블의 변화가 있는지 없는지를 몰라서요.

  3. Favicon of http://dcple.com BlogIcon chadr 2007.06.14 14:59 Modify/Delete Reply

    제가 봐도 코드상에 이상한점은 안보이는군요..

    저기 안보이는 "...."부분에서 뭔가 잘못된 일을 하지 않는가 싶군요.

    • Favicon of https://axnoah.tistory.com BlogIcon AxNoah 2007.06.14 18:55 신고 Modify/Delete

      ㅠㅠ 대체 어떤 게 문제인지 모르겠습니다.
      회피하고 말았네요.

  4. Nagne 2007.07.31 11:44 Modify/Delete Reply

    검색으로 지나가다가 소스를 보고 발목잡혀 글남깁니다...
    일단 소스는 좀 오류가 심각하네요....당연히 않됩니다...
    I* pI = (I*)pC; 이부분과
    vt.push_back(pI); 이부분과
    A* pA = (A*)vt[0]; 이부분이 잘못됐습니다..

    이부분이 문제 입니다.... 인터페이스 I와 단순한 부모클래스 A를 다중상속받아서 사용하고 있습니다...
    벡터에 저장할 때는 (I*) 형으로 변환하고 있군요..
    자 일단 다중상속 받는 순서가 I 가 먼저오고, A가 다음에 온다고 가정하겠습니다...
    pC 의 주소값이 0x1000 이라고 가정하구요....
    I* pI = (I*)pC;
    A* pA = (A*)pC;

    이렇게 했을때 pI의 값은 0x1000입니다..
    그리고 pA의 값은 0x1000+alpa 입니다...
    왜 그러냐구요...클래스 포인터의 형변환은 주소값을 바꾸는
    기능을 합니다....(short*) 를 (int*)로 형변환 하는것하고
    클래스의 포인터를 형변환 하는것은 아주 큰 차이가 있습니다.
    (short*)를 (int*)로 형변환 하는것은 reinterpret 캐스팅이라고합니다. 형변환한 주소값에 아무런 변화가 없습니다. 형변환 하지 않을 경우 컴파일러가 이부분 문제가 있어보인다며 확인할것을 강요하고 프로그래머가 형변환 코딩을 넣도록 강요하는 역할을 가집니다.

    그러나 클래스 포인터의 형변환은 완전히 다른 의미입니다...즉 해당 클래스로 형변환 하면서 주소를 계산을 하는것이죠....이때에 룰이 있습니다..
    두 클래스간에 상속관계가 전혀 없을때는 주소계산을 하지 않습니다. 이것도 reinterpret 캐스팅이라고 합니다.. 그리고 상속관계에 있을때는 포인터 형변환시에 static 캐스팅이 발생합니다..주소값을 계산해 버리죠,....

    I* pI = (I*)pC; // 여기서 static 캐스팅 됐습니다..

    C는 I를 먼저 상속받았다고 가정했으니..static 캐스팅했지만 값의 변화는 없을겁니다...
    만약 (A*)pC 하였다면 값의 변화가 옵니다.

    그런데...
    (A*)vt[0]; 요 부분에서 vt[0]의 형은 (I*) 형입니다. 그리고 I와 A는 아무런 연관성이 없습니다..
    때문에 여기서는 reinterpret 캐스팅이 발생합니다...
    즉, A* pA = (A*)vt[0]; 요 부분에서 pA가 정상적인 동작을 할려면 0x1000+alpa 로 저장이 되어야 하는데, reinterpret 캐스팅 되어서 pA에 저장된 주소값은 0x1000이 되어버린것입니다...그러면 pA를 이용해서 Vfoo()를 호출하면 I의 영역을 A의 영역처럼 사용하겠죠..숨은 버그입니다... 그리고 c++에서는 static_cast<> 연산자와 reinterpret_cast<> 연산자가 있어서 위와 같은 버그를 컴파일 타임에 잡아줄수 있게끔 하고 있습니다.. (I*) 와 (A*)는 C 타입의 형변환입니다..reinterpret 캐스팅과 static캐스팅의 구분이 엄격하게 따지고 들어야만 제대로된 코딩이 가능하죠....
    아 그리고
    foo() 함수 내부에서
    * pI = (I*)p_pA; 요부분도 reinterpret 캐스팅이죠...아무연관성 없는 포인터형으로 변환한 것이니깐요..

  5. Nagne 2007.07.31 12:07 Modify/Delete Reply

    위 코드를 수정한다면 다음과 같이 하면 될겁니다..

    vector<I*> vt;

    ...

    C* pC = new C;
    I* pI = static_cast<I*>pC; // C* -> I*
    vt.push_back(pI);

    ...

    A* pA = static_cast<A*>static_cast<C*>vt[0]; // C* -> I* -> C*-> A*
    //I와 C는 연관성이 있지만 I와 A는 연관성이 없기에 연관성 있는것으로 중간에 연결가능한 C를 거쳤다가 변환합니다..당연히 static_cast이어야 합니다..

    foo(pA);

    ...

    foo(A* p_pA)
    {
    I* pI = static_cast<I*>static_cast<C*>p_pA; // C* -> I* -> C* -> A* -> C* -> I*
    //마찮가지로 A* 에서 I*로 형변환 하는 사이에 C*로 정적 캐스팅합니다..
    pI->Vfoo(); // 이제는 정상동작
    }


    static_cast가 하는일은 베이스클래스로 형변환 할때는 차일드 클래스의 주소공간 중에서 베이스클래스의 주소를 찾아서 주소값을 바꿔주고, 차일드 클래스로 형변환 할때는 베이스클래스주소가 그 차일드 클래스로부터 정적 캐스팅하였을때 획득한 주소라고 가정하고 차일드의 주소를 계산하여줍니다...
    따라서 사실 위 소스코드는 정상 동작하지만...
    vector<I*> vt 가 B 클래스의 인스턴스의 주소도 같이 저장하는 벡터라면 여전히 버그가 존재한다는것 잊지마세요...
    일단 버그 상관 없이 동작시킬라면 B 하고 C가 I하고 A를 상속받는 순서를 똑같이 하여야만 하고, B저장했던것인지 C저장했던것인지 확실히 구분 가능하여야만 위 코드가 정상 동작할 겁니다...

    class I{}; class A{}; class X{}; class Y{};
    class B : public I,public A ,public X{};
    class C : public A,public I ,public Y{};

    만약 클래스 구조가 이딴식으로 된다면....위에 수정해 드린 코드로도 정상동작은 않됩니다...단 vt[0]가 B의 인스턴스로부터 저장된 것인지. C의 인스턴스로부터 저장된것인지 확실히 알수 있다면 위와 같은 방식의 형변환으로 충분할 것입니다...
    그럼 이만...

    그리고 더 궁금한거 있으면 yilove78@fme.co.kr 로 문의하세요....

  6. Favicon of http://wafe.kr/ BlogIcon wafe 2007.08.28 15:42 Modify/Delete Reply

    다중 상속에 대해서 검색하다 우연히 들렀는데, 이미 다른 분께서 해결책을 남기셨군요. ^^

    C++에서는 타입 캐스팅을 할 때 C 스타일의 캐스팅보다는 C++ 스타일의 static_cast, dynamic_cast, reinterpret_cast 를 쓰는 것을 추천하고 있습니다.

    C의 캐스팅에 비해 여러가지 의미가 첨가되어 있는 것이 C++의 캐스팅이기 때문에 캐스팅의 내용을 좀 더 명확하게 알고 구분해서 쓰라는 의미가 있고요, 또 글에 쓰신 것과 같이 부적절한 캐스팅에 대해서 컴파일러가 힌트를 줄 수 있기 때문입니다.

    • Favicon of https://axnoah.tistory.com BlogIcon AxNoah 2007.09.15 12:50 신고 Modify/Delete

      관련 글 들은 몇 번 읽은 적이 있는데, 아무래도 습관 탓인지 아직 익숙하지 않네요. 경험부족이 이런데서 나오나 ㅠㅠ 음. 컴파일러가 알려 줄 수 있으면 적극 활용해야겠네요.

Write a comment


[기사] "내 꿈은 골방에 처박힌 프로그래머"

생각하다 2007. 5. 16. 21:45
기사링크 : http://zine.media.daum.net/mega/h21/200705/15/hani21/v16737605.html

확실히 요즘 아이들(나도 여기에 반쯤은 포함된다 싶다)은 문제다. 사람과의 소통이 너무나도 단절되어 있다. 오죽하면 학원 때문에 죽겠네 뭐하네 하는 아이들이 친구들을 만나고 싶어 학원에 다니겠는가? (그조차도 피곤해서 잘 놀지도 못한다더라) 요즘들어 사이버공간에 대한 이슈, 뉴스를 많이 접하는 것 같다. 특히나 실생활(사생활, 사회)에 관련된 뉴스들.

뉴스를 접할 때마다- 어째서 사람들은 사이버 공간에 그렇게 큰 의미를 부여하려는 것인가, 싶다. 아니 실제로는 사람들이 왜 그렇게 생각하는 것인지가 궁금하다. 인터넷은 그저 매체인가? 전공자이기 때문에 그 관심은 더하다. 내가 볼 때 인터넷은 도구다. 싸이월드 역시 자기표현의 매체에 불과하다. 안락한 만남의 장이라는 것도 결국엔 일시적인 사람들간의 연결에 불과하지 않나? 본질은 사이버 공간이 아니다. 인간과 인간의 연결 그 자체라는 거다. 하지만 정말 인터넷이란 그 자체로 다른 공간인가?

실존하지 않는 사이버 공간을 다뤘던 옛 SF들이 생각나는 밤이다.



Trackbacks 0 : Comments 1
  1. 알 수 없는 사용자 2007.05.18 20:57 Modify/Delete Reply

    저런 친구는 한 일주일 게임회사에 집어 넣고 월화수목금금금으로 야근을 시켜 봐야 정신을 차릴겁니다....

Write a comment


또다른 지식의 성전 리메이크된다

생각하다 2007. 5. 3. 12:10

오래 전부터 만날 운명이었던 당신에게.

나는 시공의 여행자인 타임워커 알비레오라고 하오...

안영기님의 명작. 또다른 지식의 성전이 리메이크된다고 합니다. 개발사는 GBA용 게임 아이언키드로 유명한 비트메이지입니다. 수소핵융합의 추억이 되살아나는군요. 플랫폼은 미정이랍니다. 개발자 분들이 게임에 대한 애착이 대단하여, 게임의 퀄리티가 기대되는 작품입니다.

NDS로 나오면 좋지 말입니다.


네이버 카페 http://cafe.naver.com/anotherlore

tags : 게임
Trackbacks 0 : Comments 0

Write a comment


Win32API 자작게임 배포

프로젝트 2007. 4. 24. 00:36
친구와 함께 공동제작하기로 하고서 제작착수한 것이 1월 12일이었습니다.
이거 하나 만든다고 한 게 깨작깨작 거리다보니 3개월 걸렸네요.


허허 이것 참…….

너 뭐하는 놈이야?

아, 저기 저도 열심히 하고 싶었다구요.


ㅠㅠ

파일 첨부합니다. 실행하기 전에 동봉된 리드미 파일을 꼭 읽어보시기 바랍니다.
프로젝트는 계속됩니다! Peace!!

※ 다운로드 : shot.rar

혹시나 소스 필요하시면 메일로 연락주세요.


known bugs가 너무 많군요 ㅠㅠ

Trackbacks 0 : Comments 0

Write a comment


게임지와 정품부록, 게임시장

생각하다 2007. 4. 2. 21:14


초등학교 시절. 컴퓨터 게임에 푹 빠져있던 나는 우연찮은 계기로 게임지를 사서 모으게 되었다. 1998 년 8월호 PC CHAMP에서부터 시작해서 2003년까지 햇수로만 6년 정도를 꾸준히 게임지를 모았었다. (6 * 12 면 72권 정도, 실제로는 용돈 수급이 좋지 않아 건너뛴 달도 있어서 실제로는 60여 권 정도가 지금 책꽂이에 모셔져 있다.)

  초창기 게임지를 사던 이유는 뭐니뭐니해도 정품 번들 게임이었다. 처음 PC CHAMP를 구매하던 1998년 8월호에는 로드 오브 렐름 2 가 정품 번들로 제공되었고, 머지 않아 아미맨등의 인기 타이틀이 번들로 제공되었던 적이 있다. 이 정품번들이라는 게 당시 패키지를 구매할 만한 돈이 안되던 나로서는 정말이지쏠쏠한(?) 구매경로가 아닐 수 없었다. (물론 조금 철지난 게임들만 제공되었지만 말이다. 그리고 아쉽게도 소프트맥스의 게임은 절대 번들로 제공되지 않았었다.)

물론 번들에 혹해서 산 게임지지만 기사 역시도 꾸준하게 읽었다. 하드웨어 강좌나 TRPG, 게임계 뉴스 같은 코너는 상당히유익했고, Tip&Hacks(게임의 공략/치트키 등이 실리는 코너)는 매월호마다 스크랩까지 해놓을 정도로, 정말이지빼먹은 적이 없었다.

물론 구매를 결정짓는 것은 번들이 약 40%, 게임 기사가 20%, 애독자로서의 사명감(?) 40% 정도였다.
사실 몇 년 잡지를 구독하면서 정품 번들의 제공에 대해 당연하게 생각했던 것이 사실이다. 당시 잘 나가던 PC 게임 잡지들(PCPlayer, PC CHAMP, V챔프 등등)은 모두 정품 번들을 제공하고 있었고, 친구들은 어떤 타이틀이 번들로 제공되는 가를잡지 구매의 중요한 요소로 평가하고 있었다. 어쩌면 이때부터 속물근성에 눈을 뜬 건지도 모르겠다.

그러던 중, PC CHAMP에서 아미맨2가 국내 정식 발매와 동시에 번들로 제공되는 일이 있었다.상당히 신기한 일이었다. 보통 몇 달, 혹은 몇 년 정도 묵어서 잘 팔리지 않는 게임들을 제공하던 것이 번들이었는데 나온지일주일도 안된 게임을 끼워주다니, 뭐 나야 좋은 노릇이지만. (사실 이때쯤해서 게임지의 번들 제공 경쟁이 과열되었던 것으로기억한다.)

그리고 화이트 데이 번들. '국산 게임은 번들로 제공할 계획이 없다'라는 프로포설을 깨버리고 발매한지(비교적) 얼마 지나지 않은 국산 타이틀을 번들로 제공하는 사태를 맞고 나니. "이거 뭔가 좀 이상한데?" 하는 생각을 조금씩갖게 되었다.

본디 번들CD는 데모 버전, 동영상, 평가판 유틸리티, 세이브 파일 등을 끼워넣어 주는 것이관행이었다고 하던데. 언제부터인가 어느 잡지사에서 정품 게임을 번들로 제공하면서부터 치열한 정품 번들 경쟁이 시작되었다고하더라. 결국 이 피 튀기는 전쟁은 제 살을 깎아먹는 것으로 끝나고 만다. 수많은 게임잡지들이 폐간했고 그시절 잡지사들 중에서그나마 현재 명맥을 유지하고 있는 것은 PC Player 하나뿐이다. (그나마 이것도 잡지 두께가 꽤나 얇아졌더라, PCCHAMP = PC PowerZine은 NetPower에 통합되어버리고.)

정품 번들 경쟁은 결국 게임 잡지들의수준 저하를 유발하고, (솔직히 어느 시기부터였던지, 기사들의 수준이 부쩍 수준 미달로 치닫는 것을 느낄 수 있었다. 아마도2001년 전후였을 것이다.) 게임 잡지의 본질을 변질시켜 버렸다. 잡지를 위한 번들이 아닌 번들을 위한 잡지로 은연 중에바뀌어가고 있던 것이다.

초고속 통신망의 보급에 따라 게임을 더욱 쉽게 (그리고 저렴하고 파렴치하게) 구할 수 있는루트가 생기자 염가에 질 좋은 게임을 모토로 내세웠던 게임지(이미 이 시점에서 글러먹은 것)들은 하나 둘 씩 재정적 압박에시달리게 되고, 결국 폐간을 결정하고 만다.

게임지의 번들 제공은 결과적으로 게이머들의 소비 심리를 위축시키고, ( 게임 = 제 돈 쓰고 살 필요 없는 것 ) 게임지의 저널리즘으로의 가능성을 원천적으로 봉쇄해버렸으며, 올바른 비평을 수행할 미디어 저변 부족으로 국내 게임계의 일보후퇴를 불러오지 않았나 싶다. 작금의 사태 -공장제 판박이 같은 게임들이 쏟아져 나오는 사태- 역시 올바른 비평 문화나 게임 언론의 질타와 타박이 부족해서는 아닐까.

언뜻 책장의 낡은 잡지를 보고 고개를 끄덕여본다.

Trackbacks 0 : Comments 0

Write a comment


블록버스터 게임과 Independancy

생각하다 2007. 3. 29. 16:55

스페이스 워 (1962)

그 오래전 스페이스워(spacewar, 1962년 MIT공과대학)에서부터 지금의 WoW(2004, 블리자드 엔터테인먼트) 근 40여 년에 걸쳐 PC게임은 엄청난 변화를 겪어왔습니다. 기술적 혁신은 물론이며 게임 이론의 수립 및 대규모 제작 공정의 출현. 정말이지 하나의 산업 분야가 되어버렸지요.

사실 게임 개발은 엄청난 노동집약형 산업입니다. 코드 한 줄, 그래픽 리소스 하나 하나 심지어 미세한 효과음 하나 하나까지 사람 손을 거쳐야 하는 정말이지 사람들의 땀과 노력의 현장이라 할 수 있죠. 이 과정에서는 막대한 자금과 많은 사람들의 노동력이 소비됩니다. 하지만 이렇게 심혈을 기울여 만든 게임들이 모두 성공하는 것은 아니죠. 어떤 게임은 잊혀지고 또 어떤 게임은 출시 당일부터 여러 사람들의 입에 오르내리며 출세가도를 달리게 됩니다. 물론 만들어지는 게임의 대다수는 후자에 속해있습니다.

게임 산업이 노동집약형 산업이면서도 그 결과물로 창출할 수 있는 가치의 산정이 불분명한 특성이 있기 때문에, 이것은 흡사 영화 산업과도 유사해 보입니다. 영화계처럼 그들중에는 블록버스터 게임도 있고, 소수만이 즐기는 마이너 게임도 있죠. 그리고 블록버스터 게임들은 필시 제작과정에서부터 엄청난 규모의 인력, 자본이 투입됩니다. (물론 리니지, 뮤 등의 초기 온라인 블록버스터 게임들은 소규모 공정의 산물이라 볼 수 있겠지만, 현 시장의 판도는 그때와는 상당한 차이가 있지요.)

블록버스터 게임들은 블록버스터 영화와 마찬가지로 대규모의 자본이 투입됩니다. 개발인력(자본의 블랙홀)은 물론이며 대규모의 프로모션, 유저들을 끌어들이기 위한 다양한 마케팅 비용 등등. 어지간한 영화 한 편 만드는 비용 못지 않죠. 이렇게 기회비용이 커지게 되면서 출시되는 게임들은 다들 흥행을 위한 보증수표, 영화 산업에서는 유명 배우나 뻔한 스토리 등으로 통하게 되는 몇몇 클리셰(cliche)를 첨가하게 됩니다. (사실 이 클리셰가 요즘 게임들에선 너무 과하죠?) 익숙한 UI, 혹은 게임진행방식과 같은 형태의 것들 말이죠. 이런 것들은 유저들의 진입장벽을 완화하고, 사용자 증
가로 인한 안정적인 수익창출을 가능케합니다. 이것이 바로 '대안게임'의 이점입니다.

WoW

월드 오브 워크래프트 (2004)

그러나 그게 전부일 뿐. 결국 과도한 클리셰의 남용으로 인하여 모든 게임들은 서로의 개성을 잃어가고 맙니다. 대안게임은 대안게임에 충실해야지 다른 모습을 가졌다간 수익을 보장할 수 없을 테니까요. 결국 대안게임은 영리를 목적으로 한다는 그 오버그라운드적 특성때문에 자신의 목을 죄고 있는 것이나 다름이 없어요. 그렇기 때문에 수많은 게임들이 서로 엇비슷한 눈, 코, 입, 목소리를 가지게 되는 것이고 게임계에 발전이 없다는 소리가 나오는 것이겠지요.

하지만 솔직히, 그러니까 까놓고 말해서 진보와 혁명은 오버그라운드의 것이 아니죠. 자본의 물을 먹고 몸집이 비대해진 개발사들은 쉽사리 변혁을 시도할 수 없습니다. 시장의 개혁과 혁신이라면 모를까 시대의 개혁과 혁신은 젊은 층. 즉 언더그라운드에서 행해지는 것이 지금까지의 역사였습니다.

그렇다면 게임계의 언더그라운드. 그들은 지금 어디 있는 걸까요?

Trackbacks 0 : Comments 0

Write a comment