'정보 공유터'에 해당되는 글. 71건

  1. 2010/07/30 [C++0x] r-vaule reference: 파라미터의 const 속성 없애기!? (1)
  2. 2010/07/25 [C++] r-value vs. l-value (1)
  3. 2010/07/22 [Apache] 찾을 수 없습니다. (3)
  4. 2010/07/13 [C++] r-value Reference: Performance (2)
  5. 2010/05/27 [C++] 임의의 이름의 변수 만들기
  6. 2010/05/15 [C++] 지연 호출(Deferred Functional Call) 구현
  7. 2010/04/21 [C++] Visual Studio 2010, GCC 4.5.0 Released (2)
  8. 2010/03/31 [Tip] Chrome에서 사용하기 좋은 드래그 사전(DragDic) Bookmarklet (1)
  9. 2010/03/28 [C++] Google의 C++ 라이브러리 (2)
  10. 2010/03/24 [RSS] 네이버 Hot 뉴스 피드
  11. 2010/03/24 [RSS] 네이버캐스트 Feed (2)
  12. 2010/03/19 [VS] ProjectName도 창 제목 표시 해주기.
  13. 2010/03/07 [Tip] Customizing Windows Command Prompt (2)
  14. 2010/03/02 [Game] GameTech 2010 - TERA의 서버 구조 (1)
  15. 2010/02/16 한국 귀화시험 기출 문제... (1)
  16. 2010/02/16 [RSS] 네이버 캐스트 Feed (2)
  17. 2010/02/04 빌드(컴파일, 링크) 속도가 느리다면.... (3)
  18. 2010/01/22 [MySQL] NULL이지만 NULL이 아닌 슬픈 이야기.. (3)
  19. 2010/01/18 [Linux] 콜스택이 깨진 Core 파일 디버깅 하기 (5)
  20. 2009/12/22 [VS] 위대한 발견: Visual Studio 검색창 늘리기 (2)
  21. 2009/10/31 [Vim] 여러 파일 Tab으로 열기 (2)
  22. 2009/05/10 C# 4.0 - Dynamic Programming (2)
  23. 2009/05/07 [VS] Visual Studio 2008 SP1, Hotfix and Powertoys
  24. 2009/05/06 C++ Concurrent Container - Intel TBB.
  25. 2009/04/28 영어에서 시간과 시각 구분하기 (2)
  26. 2009/04/28 Boost.Intrusive - STL Container보다 빠른 Container (1)
  27. 2008/07/19 Windows Tip - 메시지 박스 내용 복사하기. (10)
  28. 2008/06/30 C++에서 const char** (2)
  29. 2008/06/05 [TIP] 티스토리에서 MP3 쉽게 다운 받기 (3)
  30. 2008/03/08 Internet Explorer 8에서 바뀐점 (8)

 C++ 표준 문서 N2798의 14.3.1의 4번째 항목을 보면. 위와 같은 내용이 있다.
 ( 더 최신 문서인 N3092 에는 위 항목이 빠져 있음. )

 해석을 해서 옮기고 싶지만..
 괜히 혼란만 가중 시킬것 같아서.. 패스하고..

  아무튼 자세히 보면.. 정말 해괴망측한 부분이 있는데
  그 부분을 조금 더 살펴 보자면... 아래와 같은 코드가 있다고 했을 때

    1 template<typename T>

    2 struct X

    3 {

    4     static void f(const T& t)

    5     {

    6         t.a = 100;

    7     }

    8 };

 
 함수 f()는 const로 받은 변수의 값을 변경하고 있다.
 얼핏 보아도 이상한 코드다.
 (  아직 template가 instantiation이 되지 않아서 이 부분만 가지고는 컴파일 에러가 나지 않는다.)


 코드를 조금 더 작성해 보면..

    9 struct S

   10 {

   11     int a;

   12 };

   13 

   14 int main(int argc, char* argv[])

   15 {

   16     S s;

   17     X<S>::f(s);

   18 


이제 아마 Line 17에서 readonly인 a에 값을 넣으려고 했다고 해서 컴파일 에러가 날 것이다.
근데 C++0x 부터는 이를 회피할 수 있는 아주 간단한 방법이 생겼다.
단순히 ' & ' 하나만 추가 하면 된다.


   16     S s;

   17     X<S&>::f(s);

   18 

   19     cout << s.a << endl;


 이제 함수 f()는 
 void X::f(S& t) 와 같이 파라미터의 타입이 정해지고, const 속성을 날려버리게 된다. 우왕ㅋ굳ㅋ
 ( 물론, 이렇게 만들어서 const 속성을 없애서 쓰자는 이야기는 절대 아님...)



 C++의 복잡도는.. 날이 갈 수록 올라가고 있다.


끝으로 Quiz..
각각 파라미터 타입은 어떻게 될까요? ( Line 11 ~ Line 29 )
참고로 gcc 4.5.0과 VS2010 에서 둘다 돌려봤는데. 같게 나왔습니다.

    1 template<typename T>

    2 struct R

    3 {

    4     static void A(T&){}

    5     static void B(const T&){}

    6     static void C(T&&){}

    7     static void D(const T&&){}

    8 };

    9 

   10 {

   11     R<int&>::A(?)

   12     R<int&>::B(?)

   13     R<int&>::C(?)

   14     R<int&>::D(?)

   15 

   16     R<const int&>::A(?)

   17     R<const int&>::B(?)

   18     R<const int&>::C(?)

   19     R<const int&>::D(?)

   20 

   21     R<int&&>::A(?)

   22     R<int&&>::B(?)

   23     R<int&&>::C(?)

   24     R<int&&>::D(?)

   25 

   26     R<const int&&>::A(?)

   27     R<const int&&>::B(?)

   28     R<const int&&>::C(?)

   29     R<const int&&>::D(?)

   30 }



Posted by U_Seung

{Quiz}. 다음 중 l-value는 몇 개일까요? (line 12 ~ line 29 중에서.. )


    1 int* pa = &a;

    2 const int* pb = &a;

    3 

    4 int fa() { return 1; }

    5 const int fb() { return 2; }

    6 

    7 int& fra() { return a; }

    8 const int& frb() { return b; }

    9 

   10 void main_rvalue()

   11 {

   12     RVALUE_CHECKER(1);

   13     RVALUE_CHECKER(int(1));

   14     RVALUE_CHECKER(new int(1));

   15     RVALUE_CHECKER(*(new int(1)));

   16 

   17     RVALUE_CHECKER(++a);

   18     RVALUE_CHECKER(a++);

   19     RVALUE_CHECKER(a + 1);

   20 

   21     RVALUE_CHECKER(++*pa);

   22     RVALUE_CHECKER(*pa++);

   23     RVALUE_CHECKER(*pa + 1);

   24 

   25     RVALUE_CHECKER(fa());

   26     RVALUE_CHECKER(fb());

   27 

   28     RVALUE_CHECKER(fra());

   29     RVALUE_CHECKER(frb());

   30 }



참고로...
#1.  l-value, r-value 구분은 expression에 대한 구분임 (type 이라던지 하는 건 관계가 없음.)
#2.  ++a (line 17) 은 l-value 이지만, a++ (line 18)은 rvalue임.


Posted by U_Seung

 Apache를 설치하고, 서비스를 시작하면.. 간혹 실행이 안되고 실패를 한다.
 특별한 메시지를 주는 것이 아니기 때문에.. 관리도구 - 이벤트 로그를 확인 하면..



 뭔가 알 수 없는 메시지를 준다.
 
 아무래도.. 알 수가 없어서.

 >>> \xc3\xa3\xc0\xbb \xbc\xf6 \xbe\xf8\xbd\xc0\xb4\xcf\xb4\xd9.

 여기에 단서가 있을까 해서.. 좀 살펴 보니..

 1. 한글이 깨진 것 같고,
 2. \x 가 붙은 것으로 봐서 바이너리 형태 같고,
 3. 세글자가 아닌 두 글자로 쪼개지며, 대충 범위 대역이 EUC-KR 같아서..

  바꿔 보기로 했다. 

  gvim을 이용해서 아래 처럼 입력하고..
  도구(T) - 원래대로 변환(r) 을 누르면..
  xxd 프로그램으로 Binary로 바꿔 준다.



 결국, 이 메시지 만으로는 문제를 '찾을 수 없다는 것'을 알게 되었다.
 장난 하냐? 응?



Posted by U_Seung

r-value reference 쓸려고 테스트를 해봤습니다.


#. 일단 임의의 문자열(string) N개를 vector에 넣고..

    1     static const size_t N = 100000;

    2     static const size_t MaxLen = 100;

    3     static const char range[] = "abcdefghijklmnopqrstuvwxyz_0123456789";

    4 

    5     struct rnd_gen

    6     {

    7         char operator()() const

    8         {

    9             return range[std::rand() % (_countof(range) - 1)];

   10         }

   11     };

   12 

   13     std::vector<std::string> v(N);

   14     for(int i=0; i<N; ++i)

   15     {

   16         std::generate_n(

   17             std::back_inserter(v[i]),

   18             std::rand() % MaxLen + 1, rnd_gen());

   19     }



#. Sorting 해보고

   20     {

   21         boost::timer t;

   22         std::sort(v.begin(), v.end());

   23         std::cout << "Sort: " << t.elapsed() << std::endl;

   24     }



#. Join 해봤습니다.

   25     {

   26         boost::timer t;

   27         std::string result = boost::algorithm::join(v, ",");

   28         std::cout << "Join: " << t.elapsed() << std::endl;

   29     }




-[ VS 2008 ]--------------
Sort: 0.178
Join: 0.104

-[ VS 2010 ]--------------
Sort: 0.079
Join: 0.029


 C++0x 이전에는 위 처럼 코딩 하지 말라고 했겠죠..
 사실 부자연 스러울 것이 없는 코드인데..
 하지 말라고 하는게 안타까운 상황이었습니다..ㅋ




Posted by U_Seung

C++로 프로그래밍을 하다보면 딱히 변수 이름이 중요하지 않을 때가 많이 있습니다.
주로 생성자 혹은 파괴자를 이용한 RAII 패턴을 사용하는 상황이 그렇습니다.


임의의 변수명은 Macro를 이용하여 구현합니다.

 

#include <boost/preprocessor/cat.hpp>

#define RANDOM_NAME BOOST_PP_CAT(_random_, __COUNTER__)

 


선언은 위와 같이 하고
대략적인 사용은 아래와 같이 합니다.

 

namespace NS

{

    bool Func(Arg* arg)

    {

        SomeGuard<Arg> RANDOM_NAME(arg);

 

        (...)

    }

 

    static Initialization RANDOM_NAME;

}

 



이렇게 만들어진 변수 명은 '해당 변수를 생성자와 파괴자의 동작만 사용하겠다' 라고 명시적으로 지정하는 역할도 담당하게 됩니다. 변수 명을 알 수가 없으니까 강제로 다른 용도로 사용하려고 해도 할 수가 없겠지요.



Posted by U_Seung

제가 구독하는 블로그 중에
rein님의 C++0x를 써서 Closure 다시 만들기와 C++기반의 closure를 보고
제가 쓰고 있던 방법도 공개 합니다.


사용할 수 있는 곳은 여러 곳이 있겠습니다만..
다른 곳으로 Message를 Passing 한다던가 Timer를 쓴다던가 할 때
유용하게 쓸 수 있겠습니다.




typedef
function<void (void)> Closure;


C++0x가 지원되면 std.function을 써도 되고
그렇지 않으면 boost.function을 쓰면 됩니다.




void
freef(int a, int b)

{

    cout << a << " + " << b << " = " << a+b << endl;

}

 

struct Class

{

    Class(int a): a_(a) {}

 

    void memf(int b)

    {

        cout << a_ << " - " << b << " = " << a_-b << endl;

    }

 

    int a_;

};

 

vector<Closure> closures;

{

    int a = 10;

    closures.push_back(bind(freef, a, 4));

    closures.push_back(bind(&Class::memf, new Class(a), 2));

//  closures.push_back([=](){ cout << a << endl; });

}

 

foreach(Closure& closure, closures)

{

    closure();

}



마찬가지로 std.bind 나 boost.bind를 사용하고,
C++0x가 지원되면 lambda를 추가적으로 사용할 수 있습니다.




Posted by U_Seung


 둘다 깔아서 써보고 있는데 괜찮네요 :)

 이제 tr1뿐만 아니라.
 auto, decltype, lambda, strongly typed enum, Rvalue references 등등의 
 C++0x의 훌륭한 Feature 들을 양쪽에서 사용할 수 있게 되었습니다.

 저런 것들은 Boost 등과 같은 Library 만으로 커버가 안되는 것들이라서 더 의미가 깊다 할 수 있겠습니다.



 이건 g++ 4.5.0 인증샷.

