• 2012-10-11

    C++11

    C++에 손을 뗀지 어언 3년, 그동안 C++0x이니 C++11 같은 게 정말 좋아졌다고 하긴 하는데, 한눈에 알아볼 수 있는 한글 사이트가 없기에 한번 정리해봤다. 위키피디아 문서를 기준으로 요약, 번역한 것이니 틀린 점이 있으면 너그럽게 지적해주기 바란다.

    아래 샘플 코드들을 Xcode 4.5에서 Apple LLVM 4.1--std=c++11, --stdlib=libc++ 옵션으로 테스트 했음을 밝힌다.

    요약

    C++ 11 의 언어 레벨에서의 개선 사항은 대충 다음과 같이 요약할 수 있다.

    키워드 설명
    && rvalue 참조 연산자
    auto 컴파일러가 유추해낼 수 있는 자동 타입. any 와는 다르다.
    char16_t, char_32_t UTF-16 과 UTF-32 타입과 리터럴 선언
    constexpr 이름 그대로 상수 + 식
    decltype 변수 이름으로 타입을 알아내어서 선언 가능
    noexcept 어떤 함수가 예외를 던지는지의 여부를 지정
    nullptr NULL 포인터 상수
    static_assert assert 의 정적 버전
    thread_local 쓰레드 로컬 저장소를 사용하는 변수 지정자
    using type aliasing
    override 가상 함수의 상속 여부 지정
    alignas, alignof 구조체나 클래스의 메모리 정렬 단위를 지정
    final 가상 함수나 클래스의 상속 불가능 여부 지정

    표준 라이브러리 역시 많이 개선되었다. 그 중에서 핵심적인 부분들을 살펴보면,

    클래스/함수 설명
    std::initializer_list 초기화 리스트
    std::thread, future, promise, async 쓰레드 관련 클래스들
    std::function 함수 객체
    std::regex 정규식
    std::unordered_map O(1) 짜리 해시맵
    std::tuple 튜플
    std::forward_list 단방향 리스트
    std::array 배열
    std::atomic lockless 연산을 위한 클래스

    rvalue 참조 연산자 &&

    class A {
        char* buf;
        int size;
        // move constructor
        A(A&& a): buf(a.buf), size(a.size) { a.buf=0; a.size=0; }
    };
    

    주로 임시 객체가 만들어질 때 불필요한 메모리 할당이나 버퍼 복사로 인한 성능 저하를 막기 위해, 파라미터의 내부값 전체를 이동시켜 버리는 용도다. 많은 STL 컨테이너들이 성능을 위해서 이런 이동 생성자(move constructor)와 이동 대입연산자(move assignment operator)을 구현했다는데, 평범한 개발자가 쓸 일은 드물 듯.

    더 많은 내용은 MSDN 참조.

    constexpr

    constexpr int get_five() {return 5;}
    int some_value[get_five() + 7];
    

    constexpr을 붙이면 일반 변수나 함수도 컴파일 타임 상수로 쓸 수 있다. 단 함수일 경우 내부에 리턴문만 있어야 한다.

    템플릿의 Extern 선언

    extern template class std::vector<MyClass>;
    

    이제 특수화된 템플릿 클래스의 extern 선언이 가능해졌다. 단 한 군데에서만 컴파일하게 되므로 컴파일 시간도 빨라졌다.

    리스트 초기화

    class SequenceClass {
    public:
        SequenceClass(std::initializer_list<int> list);
    };
    SequenceClass some_var = {1, 4, 5, 6};
    
    void function_name(std::initializer_list<float> list);
    function_name({1.0f, -3.45f, -0.4f});
    
    std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
    
    struct AltStruct {
        AltStruct(int x, double y) : x_{x}, y_{y} {}
    
    private:
        int x_;
        double y_;
    };
    
    AltStruct var2{2, 4.3};
    

    새롭게 추가된 initializer_list를 이용하면, 리스트로 객체를 초기화하거나 파라미터로도 넘길 수 있고, 생성자를 대체할 수도 있다. 맨 마지막 문법은 좀 손가락이 꼬이는 느낌.

    auto 와 decltype

    auto some_type = boost::bind(&some_function, _2, _1, some_object);
    decltype(some_type) other_type = some_type;
    

    템플릿 메타 프로그래밍에서는 리턴값을 알기 힘든 경우가 많은데, 이때 auto로 변수를 선언하면 컴파일러가 자동으로 타입을 찾아준다. decltype은 변수만으로도 타입을 추론해낼 수 있다.

    덕분에, iterator를 사용하는 for 루프는 정말 간단해질 수 있다.

    for (std::vector<int>::const_iterator itr = myvec.cbegin(); itr != myvec.cend(); ++itr)
    
    for (auto itr = myvec.cbegin(); itr != myvec.cend(); ++itr)
    

    auto 를 리턴하는 함수의 경우, -> 를 이용해서 타입을 컴파일러에게 친절하게 알려줄 수 있다.

    struct SomeStruct  {
        auto func_name(int x, int y) -> int;
    };
    
    auto SomeStruct::func_name(int x, int y) -> int {
        return x + y;
    }
    

    범위 기반 for 루프

    int my_array[5] = {1, 2, 3, 4, 5};
    for (int &x : my_array) {
        x *= 2;
    }
    

    배열, 초기화 리스트, begin/end가 정의된 컨테이너 등 컴파일러가 범위를 알 수 있을 듯한 컬렉션들에 한해서만 가능하다. in 연산자를 지원해주면 참 좋겠지만...

    람다식과 람다 함수

    [](int x, int y) { return x + y; }
    

    함수명에 []을 쓰면, 람다 함수로 사용할 수 있다. 리턴값은 자동적으로 추론된다고 한다.

    생성자 관련 개선

    class SomeType  {
        int number;
        int value = 5;
    public:
        SomeType(int new_number) : number(new_number) {}
        SomeType() : SomeType(42) {}
    };
    

    생성자에서 다른 생성자를 호출할 수 있게 되었고, 데이터 멤버도 클래스 선언시에 초기값을 가질 수 있다.

    override & final

    struct Base {
        virtual void some_func(float);
    };
    
    struct Derived : Base {
        virtual void some_func(int) override; // ill-formed because it doesn't override a base class method
    };
    
    struct Base1 final { };
    struct Base2 {
        virtual void f() final;
    };
    

    c# 이나 자바 같은 언어에서 오래전부터 지원하던 override 와 final 지정자가 드디어 표준이 되었다. final 은 클래스에 대해서도 사용 가능하다.

    널 포인터 상수 nullptr

    char *pc = nullptr;     // OK
    int  *pi = nullptr;     // OK
    bool   b = nullptr;     // OK. b is false.
    int    i = nullptr;     // error
    
    foo(nullptr);           // calls foo(char *), not foo(int);
    

    NULL 이 0 과 혼용되면서 생긴 문제 때문에, 포인터에 대한 전용 상수인 nullptr이 추가되었다.

    열거자의 타입 지정

    enum class Enum2 : unsigned int {Val1, Val2};
    

    예전 열거자는 컴파일러 구현에 따라서 int 도 되고, unsigned int 도 되었다. 새 열거자 선언 방식에서는 기본적으로 int이고, 별도로 타입을 지정할 수도 있지만, 정수로 암묵적으로 변환되지는 않는다.

    using

    template <typename First, typename Second, int Third>
    class SomeType;
    
    template <typename Second>
    using TypedefName = SomeType<OtherType, Second, 5>;
    
    typedef void (*Type)(double);       // Old style
    using OtherType = void (*)(double);     // New introduced syntax
    

    매크로나 typdef 대신 using 을 이용해서 긴 템플릿 이름을 짧게 줄일 수 있다.

    가변 갯수 템플릿 인자

    template<typename... Arguments>
    void SampleFunction(Arguments... parameters);
    
    SampleFunction<int, int>(16, 24);
    

    세상에나, 템플릿 인자도 가변적으로 받을 수 있구나. 여기 참조.

    union 개선

    #include <new> // Required for placement 'new'.
    //
    struct Point {
        Point() {}
        Point(int x, int y): x_(x), y_(y) {}
        int x_, y_;
    };
    //
    union U {
        int z;
        double w;
        Point p; // Illegal in C++03; legal in C++11.
        //
        // Due to the Point member, a constructor definition is now required.
        //
        U() {new(&p) Point();}
    };
    

    union 에 non-trivial 생성자를 가진 클래스를 담을 수 없던 제약이 풀렸다. 근데 이런 거 쓰는 사람이 있나.

    유니코드 문자열 선언

    const char* a = u8"I'm a UTF-8 string.";
    const char16_t* b = u"This is a UTF-16 string.";
    const char32_t* c = U"This is a UTF-32 string.";
    

    이제, utf-8 문자열을 하드코딩할 수 있다.

    const char* d = R"(The String Data \ Stuff " )";
    const char* e = u8R"XXX(I'm a "raw UTF-8" string.)XXX";
    const char16_t* f = uR"*(This is a "raw UTF-16" string.)*";
    const char32_t* g = UR"(This is a "raw UTF-32" string.)";
    

    정규식을 위한 raw 문자열도 추가되었다. 단, R 만 붙이는게 아니라 따옴표와 괄호까지가 필수적이라서, 첫번째 괄호와 마지막 괄호 내부의 문자열 escape 되지 않게 된다.

    멤버 함수 삭제

    struct NonCopyable {
        NonCopyable & operator=(const NonCopyable&) = delete;
        NonCopyable(const NonCopyable&) = delete;
        NonCopyable() = default;
    };
    

    컴파일러가 자동으로 만들어주던 기본 생성자와 복사 생성자, 기본 소멸자 및 대입 연산자에 대해서 명시적으로 default 또는 deleted 를 지정할 수 있게 되었다. 물론 일반 멤버 함수에 대해서도 가능하다.

    컴파일 시간 assertions

    static_assert((GREEKPI > 3.14) && (GREEKPI < 3.15), "GREEKPI is inaccurate!");
    
    template<class T>
    struct Check  {
        static_assert(sizeof(int) <= sizeof(T), "T is not big enough!");
    };
    

    된다!

    sizeof 개선

    struct SomeType { OtherType member; };
    
    sizeof(SomeType::member); //Does not work with C++03. Okay with C++11
    

    데이터 멤버에 대한 sizeof 가 가능해졌다.

    동적 메모리 관리(Garbage Collection)

    컴파일러에 따라 동적 메모리를 자동으로 관리할 수 있게 되었다. 물론 수동으로 관리하는 방법도 제공한다.

    쓰레드 관련

    std::thread 클래스가 지원되고 다음과 같은 쓰레드간 동기화 프리미티브들이 포함되었다.

    • std::mutex
    • std::recursive_mutex
    • std::condition_variable
    • std::condition_variable_any
    • std::lock_guard
    • std::unique_lock
    std::atomic<bool> ready(false);
    std::atomic<int> data(0);
    
    // Thread 0:
    data.store(1, std::memory_order_release);
    ready.store(true, std::memory_order_release);
    
    // Thread 1:
    if (ready.load(std::memory_order_acquire))
        assert(data.load(std::memory_order_acquire) == 1);
    

    보다 가벼운 원자적 연산(atomic operation)도 드디어 표준으로 채택되었다. 윈도우의 InterlockedIncrement() 류라고 보면 된다. 메모리 정렬은 좀 헷갈리니 여기를 참조.

    std::packaged_task<int()> task([](){ return 7; }); // wrap the function
    std::future<int> f1 = task.get_future();  // get a future
    std::thread(std::move(task)).detach(); // launch on a thread
    f1.wait();
    std::cout << f1.get() << std::endl;
    

    std::packaged_task를 이용하면, 비동기로 함수를 실행하고, 그 결과가 끝날 때까지 대기할 수 있다.

    std::future<int> f2 = std::async(std::launch::async, [](){ return 8; });
    f2.wait();
    std::cout << f2.get() << std::endl;
    

    std::async 역시 future 를 리턴하지만, 자동으로 쓰레드를 만들고 함수를 실행해준다.

    튜플

    typedef std::tuple <int, double, long &, const char *> test_tuple;
    long lengthy = 12;
    test_tuple proof (18, 6.5, lengthy, "Ciao!");
    
    lengthy = std::get<0>(proof);  // Assign to 'lengthy' the value 18.
    std::get<3>(proof) = " Beautiful!";  // Modify the tuple’s fourth element.
    

    가변 인자 템플릿 덕분에 튜플의 인자 갯수 제한이 풀렸다.

    unordered 해시 테이블

    기존의 map 과 set 은 정렬된 트리를 사용하므로 검색에 O(log N)이 걸리지만, unordered 는 메모리를 좀 더 쓰는 대신 O(1)로 요소를 찾을 수 있다.

    Type of hash table Associated values Equivalent keys
    std::unordered_set no no
    std::unordered_multiset no yes
    std::unordered_map yes no
    std::unordered_multimap yes yes

    정규식

    std::regex rgx(R"([ ,.\t\n;:])");
    std::cmatch match;
    if( std::regex_search( "Unseen University - Ankh-Morpork", match, rgx ) ) {
        for( size_t a = 0; a < match.size(); a++ ) {
            std::string str( match[a].first, match[a].second );
            std::cout << str << "\n";
        }
    }
    

    C++ 에서 정규식이 된다니 감개가 무량하다...

    스마트 포인터

    std::auto_ptr은 사라지고, std::unique_ptr, std::shared_ptr 그리고 and std::weak_ptr이 표준에 합류했다.

    ref

    void func (int &r)  { r++; }
    template<class F, class P> void g (F f, P t)  { f(t); }
    
    int i = 0 ;
    g (func, i) ;
    std::cout << i << std::endl;  // Output -> 0
    
    g (func, std::ref(i));
    std::cout << i << std::endl;  // Output -> 1
    

    임의의 객체의 레퍼런스를 얻어내는 refcref가 추가되었다.

    std::function

    struct Foo {
        Foo(int num) : num_(num) {}
        void print_add(int i) const { std::cout << num_+i << '\n'; }
        int num_;
    };
    
    void print_num(int i)
    {
        std::cout << i << '\n';
    }
    
    std::function<void(int)> f1 = print_num;
    std::function<void()> f2 = []() { print_num(42); };
    std::function<void()> f3 = std::bind(print_num, 31337);
    std::function<void(const Foo&, int)> f4 = &Foo::print_add;
    Foo foo(314159);
    f4(foo, 1);
    

    함수 객체는 일반적인 함수 포인터 뿐만 아니라, 람다 함수, 멤버 함수, bind식까지 담을 수 있다.

    기타

    • 템플릿 선언할 때 일부러 > > 띄워쓰지 않아도 컴파일러가 잘 처리해준다.
    • 변환 연산자(conversion operator)에도 explicit 를 붙일 수 있다.
    • thread_local 지시를 붙이면 쓰레드 로컬 변수를 선언할 수 있다.
  • 2012-09-16

    DropPress

    DropPress는 이번에 다 죽어있던 블로그를 개편하면서 만든 정적 사이트 생성 스크립트다.

    왜 이름이 DropPress 이냐면, 이 프로젝트의 시작은 드랍박스를 연동하는 웹서비스였기 때문이다. 드랍박스에 마크다운 포맷의 글을 저장해두면, 버전관리를 안해도 되고, 드랍박스와 연동되는 훌륭한 편집기가 널려 있으니, 나는 마크다운 변환과 github 배포를 구현하기만 하면 된다고 생각했다. 그런데, 비슷한 웹 에디터나 호스팅 서비스도 이미 존재하길래, 목표를 간단한 스크립트로 바꿨다. :)

    소스코드는 github에 공개되어 있다.

    기능 소개

    웬만한 블로그에 있는 기본적인 기능(이라고 하면 부끄럽지만)은 대충 다 구현했다.

    • 페이지 네비게이션, 아카이브, 카테고리, 태그, RSS, 최근 글목록
    • disqus 기반의 코멘트
    • google analytics 연동
    • 글 제목 검색
    • 쉘 명령 지원: Octopress처럼 init, generate, clean, deploy, new_post 같은 쉘 명령을 지원한다. new_post 의 경우 새 파일을 만든 후 서브라임 텍스트2에 띄워준다. 원래는 Makefile을 쓰려다가 파일 갯수를 줄인다는(?) 취지에서 그냥 파이썬으로 모두 구현해 버렸다.
    • wordpress 변환기

    구현

    파이썬 스크립트 자체는 몇 줄 안되는데도 봐줄만하게 나온 이유는 트위터 부트스트랩 덕분이다. 이런 라이브러리가 전업이 아니라 주말 작업만으로 나왔다니, 진짜 대단한 친구들이다.

    octopress에서 영감을 많이 받아서 글 헤더의 포맷이나 형태, 구조, 쉘 명령 등을 많이 참조했다. 얘들이 업데이트만 자주 했더라도 내가 안만들었을텐데..

    라이브러리 적용
    twitter bootstrap HTML 레이아웃 및 웹 디자인. 페이지 곳곳마다 진짜 열심히 사용했다.
    bootstwatch 부트스트랩의 무료 테마. 현재 readable 테마를 사용중이다.
    python-markdown 마크다운 변환. 테이블을 지원하는 플러그인도 존재한다. :)
    jinja2 파이썬용 HTML 템플릿 라이브러리
    yaml 설정 파일 및 글의 헤더 포맷
    feedgenerator atom.xml 생성용
    google-code-prettifier 자바스크립트 코드 하일라이팅
    locally 테스트용 로컬 웹서버(node.js 필요)

    향후 계획

    위에서도 밝혔지만 이제 블로그 생성기로서의 웬만한 기능은 이미 다 구현했고, 뭔가를 더 추가한다면

    • 더 많은 설치 및 배포 테스트: 아직 제대로 안해봤다.
    • 트위터 위젯 연동
    • ACE 에디터로 드랍박스 API연동해서 웹 편집하기
    • 최종적으로는 웹 서비스 기반의 배포 시스템

    정도가 남은 셈이다. 근데 과연 거기까지 갈지가 의문이다.

    그나저나, 실컷 끝내고 나니 왠지 바퀴만 재발명한 거 같은 생각이 든다. 좀 더 컨텐츠에 집중해야 되는데..

  • 2012-08-05

    Asrock P67 Extreme4 Gen3 에 산사자 설치하기

    며칠간의 삽질 끝에 집에 있는 데스크탑에 산사자를 설치했다. 이놈의 사양은

    • M/B: Asrock P67 Extreme4 Gen3
    • Audio: Onboard ALC892
    • Lan: Onboard Realtek Gigabit Ethernet
    • VGA: NVidia Geforce GTX 560 Ti
    • RAM: 8G

    이다. 요즘 대세인 tonymacx86의 Unibeast를 사용하면 아주 간단하게 설치할 수 있다. 까먹을까봐 정리해본다.

    1. Unibeast 1.5.2에 정품 산사자를 설치. Legacy USB 옵션은 지정하지 않았다.
    2. 기본적인 Unibeast 바이오스 설정(ACPI 등)만 해서 설치를 하니, 인스톨러 화면도 못보고 그냥 리붓되었다. 이 경우 CPU Configuration - No-Execute Memory Protect: Enable를 설정해서 해결했다.
    3. 부팅 옵션은 PCIRootUID=0 하나만으로 충분했다.
    4. 무사히 산사자 설치가 완료되면 이제 멀티비스트로 네트워크와 오디오 드라이버를 잡아야 한다. 이 자료가 많은 도움이 되었다.
    5. 오디오는 ALC8XXHDA, AppleHDA Rollback, Non-DSDT HDA Enabler for ALC892를 선택할 것.
    6. 네트워크 설정시, 위 글에서는 Lnx2Mac's RealtekRTL81xx Ethernet Driver를 하라고 했는데, 그냥 Realtek Gigabit Ethernet 을 지정해도 잘 설정되었다. (사실 최초 부팅시 네트워크는 인식되지만, 멀티비스트를 돌리고 나면 사라지기 때문에 꼭 지정해줘야 한다)

    가끔 다운되는 현상이 있긴 해서 백점 만점을 주진 못하겠지만, 어쨌든 성공이다.

  • 2012-05-22

    AppScale

    개요

    AppScale은 구글 앱엔진 플랫폼을 오픈 소스화하는 프로젝트이다. 아래와 같이 구글 앱엔진의 주요 모듈들을 오픈 소스 서비스들로 교체했다고 보면 정답이다.

    • big table => mysql, MongoDB, Cassandra 등 입맛대로 선택.
    • memcache => memcached
    • task queue => RabbitMQ
    • backend => not supported
    • email => sendmail
    • cron => cron

    다만, 위 서비스들을 리얼 머신들에 직접 분산 설치하는 게 아니라, Ubuntu 가상 머신 이미지에 설치해둔 후 Amazon EC2 같은 가상 머신에 인스턴스들을 설치하고 역할을 지정하는 식으로 설치를 하게 된다. 가상 머신에는 그 외에도 다음과 같은 서비스들이 떠 있다.

    • ruby
    • erlang & neptune => neptune 이라는 cloud config/delpoy language
    • mongrel, mongodb
    • ndbd
    • nginix master & slave => 로드밸런싱용 웹서버

    appscale tools라는 아마존 EC2 tools와 비슷한 루비로된 스크립트로 플랫폼을 관리하게 되며, 아직까지는 python 2.5 만 지원한다. 웹 기반의 간단한 관리툴도 제공한다.

    구조

    • load balancer : http 분산
    • application : python
    • data management : DB. (cassandra, hbase, hypertable, mongodb, memcachedb, simpledb, mysql cluster, voldmort)

    배포 모델

    virtualized cluster deployment

    관리자가 각 호스트에 이미지를 설치하고 부팅해서 각각 네트워킹이 되는지 체크하고 IP를 기록해서 통신토록.

    • 인스턴스 하나당 1G 메모리, 2 virtual CPU 를 권장
    • ssh & root 접근 권한 필요
    • 그냥 셧다운하면 안됨. appscale 전체를 셧다운한 후에 개별 노드를 셧다운해야 함.

    cloud infrastructure deployment

    아마존 EC2 에 설치하거나 Eucalyptus(아마존EC2의 오픈소스 버전) 에 배포. AppScale 이 미리 설치된 AMI(Amazon Machine Image)로 설치.

    • 클라우드 관리자는 account credential 필요
    • appscale 설치 전에 non-appscale image 가 배포되고 public/private ip 를 설치할 수 있는지 체크해야 함.
    • 이 테스트가 모두 끝나고 나서 전체 셧다운 후 배포.

    배포

    appscale tools 를 이용해서 자동화함.

    • 클라우드 관리 인터페이스 제공
    • 각 인스턴스들의 ssh 키와 credential 들을 동기화함
    • ips.yaml 에 각 노드 정보가 있음.

    :controller: --> database master & load balancer 가 설치됨
    :servers: --> application servers & database slave 가 설치됨

    AppScale Tools

    사용법 참조

    appscale-run-instances

    특정 폴더를 배포하면서 appscale 서비스를 시작함.
    --file: 배포할 폴더 지정
    --table: 데이터베이스 지정.

    맨 처음에는 controller 노드를 시작함. servers 노드들은 비동기로 시작. 클라우드 배포시 VM 부팅을 시작함. 이미지 크기 때문에 수십분 걸림. 그다음엔 DB를 시작함.

    appscale-describe-instances

    각 노드 상태를 보여줌. 메모리. CPU. HDD. 역할. DB.

    appscale-upload-app, appscale-remove-app

    특정 앱을 업로드하거나 삭제함.

    appscale-terminate-instances

    전체 클라우드를 셧다운함.

    배포 구성 전략

    • load balancer: 라우팅. 모든 노드들의 상태 페이지 호스팅. 여러 개 실행 가능.
    • app engine: 커스터마이즈된 gae sdk 가 실행됨
    • database
    • login: 딱 한놈만 appscale-run-instances/appscale-upload-app 역할을 담당
    • zoo keeper : db transaction 을 위한 메타 데이터 호스팅
    • shadow :

    호환성 & 차이점

    설치하기

    가상 환경에서 guest OS로 돌아감. 가상 머신 이미지를 배포함. KVM, XEN. 근데 리눅스 Host 만 지원함. 보통 우분투를 씀.

    아마존에서는 이미지 업로드 없이 public AMI 를 써서 바로 띄울 수 있음. 단 버지니아에만 이미지가 존재함.

    see also deploying appscale via ec2

    환경 변수 설정

    AWS 키 & 크레덴셜 에서 X.509 키들을 다운받아서 pem 파일을 저장하고 환경 변수로 등록할 것.

    Access Keys 를 카피해서 배치 파일에 등록한다.

    see also appscale IaaS cloud deployment

    euca tools 설치

    아마존 접근을 위해서는 이 툴을 설치해야 된다.

    euca tools 다운로드

    1. pcre 설치
    2. swig 설치

    3. euca tools src deps 에서
      3-1. boto-1.9b

    python2.7 에서는 다음 패치를 해야 함.

    3-2. M2Crypto-0.20.2

    appscale tools 설치

    debian/appscale_build_source.sh 열어서 help2man 관련 섹션 제거 후
    sudo bash debian/appscale_build_source.sh 를 실행하면 /usr/local/appscale-tools 에 설치됨

    아마존 서버 설치

    버지니아에만 있는 appscale 1.6.1rc AMI (ami-e4a3048d) 을 이용해서 1 노드로 설치할 것. 이때 db 는 mysql

    appscale-run-instances --min 1 --max 1 --file /usr/local/appscale-tools/sample_apps/python/guestbook --machine ami-e4a3048d --table mysql --iaas --force -v

    인스턴스 타입은 지정하지 않으면 m1.large

    가끔 키가 이미 등록되어 있다고 하는데, 그럴 때에는 --keyname XXX 로 다른 걸 사용할 것.

    관련 키들은 ~/.appscale 폴더에 저장됨. pem 도 들어가 있음.

    ssh 하기

    ssh -i /Users/reiot/.appscale/warcloud.key root@ec2-23-22-2-204.compute-1.amazonaws.com

    access key & secret

    대칭형 암호화.
    모든 리퀘스트마다 public key id 를 보내고 더불어 secret key의 해시코드를 보내서 서버에서 검증하는 방식. 페북 캔버스앱과 동일한 구조다.

    X.509 Certificates

    공개키 암호화. cert.pem 으로 암호화하면 pk.pem 으로 복호화.

    • PEM encoded X.509 certificate: cert-xxxx.pem
    • PEM encoded RSA private key: pk-xxxx.pem

    key pairs

    EC2 인스턴스 접근시 권한.

    ssh 를 위해서 가상 서버 인스턴스에 키를 등록함.

    ssh 하기

    -v 옵션으로 상태를 볼 것. -i 로 cert-xxx.pem 파일을 이용. 로그인시 account@server 형식 사용.

    ssh -i ~/.ec2/cert.pem root@ec2-23-22-2-204.compute-1.amazonaws.com -v

    ec2 commands

    • ec2-authorize default -p NN : 특정 포트를 기본 오픈. (보통 ssh 22, 웹 80번 포트가 필요함)
  • 2012-04-27

    Unity3D Serialization

    C# 에서의 직렬화

    MSDN에 따르면, 클래스에 [Serializable()]만 선언하면 자동적으로 직렬화가 되며, ISerializable 을 상속받아서 다음 함수를 재정의해도 된다.

    • GetObjectData(): serialize 시 호출됨
    • protected constructor: deserialize 에서 호출됨

    Unity3d의 제약 조건

    Unity3d SerializeField 문서에 따르면,

    • static 필드, private 필드, property 는 자동 제외.
    • 각 필드별로 넣으려면 [SerializeField], 빼고 싶으면 [NonSerialized] 선언.
    • Dictionary, List of List, Array of Array 의 직렬화는 지원 안함

    이렇게 하더라도 가끔 iOS에서 지원하지 않는 경우가 있으니, 꼭 디바이스에서 테스트해보기 바란다 :P

    참고 자료