#1.  Local Class를 template parameter로 넘길 수 있게 되었습니다.

#2. -flto 옵션이 컴파일, 링크에 추가 되었습니다. 

#3. c++0x feature 중에 하나인 lambda 가 가능해졌습니다.









Posted by U_Seung
TAG C++, gcc

DragDicN: 네이버 사전

DragDicD: 다음 사전

DragDicY: 야후 사전



 만든지 정말 오래된 것이지만..
 Chrome이 IE보다는 크롬을 더 많이 쓰기 시작한 시점에서 더욱 유용해졌습니다.
 그래서 Chrome에 더 잘 맞도록 수정했습니다. (추가 버튼 색상을.... )

 사용법은...
 1. Boomarklet을 Browser에 등록 합니다.
 2. 사전에 찾아 보고 싶은 단어를 마우스로 Drag합니다. (옵션)
 3. 설치한 북마클릿(Bookmarklet)을 클릭 합니다.





 4. 그럼 아래와 같은 창이 뜹니다.



 5. 단어 뜻을 봤으면 .. 창을 닫아 버리면 됩니다. (옵션)




Posted by U_Seung

C++ 관련 자료를 찾다 보면 
Google에서 공개한 자료를 많이 접할 수 있게 됩니다.

뭐 사실 C++의 Library야 찾아보면 다른 Library도 많습니다만...
Google의 자료들은 몇가지 공통적으로 기본빵을 해주는게 몇 가지 있는데..
 - 오픈소스라서 소스레벨의 접근이 가능합니다.
 - 라이선스가 BSD/MIT 입니다. 즉 GPL이 아니라서 라이선스 제약이 상대적으로 덜 합니다.
 - 멀티 플랫폼을 지원합니다. (Windows/Linux은 기본으로 됩니다.)
 - 마지막으로 Google이라는 거대 회사에서 직접 적용해본 도입 사례가 있습니다.


제가 찾은 Google의 자료를 공유 합니다. 이밖에 좋은 자료가 있으시면 공유 부탁드립니다.


#. Google Test & Google Mock
 - Google Test: Google C++ Testing Framework
 - Google Mock: Google C++ Mocking Framework

   C++의 xUnit 도구들이 상당히 많은데.. 사용하다보면 뭔가 하나씩 부족한 느낌이 듭니다.
  그 중에서 제일 덜 부족한 느낌이 드는게 Google Test가 아닌가 싶습니다.







#. Google Performance Tools
 - Google Perftools: Fast, multi-threaded malloc() and nifty performance analysis tools

   멀티쓰레드에서 더욱 좋은 성능을 내는 TCMalloc(Thread-Caching Malloc), CPU Profiler를 제공 합니다. TCMalloc에는 HeapProfiler와 HeapChecker포함되어 있습니다. 하지만, Windows 쪽은 지원이 미약하며 다른 좋은 것들도 많기 때문에 Linux에서 쓰기에 적합하다고 할 수 있겠습니다.







#. Google Log
 - Google glog: Logging library for C++

   glog는 Application Level Logging을 할 때 쓰는 Library입니다. 서버 Application을 만든다면 반드시 어떠한 방식으로든 로깅 기능을 사용할텐데 참조가 될만한 Library입니다. 직접 써도 좋을 것 같다는 생각도 들고요.

  인상적인 부분중에 하나는 google::InstallFailureSignalHandler() 함수 하나만 호출하면.. SIGSEGV 등을 받으면 아래와 같이 Logging을 하게 해준다고 합니다. 매우 편할 것 같습니다. 

*** SIGSEGV (@0x0) received by PID 17711 (TID 0x7f893090a6f0) from PID 0; stack trace: *** PC: @ 0x412eb1 TestWaitingLogSink::send() @ 0x7f892fb417d0 (unknown) @ 0x412eb1 TestWaitingLogSink::send() @ 0x7f89304f7f06 google::LogMessage::SendToLog() @ 0x7f89304f35af google::LogMessage::Flush() @ 0x7f89304f3739 google::LogMessage::~LogMessage() @ 0x408cf4 TestLogSinkWaitTillSent() @ 0x4115de main @ 0x7f892f7ef1c4 (unknown) @ 0x4046f9 (unknown)







#. Google Sparse Hash
 - Google Sparse Hash: An extremely memory-efficient hash_map implementation

 긴 설명 보다는 아래 테스트 결과가 많은 것을 말해줄 수 있을 것 같습니다.

Average over 10000000 iterations
Wed Dec  8 14:56:38 PST 2004

SPARSE_HASH_MAP:
map_grow                  665 ns
map_predict/grow          303 ns
map_replace               177 ns
map_fetch                 117 ns
map_remove                192 ns
memory used in map_grow    84.3956 Mbytes

DENSE_HASH_MAP:
map_grow                   84 ns
map_predict/grow           22 ns
map_replace                18 ns
map_fetch                  13 ns
map_remove                 23 ns
memory used in map_grow   256.0000 Mbytes

STANDARD HASH_MAP:
map_grow                  162 ns
map_predict/grow          107 ns
map_replace                44 ns
map_fetch                  22 ns
map_remove                124 ns
memory used in map_grow   204.1643 Mbytes

STANDARD MAP:
map_grow                  297 ns
map_predict/grow          282 ns
map_replace               113 ns
map_fetch                 113 ns
map_remove                238 ns
memory used in map_grow   236.8081 Mbytes






#. Google CoreDumper
 - Google CoreDumper: A neat tool for creating GDB readable coredumps from multithreaded applications

  Runtime에 원하는 시점의 Memory를 Dump할 수 있는 기능입니다.
  ASSERT를 걸어야할 시점이 Runtime에서 한참 작업을 진행중이라면 Core만 떠두고, 일단 작업을 진행하도록 한 다음에 나중에 수정하여 업데이트 하는 방법이 있겠습니다.
 (당연히도) Linux만 지원됩니다.







#. 그 밖에..
 - gflags: Commandline flags module for C++
 - Keyczar: Toolkit for safe and simple cryptography
 - Breakpad: An open-source multi-platform crash reporting system
 - Omaha: Software installer and auto-updater for Windows
 - Protocol Buffers: Google's data interchange format

그리고 꼭 읽어보길 권장하는...
Posted by U_Seung
Posted by U_Seung

네이버캐스트 :: 교양 경제학RSS

네이버캐스트 :: 옛날신문RSS

네이버캐스트 :: 오늘의 문학RSS

네이버캐스트 :: 오늘의 클래식RSS

네이버캐스트 :: 지구촌 산책RSS

네이버캐스트 :: 철학의 숲RSS

네이버캐스트 :: 키친 스페셜RSS

네이버캐스트 :: 포토 스페셜RSS

Posted by U_Seung


 S/W 개발을 하다 보면... 프로젝트들이 하나 둘 추가 되고
 그러다보면 Visual Studio 창은 온갖 창들로 복잡해 집니다.

 저 같은 경우에는 파일 이름을 정하는 것이 힘들어서 프로젝트는 다르지만 같은 이름의 파일을 많이 만들게 됩니다. 그러다 보면 이게 어느 파일인지 창만 보고는 분간이 힘들어지고, 작업이 불편하다고 느끼게 되었습니다.



 그래서 찾아낸 해결 책이 Tabs Studio Add-in 입니다.
 Tabs Studio에 보면 여러 기능이 있는데 그 중에서 창 제목을 바꿀 수 있는 기능을 제공 합니다.
 이를 이용 해서 창 제목에 [$(ProjectName)] $(FileName) 가 되도록 만들었습니다.
 ( Tabs Studio에서는 Add-in안의 Add-in 기능을 제공하는데.. 제작자가 샘플로 공개한 Disambiguator를 조금 고쳐서 만들었습니다. )

 이렇게 쓰고 나서 부터는 작업 효율이 좀 나아진 느낌입니다. :)



Posted by U_Seung


#1. Prompt 설정.

PROMPT=$P$G$_$$

계속 사용하고 싶으면..
환경 변수에 등록해주면 됩니다.

몇 가지 포인트가 있는데..
$_는 한 줄을 바꿀 때 씁니다.
마지막에 Space 를 넣어 주는 것이 보기 편합니다.

편의에 따라서 %USERNAME%, %COMPUTERNAME% 등을 넣어 줄 수도 있지만
Remote로 접속하는 경우가 적기 때문에 필요 없는 경우가 많습니다.

 

#2. 폰트 변경.


Fixed Width 폰트를 지정할 수 있습니다.
한글은 굴림체, 돋움체, 나눔고딕 코딩 등을 지정할 수 있습니다.
원하는 폰트가 목록에 나오게 하기 위해서는
Registry의 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont 에 추가하시면 됩니다.

영문폰트를 사용하고 싶으시면 Codepage를 바꿔야 합니다.
chcp 명령어를 사용하거나
Registry의 HKEY_CURRENT_USER\Console의 하위를 직접 세팅 해서 바꾸면 됩니다.

Posted by U_Seung

지난 주에 GameTech 2010에 다녀 왔습니다.
정말 오랜만에 세미나를 들으러 갔던 것 같습니다.

GameTech 2010 공식 홈페이지: http://gametech.gamespot.co.kr/

여러가지 세션을 들었지만 가장 인상 깊었던 블루홀 스튜디오의 세션에 대해서만 몇자 남깁니다.

일단 TERA의 서버 구조는 매우 간단합니다.
  • 한 Planet(Wow의 Relm)당 수용인원은 대략 5000명 정도 예상.
  • 한 Planet에는 하나의 Arbiter 서버를 Front-end로 둠.
  • 한 Arbiter 서버에는 여러개의 World서버를 Back-end로 둠.
    • TERA에서는 Planet간에도 유저가 만날 수 있는 통합전장이라는 시스템이 있으므로,
      특정 World서버에서는 여러개의 Arbiter 서버와 연결을 가질 수 있음.
이게 끝입니다.
(물론, 로그인과 같은 인증관련 부분은 생략 되었습니다. 한게임에서 처리하니 필요 없을 것 같기도 합니다.)

정말 간단합니다.
그렇기 때문에 역할 구분도 매우 명확합니다.

[Arbiter 서버]
  • 주로 I/O를 담당.
  • Network 통신에 해당하는 Non-Blocking I/O와 Database 작업에 해당하는 Blocking I/O를 담당.
    (내부적으로는 위의 두가지 방식의 Thread Pool을 분리 한다고 함.)
  • 채팅, 길드 등의 게임 로직을 담당

[World 서버]
  • 주로 (CPU작업이 많은) 게임로직을 담당.
  • Blocking I/O만을 처리하며 모든 Thread가 대등한 역할을 수행.
  • 대부분의 게임 로직을 처리하며, 통합 전장/Instance Dungeon 기능도 가짐.

----

여기까지는 발표 내용이고, 제 개인적인 생각을 몇 자 적어보자면...
발표 초반에 액션성을 강조한 게임이라고 TERA의 특징을 소개하였으나
설명을 들을 수록 액션성이 잘 표현되는 CPU와 I/O를 많이 쓰는 곳에 적합한 구조라는 생각은 안 들었습니다.

지금 구조에서는 Arbiter 서버 프로세스 하나에서 대부분의 I/O가 일어 나는데
I/O쪽 부하가 지나치게 집중 되도록 되어 있으며,
안정성 측면에서도 Arbiter 서버 이거 다운되면 어떻게 하나 걱정부터 많이 들었습니다.

물론, 서버 기능별로 채팅서버, 파티서버, 몬스터서버 이렇게 한 없이 분리하다보면
복잡도가 올라가서 결국 서버의 안정성이 떨어진다는 것을 부정하긴 힘들지만
아무리 그래도 프로세스 하나에서 Network I/O, 채팅/길드, DB 까지 다하는 것은 좀 지나치다는 생각이 듭니다. ( 물론, 블로홀 스튜디오에는 국내 최고 수준의 막강 QA 인력이 포진하고 있다고 합니다... )

뭐 이런 저런 우려와 걱정이 되긴 하였지만..
가슴 속에서는 'Arbiter 서버와 World 서버만 있다고? 이거 만들기 엄청 편하겠는데 +_+)/.... '


끝으로 강연자 분이 했던 말씀중에 인상 깊었던 말이 있었는데...
정확히 문구까지는 기억이 나지는 않지만 대략 아래와 같은 말이었습니다.

서버 구조는 해당 게임의 특징에 따라서 다르겠지만 그것과 더불어서 해당 게임을 만드는 팀에 따라서 달라져야 합니다. 지금 만들고 있는 서버 구조는 현재 팀의 구성에 따라서 정한 것입니다. 만약 현재 팀 구성이 아니었다면 다른 모델을 도전 해볼 수도 있었을 것 같습니다.




Posted by U_Seung





Posted by U_Seung

네이버에서는 좋은 정보를 참 많이 제공 해주고 있습니다.
구워진지(Burned) 얼마 되지 않은 Feed.



네이버캐스트 :: 매일의 디자인: RSS, EMAIL

네이버캐스트 :: 아름다운 한국: RSS, EMAIL

네이버캐스트 :: 오늘의 과학: RSS, EMAIL

네이버캐스트 :: 오늘의 미술: RSS, EMAIL

네이버캐스트 :: 오늘의 집: RSS, EMAIL

네이버캐스트 :: 오늘의 체조: RSS, EMAIL

네이버캐스트 :: 인물과 역사: RSS, EMAIL



Posted by U_Seung

 컴파일 속도가 느리다면.. IncrediBuild를 쓰세요.




 링크 속도가 느리다면.
 일단 64비트 OS를 설치하고,
 RAM을 넉넉하게 늘리세요.   ( 4G 이상, 6G 이상 추천 )



 RAM 업그레이드 이후에 체감 링크 속도가 2~3배 빨라졌습니다.

------------------------------------

 OS를 Windows 7 x64로 업그레이드 했더니 빌드 속도가 더 빨라 졌습니다.
 Windows 7 에서 멀티코어 지원이 강화 된 영향 같습니다.





Posted by U_Seung
TAG C++

 일단 어떤 테이블에 varbinary(123) 타입을 가진 컬럼이 하나 있었습니다.

mysql> DESC SomeTable col1;
+-------+----------------+------+-----+---------+-------+
| Field | Type           | Null | Key | Default | Extra |
+-------+----------------+------+-----+---------+-------+
| col1  | varbinary(123) | YES  |     | NULL    |       |
+-------+----------------+------+-----+---------+-------+
1 row in set (0.00 sec)


 이 컬럼에는 NULL이 들어 있었습니다.

mysql> SELECT col1 FROM SomTable LIMIT 0, 10 ;
+------+
| col1 |
+------+
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
+------+
10 rows in set (0.00 sec)


 Stored Procedure를 통해서 여러개의 테이블에서 여러개의 컬럼을 읽는 프로그램이었는데... 디버깅 끝에 이 부분부터 꼬이기 시작한다는 것을 발견했습니다.
 그리고 희한하게도 이 컬럼을 읽는 부분에서 NULL이 아닌 값을 읽고 있는 것을 발견했습니다.




 그리고... 확인결과 ... 진짜 NULL이 아님을 알았고

mysql> SELECT col1 FROM SomeTable WHERE col1 IS NULL LIMIT 0, 10 ;
Empty set (0.00 sec)

 



 비극의 진실은...

mysql> SELECT col1 FROM SomeTable WHERE col1 = "NULL" LIMIT 0, 10 ;
+------+
| col1 |
+------+
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
+------+
10 rows in set (0.00 sec)



.......... oTL

 한 가지 고려해볼 수 있는 사항은
 Binary 컬럼은 SELECT시에 *(asterisk)를 쓰지 않고, HEX(col1) 처럼 HEX() 함수로 감싸도록 (마음속으로.. ) 강제 하는 방법.
 


Posted by U_Seung

 Linux에서 Daemon을 돌리다 보면 버그로 인해서 프로그램이 Crash 되는 일이 종종 있습니다.
 당연히 문제가 되는 부분 찾아서 고쳐야 합니다.

 그럴때 대부분 사용하는 방법이 Process가 죽기전에 기록을 Core파일에 남기도록 설정 하는 방법 입니다.
 정상적으로 남겨진 Core파일 경우라면 디버깅 하는게 큰 문제는 없을 테지만
 아래와 같이 콜스택이 깨져 보이는 난감한 상황을 만들어 내기도 합니다.

Loaded symbols for /lib/tls/librt.so.1

Reading symbols from /usr/lib/libggauth2.so.56...done.

Loaded symbols for /usr/lib/libggauth2.so.56

#0  0x02d10100 in ?? ()

(gdb) bt

#0  0x02d10100 in ?? ()

#1  0x01010000 in ?? ()

#2  0x000002d2 in ?? ()



 콜스택이 깨져 보이는 경우는 주로 Stack Buffer Overrun 으로 인한 문제 입니다.
 (다른 문제는 이 글에서 다루지 않습니다.)
 이 경우, 스택에 있던 Return Address가 지워져 있기 때문에 GDB는 콜스택을 표시하지 못합니다.

 하지만 이런 경우라고 해서 너무 낙심할 것은 아닙니다.
 Stack Buffer가 조금 넘친 경우에는 남은 정보를 이용해서 문제를 해결 할 수 있기 때문입니다.

 이때, 실마리를 제공해주는 것은 Register의 ESP 입니다.
 비록 원하던 Return Adress는 지워졌지만 ESP는 값은 정상적인 값을 유지하고 있습니다.
 이제 ESP가 가르키던 메모리 주변을 뒤져서 Return Address와 유사한 값들이 있는지 찾아보면 문제에 대한 힌트를 얻을 수 있습니다.

 일단 Return Address랑 유사한 녀석들은 어떤 녀석이어야 하는지 파악 해야 합니다.
 당연히 Return Address는 실행가능한 Instruction 들이 저장되어 있는 Code Segment를 가르키고 있습니다. GDB에서는 maint info sections .text 명령어를 통해서 Code Segment를 찾아 볼 수 있습니다.

(gdb) maint info sections .text

Exec file:

    `/home/aa/bb.debug.1f25cf3be302bd7308d598c132ac904b', file type elf32-i386.

    0x08051e20->0x0824fc08 at 0x00009e20: .text ALLOC LOAD READONLY CODE HAS_CONTENTS

Core file:

    `/home/aa/core.1214458224.bb.30678', file type elf32-i386.



 이제 Code Segment의 범위도 구했으니 ESP를 기준으로 주변 탐색해서 Return Address와 유사한 녀석들을 찾아 본다면 아마 콜스택과 유사한 모양이 만들어 질 수 있을 겁니다.

 이를 위해서 간단한 User-defined Command를 만들었습니다.

define findsymbols
set $textbegin = $arg0
set $textend = $arg1
set $si = $arg2
set $ei = $arg3
while $si < $ei
set $value = *(int*)$si
if ($textbegin <= $value && $value <= $textend)
printf "[0x%08x] ", $si
info symbol $value
end
set $si = $si + sizeof(void*)
end
end

 가독성이 다소 떨어지긴 하지만 동작은 간단합니다.
 주어진 범위를 탐색하면서 정해진 범위의 값(Code Segment의 범위)이 들어오면..
 해당 값을 info symbol 을 이용해서 출력하는 Command 입니다.



 실제로 사용하면 아래와 같은 결과를 얻을 수 있습니다. (함수 이름은 가명..)

(gdb) findsymbols 0x08051e20 0x0824fc08 $esp-1024 $esp+1024

[..] IoHandler::SendPacket(char const*, unsigned int, bool) + 786 in section .text

[..] IoHandler::UniCast(char const*, unsigned int) + 26 in section .text

[..] Remote::PartyCast(Party*, char const*, unsigned int) + 141 in section .text

[..] Dispatcher::Do(Task*, TaskMsg*) + 795 in section .text

[..] Task::ExtractTaskMsg(TaskMsg*) + 953 in section .text

[..] Task::svc() + 510 in section .text



콜스택(?)을 얻었으니 ESP값과 비교 등을 통해서 어느 지점에서 Crash되었는 지를 파악할 수 있을 것입니다. 아마 있어야 하는 함수 1~2개가 누락되어서 보이는 경우가 대부분 일테고요. 어떤 함수가 버퍼를 넘치게 했는지 찾아내면 됩니다.

좀 더 정확한 원인을 얻어 보기 위해서는 GDB의 x 명령어 등을 이용해서 ESP 주변 메모리를 잘 뒤져보면 답을 찾을 수 있습니다. 하지만 이 정도 까지 얻었다면 소스를 보고 문제의 원인을 먼저 찾고 문제점이 맞는지 검증하는 편이 더 빠를 수 있습니다.

그럼 즐거운 디버깅 되세요 :)


Posted by U_Seung


 그림의 오른쪽 아래 동그라미 쳐진 곳을 주목하면 된다.
 저 상자가 늘어난다는 것..

 매일 쓰던 툴에서 발견한 신선함 이랄까;;;


Posted by U_Seung

 일단 회사에 보면 대부분이 U모 Editor를 사용하고 있다.
 훌륭한 프로그램이라고 생각하지만 그냥 안 쓰다보니 설치도 안했다.

 나는 주로 Windows에서도 Vim을 쓰는데..
 다른 사람들에 비해서 여러개의 파일을 다루는 것이 불편하다는 것을 알게 되었다.




 그래서 위와 같이 Vim의 Tabs 기능으로 자주 쓰는 파일을 열어야 생각이 들었다.
 일단 생각하고나니 문제가 간단해졌다.

CD F:\TT\
gvim -p *.xml

 자주 쓰는 파일 목록을 따로 저장해서 열어주는 방식도 있겠지만..
 난 이 정도로 충분했다.

 두 개의 바로가기를 만들었는데
 하나는 *.xml을 읽어 주고, 하는 *.ini를 읽어 준다.

 이제는 다른 사람보다 편해졌다. :)


----
(추가)

Vim 기본설정에서 tabpage 개수는 10개로 제한되어 있다.
이를 늘리려면

set tpm=20


Posted by U_Seung

 C# 4.0에 대한 윤곽이 나왔었습니다.
 요즘은 C++에 집중하느라고 다른 Language들을 잘 보지 않고 있었는데.. 알고보니 지금 포스팅 하기엔 민망한 소식이기도 합니다.

 C# 4.0에 대한 소개를 보니.. 정말 매력적인 Feature들이 추가되었습니다.
 C# 3.0 때 추가된 Type inference, Lambda expressions, LINQ 등도 꽤나 신선했었는데..
 C# 4.0에 추가된 dynamic keyword나 COM 객체에 사용성 향상 같은 대한 지원은 당장이라도 테스트 어플리케이션을 만들고 싶고, 기존 코드를 고치고 싶게 합니다.


 저기 동영상 중에서 Anders Hejlsberg 아저씨의 PDC 2008에서의 발표는 정말 볼만합니다.
 C# 언어 설계자가 새로 설계한 부분에 대해서 직접 발표를 하다보니 아무래도 흥미롭습니다..


 동영상의 일부분을 보면...


 C# 언어의 발전 과정입니다.
 이제 만든지 10년이 넘었다져..




 C# 4.0의 Language 자체에서 지원되는 변화입니다.
 해당 키워드들에 C#을 붙여서 구글링을 하면 자세한 정보를 얻을 수 있습니다.
 - Dynamically Typed Objects
 - Optional and Named Parameters
 - Improved COM Interoperability
 - Co- and Contra-variance





 C# 4.0 이후에 Compiler를 약간 오픈해서 Meta-Programming에 대한 지원도 강화할 것이라고 합니다.



 데모로 만든 C# Interactive Shell을 보여주는데..
 Winform으로 Windows 하나를 띄우고,
 거기에 Background Image를 입히고,
 Button UI을 추가하고,
 Button을 누르면 Console에 "Hello world" 를 출력하는 이벤트 핸들러를 추가 합니다.

 좀 찾아보니 Mono 2.2에선 이 기능이 추가된 것 같네요.



Posted by U_Seung

 - 주로 Multi-threading 프로그래밍을 할 때, 문제가 되는 bug들이 많이 fix 되었단다.
 - 사소하 버그지만 아래 Disable된 Breakpoints가 보이지 않던 버그도 수정 되었다.



 - Close All But This는 있는데 Close All이 없었다.
 - 창을 실수도 닫았는데.. 방금 닫은 창을 다시 열고 싶다.
 - 해당 소스코드가 있는 폴더를 cmd 로 열고 싶다.
 - 등등등..



Posted by U_Seung


기본적으로 STL Container들은 Thread Safety하지 않다.
뭐 구현에 따라 다를 수 있지만..

서로 다른 Thread에서 Writing을 하거나
한 Thread에서 Writing을 하는 도중에 다른 Thread에서 Reading을 할 경우,
문제가 발생할 수 있다. (많은 경우, 프로그램이 Crash됨.)

관련 문서들은 아래를 참조..
- [Dinkumware] Thread Safety

---------------------------------------------------------------------------------

따라서, Multi-threading 환경에서 STL Container를 사용하기 위해서는 주의가 필요하다.
한 Thread에서 특정 Container object에 Writing operation을 하기 위해서는 (특히, 삽입/삭제)
다른 Thread에서는 해당 Container object에 reading이나 writing을 하지 않도록 locking을 해주어야 한다.

뭐 복잡하게 설명할 것 없이, 
Intel에서는 Concurrency한 Template Library를 제공한다.

해당 Library에는 여러가지 기능이 제공되지만, 가장 관심이 가는 것 중 하나로
High concurrency & Thread-safe(인텔 측에 따르면)한 Container가 아닐까 싶다.

High concurrency라고 한 이유는, 걍 적당히 Operation 위 아래에다가 Lock/Unlock을 한게 아니라 Lock-free algorithmFine-grained locking을 사용했다는 것인데 실제로 이렇게 구현하는 것은 몹시 까다로운 방법이다. 

intel TBB에서는 아래와 같은 총 3개의 Container가 제공 된다.


사용 예는 기회가 되면 공유하기로 하고,
문서 중 흥미로운 사항을 몇 가지 이야기를 적어 보면..

[concurrent_vector] 
 - Operations on concurrent_vector are concurrency safe with respect to growing, not for 
clearing or destroying a vector. Never invoke method clear() if there are other 
operations in flight on the concurrent_vector.

 = concurrent_vector의 경우, dynamic하게 growing하는 부분에서는 thread-safe하나 벡터의 clearing이나 destroying 부분에서는 thread-safe하지 않단다. clear()나 파괴자 등이 실행 중일 때, 다른 오퍼레이션도 일어난다면 해당 변수에 대한 Logic적인 부분도 고려 해봐야하지 않을까 싶다.

[concurrent_queue]
- Queues are widely used in parallel programs to buffer consumers from producers. Before 
using an explicit queue, however, consider using parallel_while or pipeline instead. These options are often more efficient than queues for the following reasons: 
•  A queue is inherently a bottle neck, because it must maintain first-in first-out order.  
•  A thread that is popping a value may have to wait idly until the value is pushed.  
•  A queue is a passive data structure. If a thread pushes a value, it could take time until 
it pops the value, and in the meantime the value (and whatever it references) 
becomes “cold” in cache. Or worse yet, another thread pops the value, and the value 
(and whatever it references) must be moved to the other processor. 

 = 뭐 복잡하게 설명하고 있지만, Queue의 FIFO 특성 자체가 순서가 강요되기 때문에.. 효율적이지 않는다는 부분이다. Queue를 꼭 사용해야하는지 고려해보고, 굳이 사용하지 않아도 된다면 다른 방법을 사용하길 권장하고 있다. 


Posted by U_Seung

 우리나라 말에서 
 시간(時間)과 시각(時刻)은 다른 개념이다.

 그럼 영어에서는 어떻게 구분을 해야할까?
 사실 내가 관심 있는 부분은 영어라는 것은 큰 의미는 없고, 
 코드에서 변수명/함수명을 작명시 어떻게 구분하는 게 좋을까에 대한 것이다.

 예전부터 고민했던 부분인데
 한 가지 괜찮은 대안을 Boost.Date_Time Library 문서에서 찾을 수 있었다.

-----

Domain Concepts

The date time domain is rich in terminology and problems. The following is a brief introduction to the concepts you will find reflected in the library.

The library supports 3 basic temporal types:

  • Time Point -- Specifier for a location in the time continuum.
  • Time Duration -- A length of time unattached to any point on the time continuum.
  • Time Interval -- A duration of time attached to a specific point in the time continuum. Also known as a time period.
-----

 요약 하면
 시각: Time Point 
 시간: Time Duration
 시간 구간: Time Interval or Time Period

 여기서 시간 구간이라는 의미는 특정 시각 두 개의 값으로 이루어진 시간을 의미한다.
 즉, 10분이라는 것은 시간(Time Duration) 이고,
 23시 00분 ~ 23시 10분은 시간 구간(Time Interval) 이다.

 약간 응용하면 <Time Interval>는 <Time Point>와 <Time Duration>의 조합으로 만들 수 있다.


 오버해서 더 나아가면.. (수학에서) 구간 이라는 것은 
 개구간(Unbounded Interval)과 폐구간(Bounded Interval)이 있다.

 [1, 10]은 Endpoints인 1과 10을 포함한다는 것 이고 (폐구간)
 (1, 10)은 Endpoints인 1과 10을 포함하지 않는 다는 것이다. (개구간)

 참고로, Boost.Date_Time 라이브러리에서 구간(Interval)은..  [Begin, End) 로 사용한다.





 
Posted by U_Seung

 제목이 약간 자극적이다. (사실, 방식 자체가 다르기 때문에 동등한 조건에서 비교하는 것은 좀 그렇다.)

 Boost.Intrusive는 Boost Library의 Container중 하나로, Performance를 높이는 방법으로 사용할 수 있다.

 Boost.Intrusive에서 제공되는 Container의 종류는 아래과 같음.
 - Singly Linked List
 - Circularly Linked List (like std::list)
 - set/multiset/rbtree
 - avl_set/avl_multiset/avltree
 - splay_set/splay_multiset/splaytree
 - sg_set/sg_multiset/sgtree
 - unordered_set/unordered_multiset

 먼저 Intrusive Container와 Non-intrusive Container의 차이점에 대해서 알아야 한다.

 쉽게 설명하면.. 기존에 우리가 쓰는 Container들은 보통 Non-intrusive Container라고 생각하면 된다.
 Linked List를 한번이라도 구현해보거나 구조에 대해서 생각해 본 사람이라면 알겠지만.

 대략 Linked List는 아래와 같이 생겼다.

    1 class SomeValue

    2 {

    3     //.. some members ..///

    4     int asdf;

    5 };

    6 

    7 template <typename T>

    8 class List<T>

    9 {

   10     class list_node

   11     {

   12        list_node *next;

   13        list_node *previous;

   14        T value;

   15     };

   16 

   17     //....

   18 };

   19 

   20 List<SomeValue> list;


 여기서 14번째 줄처럼 Non-Intrusive Container는 Value값을 복사해서 가지게 되어 있다.
 
 하지만 Intrusive Container의 Linked List는 아래와 같이 구현한다.

    1 class SomeValue

    2 {

    3     // intrusive members.

    4     SomeValue *previous;

    5     SomeValue *next;

    6 

    7     //.. some members ..///

    8     int asdf;

    9 };

   10 

   11 template <typename T>

   12 class List<T>

   13 {

   14     //....

   15 };

   16 

   17 List<SomeValue> list;


 4번째, 5번째 줄처럼 기존에 Value 구조체에 Linked List에 필요한 구조체를 포함 시키는 게 핵심이다.


 따라서, 메모리 관리는 Container 외부에서 담당하게 되는 것이고
 Container 관리를 위한 메모리를 따로 할당 하지 않기 때문에 Performance 향상을 볼 수 있다.
 아래는 비교표.

Issue

Intrusive

Non-intrusive

Memory management

External

Internal through allocator

Insertion/Erasure time

Faster

Slower

Memory locality

Better

Worse

Can hold non-copyable and non-movable objects by value

Yes

No

Exception guarantees

Better

Worse

Computation of iterator from value

Constant

Non-constant

Insertion/erasure predictability

High

Low

Memory use

Minimal

More than minimal

Insert objects by value retaining polymorphic behavior

Yes

No (slicing)

User must modify the definition of the values to insert

Yes

No

Containers are copyable

No

Yes

Inserted object's lifetime managed by

User (more complex)

Container (less complex)

Container invariants can be broken without using the container

Easier

Harder (only with containers of pointers)

Thread-safety analysis

Harder

Easier



 내가 제일 마음에 드는 부분은..
 메모리 관리를 외부에서 할 수 있다는 점과 Memory Locality가 향상 된다는 점이 아닐까 싶다.

 이를 잘 활용하면 불필요하게 Heap을 사용하는 것을 줄일 수 있다.


 개발의 편의성 보다는 성능(!!)에 초점이 맞추어진 프로젝트가 있다면 써보길 추천..


 아.. 실제 Boost.Intrusive를 쓰는 코드는 아래와 같이 생겼다.

    1 

    2 struct SomeStruct

    3 {

    4     int i;

    5     char someBuffer[1024];

    6 

    7     SomeStruct()

    8     {

    9     }

   10 };

   11 

   12 struct SomeStructI

   13     : public boost::intrusive::slist_base_hook<>

   14     , public SomeStruct

   15 {

   16 };

   17 

   18 slist<SomeStructI, cache_last<true> > ptrContainer;

   19 

   20 BOOST_FOREACH(SomeStructI& someStruct, ptrContainer)

   21 {

   22     // ...

   23 }



 그다지 못 생긴 것도 아니다.




Posted by U_Seung

메시지 박스 내용 복사하기..
 
사용자 삽입 이미지

 가끔씩 이렇게 조금 길고 짜증나는 메시지가 나올 때가 있습니다.
 메시지가 이상해서 구글에 한번 쳐보고 싶은데 메시지도 긴데가가 복사가 잘 안되서..
 여간 불편할때가 많습니다.
 치명적인 상황은 어떻게 쳐야될지 모르는 문자가 있을 때죠 -_-;

 암튼.. 메시지 박스에 Focus를 두고, Ctrl+C를 누르면 메시지 박스가 복사 됩니다.
 위의 메시지 박스라면 메모장에 붙여 넣으면 아래와 같이 나옵니다. (XP 기준)

---------------------------
Microsoft Internet Explorer
---------------------------
자다가일어나서 일어나다가 넘어져서 에러가 발생했는데.. 다시 잘래? 말래?
---------------------------
확인   취소  
---------------------------

 너무 간단한데
 메시지 박스에 대고 Ctrl+C를 눌렀을 때, 진짜 복사가 되리라고 생각하긴 힘든 것 같습니다.

 Vista에서도 됩니다.
 모양은 조금 다르다고 하네요.




Posted by U_Seung

EC++ 에 보면 const에 대한 설명이 잠깐 나온다.

설명을 보면..

1. char* a;
2. const char* a;
3. char* const a;
4. const char* const a;

위의 넷이 다른 타입이라는 것을 설명하고 있다.

그렇다면.. 간혹 볼 수 있는 const char** 는  어떤 타입일까?

5. const (const char*)*
6. const (char *)*
7. (const char*)*


일단 5,6,7 중의 하나라고 생각할 수 있겠다.
5,6,7의 차이는 어떤 곳에 const의 속성이 붙느냐에 따라서 명확히 다른 type이다.

그렇다면....
- const char**은 5,6,7 중 어떤 타입일까?
- 셋 중에 하나라면 다른 두 가지는 어떻게 표현해야 할까?

이런 의문점이 생기게 만드는 const char** 표현은 그다지 바람직한 모양은 아닌 것 같다.

일단 정답은 7번
const char**는 (const char*)* 이다.
사용법은 아래와 같다.

char* pc = new char[20];
const char* cpc = new char[20];

const char** cppc;
cppc = &pc; // (X) error: invalid conversion from 'char**' to 'const char**'
cppc = &cpc;
*cppc = pc;
*cppc = cpc;
**cppc = '1'; // (X) error: you cannot assign to a variable that is const

 char** ppc = cppc; // (X) error: invalid conversion from 'const char**' to 'char**'


유의 깊게 볼 점은..
char** 와 const char** 은 상호 conversion이 안 된다는 점인데
char*는 const char*로 conversion이 된다는 점에서 차이가 있음을 알고 있을 필요가 있다.



그렇다면 5, 6번의 타입을 만들고 싶다면 어떻게 해야 할까?
방법 중 하나는 typedef를 쓰면 된다.

typedef char* PCHAR;
typedef const char* CPCHAR;

const PCHAR* a;
const CPCHAR* a;




 

Posted by U_Seung
TAG C++, char**, const, CPP

 Tistory에 음악을 올려두고, MP3를 듣게 해 놓으신 분들이 많습니다.

 결국 MP3 파일이 Tistory에 저장되서 유저가 받게 되어 있는 것인데 해당 URL만 알면 다운 받을 수 있습니다.
 해당 MP3의 URL를 찾는 가장 간단 방법은.. 브라우저의 Javascript혹은 JScript를 끄고, 해당 페이지를 띄우면 MP3의 URL을 아실 수 있습니다.

 이게 가능한 이유는 .. Tistory의 음악 플레이어 Script에 Script가 없는 브라우저를 위한 코드가 있기 때문입니다. 그러니까 IE나 FF를 가지고, Script가 없는 브라우저 인척 해서, 다운 받으면 됩니다.
 
사용자 삽입 이미지


 Javascript를 끄는 방법은..
사용자 삽입 이미지



FF나 IE에 따라서 위와 같이 하시면 됩니다.
FF가 설정 바꾸기 편하긴 한데, Drag했을 때, Copy가 안되는 버그가 있는 것 같군요;;



Posted by U_Seung

사용자 삽입 이미지


앞에 적었던 Internet Explorer 8에서 사용후기에 이어서 IE8에서 바뀐 점에 대해서 포스팅 합니다. IE에서 바뀐점은..  What's New in Internet Explorer 8 에 잘 정리되어 있는데 여기 나온 내용 중 관심 가는 몇가지를 소개합니다.

사실 웹을 기반으로 개발을 하게되면, 브라우저 특히 IE가 새롭게 런칭 될때마다 긴장을 하게될 수 밖에 없습니다. 웹이 플랫폼이라고 하지만, 사실 브라우저가 플랫폼이란 사실을 새삼 느끼게 된다고나 할까요.. :)



ActiveX Improvements

  • Per-site ActiveX

    많은 ActiveX Control들이 하나의 사이트에만 동작함에도 불구하고, site-locking 기술을 사용하지 않아서 ActiveX Control들이 본래의 저작의도와 다르게 다른 사이트에서 악용될 위협을 가지고 있다고 합니다. IE8에서는 ActiveX를 허용하는 동작은 Site단위로 지정하도록 하는 기능을 추가 되었습니다. (아래 그림에서 보면 Run Add-on과 Run Add-on on All Websites가 분리되어 있습니다.)

사용자 삽입 이미지

  • Non-administrator installation

    관리자 권한을 가지지 않는 표준사용자들은 그 동안 ActiveX Controls를 설치할 수 없었습니다. (UAC등을 통해 관리자로 권한상승을 하지 않는다면) IE8에서는 표준 사용자도 자신의 권한으로 ActiveX Controls를 설치할 수 있도록 하는 기능이 추가 되었습니다. 표준 사용자 권한으로 설치된 ActiveX Controls는 자신의 Profile에 한하여 영향을 미치며, 이로인하여 System 전체가 파괴되는 일은 없다고 합니다.




Activities and WebSlices

  • Activities는 브라우저 확장기능 입니다. 사용자가 특정 영역을 선택하면 해당 영역의 정보를 인식하여서 다른 서비스와 연결해주는 것을 해줍니다. 예를 들어서 주소가 들어간 곳을 마우스로 드래그하면 Google Maps와 바로 연결을 해준다던지 하는 브라우저 확장 기능입니다. 이는 사실 Windows Live Toolbar에 있던 Smart Menu를 브라우저에 기본적으로 포함시킨 정도라고 생각할 수 있겠습니다. (그림 참조)

    사용자 삽입 이미지


  • WebSlice는 Favories Bar(즐겨찾기 바)라고 하는 곳에 표시되며, RSS와  유사하게 웹페이지의 컨텐츠가 업데이트 되면 업데이트가 되었음을 알려 줍니다. 왜 RSS라는 표준적인 기술을 쓰지 않고, 새로운 형태를 만들었는지 논란의 여지가 있을 수 있겠지만, RSS와 약간 다른 성격이라고 하면은 RSS는 배포(Syndication)와 구독(Subscription)의 개념이라면..  WebSlice는 웹사이트의 특정 영역(Slice)가 변화를 확인 하는 정도의 개념이라고나 할까요. (RSS처럼 바뀌었다고해서 새롭게 읽어야할 것 같은 압박은 없는 듯.)

    아무튼 WebSlice를 제 블로그에도 한번 만들어 보았습니다. IE8을 설치하시고 메인 페이지에 들어 가신 다음에 마우스를 대면 아래와 같은 그림이 나옵니다. ( 아직 메인 화면이 아닌 곳에서도 나온다는 문제가 있습니다.)

    사용자 삽입 이미지

    여기에서 보라색 버튼을 눌면 Favorites Bar에 추가할 수 있습니다.
    추가된 화면은 아래와 같습니다.

    사용자 삽입 이미지

    WebSlice.. 말 그대로 Web의 특정 영역을 잘라서 보여준다는 느낌 입니다.




AJAX Enhancements

  • AJAX Navigation — 클라이언트에서 응답이 얼마간 없을때의 시점은 hash에 저장할수 있는데 이것을 기반으로해서 AJAX Application에서도 Back버튼이 가능하도록 되었습니다.

  • Connection Events — 브라우저에서 Connection이 끊어질 때, 이벤트를 받을 수 있게 되었습니다. 따라서 안정성이 중요한 프로그램에서는 이를 이용해서 데이터가 중간에 날라가 버린다 하거나 하는 일을 방지할 수 있게 되었습니다.

  • Cross-domain Request (XDR) — 원래 XMLHTTPRequest가 Cross-domain 접근이 되지 않습니다. 이로 인한 개발의 제약사항이 많았었는데 IE8에서는 XDomainRequest object를 통해서 제한된 통신이 가능하다고 합니다.

  • Cross-document messaging — postMessage 를 이용하면 서로 다른 도메인 간에  문서를 안전하게 교환할 수 있다고 합니다. 주로 Frame으로 제작된 곳에서 많이 쓰일 수 있겠습니다.

좀 더 자세한 정보를 보실려면:





Developer Tools

Firefox에는 Firebug라는 좋은 디버깅 툴이 있었느나 IE디버깅을 위해서는 Visual Studio/IE Developer Toolbar/Windows Script Debugger를 써야하는 불편함이 있었습니다. 이번에 IE8에서는 위와 같은 관련 도구가 합쳐진 형태를 기본적으로 IE에 포함시킬 예정인가 봅니다. 또한 Developer Tools에서는 Version Mode Switching을 제공하여서 IE의 Rendering방식을 고를 수 있도록 하였습니다. (아래 그림 참조)

사용자 삽입 이미지

좀 더 자세한 정보를 보실려면:





Document Compatibility Mode

IE는 Quirks모드, IE7 Strict모드, IE8 Standards모드의 세가지 렌더링 모드(Layout Mode)를 지원합니다. 이를 Developer Tools를 통해서 강제로 지정할 수도 있지만 일반적인 페이지는 !DOCTYPE를 기반으로 어떤 모드로 렌더링을 할지 결정하게 됩니다.

렌더링 모드가 결정되는 조건은 아래 표와 같습니다.

Page Content Declaration

Layout Mode

Known standards DOCTYPEs and unknown DOCTYPEs IE8 Standards
Quirks mode DOCTYPEs (includes the absence of a DOCTYPE) Quirks

하지만 웹 사이트 제작자가 DOCTYPE을 유지한 상황에서 강제로 렌더링 모드를 선택하는 방식도 제공합니다. (아래 코드 참조)

<meta http-equiv="X-UA-Compatible" content="IE=7" />
여기에 관한 좀 더 자세한 정보는 Defining Document Compatibility를 참조 하세요.




DOM Storage

요즘 AJAX기반으로 하는 Application은 덩치가 상당 합니다. 이렇게 되면 데이터를 메모리에 저장하는 방식에서 상당한 애로사항이 생기는데 이를 해결하기 위해서 기존에는 쿠기/DOM/Flash 등의 갖은 편법을 동원해서 작업해야 했습니다. 그래서 HTML5 Draft에서는 sessionStorage와 globalStorage등의 개념이 생기게 되고, 이 것중에 이부분이 IE8에서는 구현되었다고 합니다.

자세한 사항은.. Introduction to DOM Storage를 참조 하시면 좋을 것 같습니다.




HTML Improvements

HTML 4.01구현에서 몇 가지 부분이 다른 브라우저와 통일성을 위해 변경 되었습니다.
주요 사항은 아래와 같다고 하네요.

  • The object tag image fallback is interoperable with other browsers. For example, an object tag without dimensions is now the same size of the image rather than zero by zero pixels.
  • The button element submits its value attribute instead of its innerHTML. This means you can use the button element for cross-browser FORM scenarios.
  • The getElementById method is now case-sensitive, and it no longer incorrectly searches using the NAME attribute.
  • The setAttribute method is now case-insensitive; you do not need to use "camel case" to specify attributes. It also correctly identifies HTML attributes such as CLASS and FOR.




Selectors API

DOM을 선택할 때, CSS Selector 방식을 사용하면 쉽게 원하는 DOM을 선택할 수 있습니다. 이러한 방식은 PrototypeJS 등의 Javascript Framework에서 기본적으로 제공해주는 기능입니다. IE8에서는 이 기능을 브라우저단에서 제공해주니 Javascript Library단에서 제공하는 것과 비교하여 훨씬 빠른 성능을 낸다고 합니다. ( 예제 코드 참조)

  var oAllPs = document.querySelectorAll("div.detail");
var oLimit = document.querySelector("#second");
var oAllPs = document.querySelectorAll("div, span");



Tab Isolation and Concurrency

IE에서는 브라우저 프레임이 탭들과 "loosely coupled" 되었다고 합니다. 따라서  안전모드가 아니라고 해서 IE7에서 새창을 띄우던 것이 없어졌고, 하나의 탭에서 문제가 되었다고 해서 브라우져 전체가 죽어버리는 어처구니 없는 일은 없어졌다고 합니다. IE8에서 가장 좋아진 부분중에 하나인 것 같습니다.






결론적으로 보면..
IE6에서 IE7으로의 변화처럼 대대적인 변화는 없지만
내부적인 성능 개선과 상호 운영성(Interoperability), 웹 개발 지원이 많이 이루어진다고 볼 수 있겠습니다.

갑자기 Mix08 키노트에서 Web Developer을 연신 외쳐대던 Steve Ballmer 아저씨가 떠오르는 군요.


Posted by U_Seung