초등학교 때부터 피아노를 배우고 싶었는데 시간/금전적 여유가 부족해서 결국 이때까지 못배우고 있었습니다.

중학교 때 아버지께 떼써서 야마하 전자피아노를 하나 샀지만 학원을 못다녀서 흐지부지 되어버렸는데, 당장은 학원 다닐 상황이 안되니 독학으로라도 피아노를 좀 쳐보려 합니다.


여유 시간이 얼마나 될지는 모르겠고, 할일도 많고 바빠서 얼마나 꾸준히 할지는 모르지만 힘내봐야겠습니다 :)

'잡담' 카테고리의 다른 글

블로그 엄청 잠수했었구나  (0) 2017.04.14
서버를 옮겨야겠습니다  (0) 2017.01.06
오랜만에 잡담  (0) 2016.11.21
Tistory Flatinum 스킨 수정해서 사용  (0) 2016.10.18
수습 조기종료  (0) 2016.10.04
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


 Boost는 전 세계적으로 유명한 C++ 오픈소스 라이브러리이다.

Boost의 가장 큰 특징이자 장점은 내부적으로 수많은 플랫폼들의 표준을 이용하기 때문에 멀티플랫폼을 지원한다는 것이다. 이 Boost를 사용하기 위해 Windows에서 Visual Studio로 빌드하는 과정을 적어보았다.



첫째로, 우선 Boost를 다운받고, 압축을 풀어야 한다.


http://www.boost.org/




 위 사이트에 접속하면 우측에 GET BOOST 라고 적힌 붉은 버튼 이미지가 있다.

거기서 최신 버전을 다운받을 수 있으니 이를 다운받고, 원하는 위치에 압축을 풀어준다.

2016년 12월 20일 기준으로 최신 Release 버전은 1.62.0 버전이다.


 압축을 풀고 boost_1_62_0/bootstrap.bat 파일을 실행시킨다.

커맨드라인 창이 하나 뜨는데, 작업이 완료될 때까지 기다려 줘야 한다.

몇 분이면 끝난다.


 작업이 완료되고 나면 같은 디렉토리에 b2.exe 파일과 bjam.exe 파일이 생성된다.

먼저 b2.exe를 실행하고 끝난 후에 bjam.exe를 실행하면 되는데 b2.exe가 상당히 시간이 오래 걸린다.

인내심을 가지고 기다리자. 작업이 끝나고 나면 같은 디렉토리에 stage/lib 디렉토리가 생성되었을 것이다.


이 둘까지 마치고 나면 사용할 준비는 다 된 것이다.




 Visual Studio에서 프로젝트를 하나 만들고, Properties -> C/C++ -> General -> Additional Include Directories에 boost_1_62_0를 지정해 준다.

그 안에 든 'boost'가 아니라 'boost_1_62_0'인 이유는 일부 소스 파일들이 'boost'를 루트 디렉토리로 요구하기 때문이다.




 다음으로 똑같이 Properties -> Linker -> General -> Additional Library Directories 에 boost_1_62_0\stage\lib 을 넣어주자.

이후 빌드하면 정상적으로 빌드되며 실행도 잘 된다.




블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


 unique_ptr은 이름에서부터 알 수 있듯이 한 인스턴스에 대한 소유권을 단 하나의 포인터에만 허락하는 스마트 포인터이다. 따라서 포인터간의 복사는 불가능하며, 이동은 가능하지만 std::move라는 함수를 이용해야만 가능하다.


저번에 사용한 것과 같이 다음과 같은 클래스가 있다고 가정해 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass
{
public:
    int num;
    MyClass()
    {
        std::cout << "Ctor" << std::endl;
    }
 
    ~MyClass()
    {
        std::cout << "Dtor" << std::endl;
    }
};
cs


 int형 변수와 생성자, 소멸자에 출력문을 하나씩 갖고 있는 심플한 클래스이다.

이를 다음과 같이 unique_ptr을 이용해 main에서 생성, 출력을 하면 알아서 메모리를 해제해 준다.


1
2
3
4
5
6
7
8
int _tmain(int argc, _TCHAR* argv[])
{
    std::unique_ptr<MyClass> myClass(new MyClass);
    myClass->num = 1234;
    std::cout << myClass->num << std::endl;
    return 0;
}
 
cs




unique_ptr을 복사하려고 하면 컴파일 시점에 이렇게 에러가 발생한다.


error C2280: 'std::unique_ptr<MyClass,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': 삭제된 함수를 참조하려고 합니다.


한 인스턴스를 두개 이상의 포인터가 가리키는것은 불가능하므로 이동만 가능한데, 다음과 같은 방식으로 이동이 가능하다.


1
2
3
4
5
6
7
8
9
int _tmain(int argc, _TCHAR* argv[])
{
    std::unique_ptr<MyClass> myClass(new MyClass);
    std::unique_ptr<MyClass> myClass2 = std::move(myClass);
    myClass2->num = 1234;
    std::cout << myClass2->num << std::endl;
    return 0;
}
 
cs


std::move 이후 myClass는 NULL로 초기화되며 myClass2에 해당 인스턴스의 주소가 할당된다.




 weak_ptr은 shared_ptr의 단점을 보완하는 데에 사용되는 포인터이다.

shared_ptr의 경우 순환 참조(Circular references)라는 문제가 발생할 수 있다.

이는 shared_ptr가 서로를 참조하여 둘 모두 반환이 되지 않는 상태로, 일종의 메모리 데드락이라고 볼 수 있다.


 shared_ptr은 내부적으로 레퍼런스 카운팅을 통해 해당 인스턴스를 가리키는 포인터의 개수를 세지만, 사실 이 레퍼런스 카운트 변수는 두 가지의 종류가 있다. 이중 strong_count는 shared_ptr에서 메모리의 해제에 직접적으로 관여하는 카운트로, 0이 되면 메모리가 자동으로 해제된다. weak_count는 간단하게 같은 인스턴스를 가리키는 weak_ptr의 개수로, 이는 메모리의 해제에 영향을 미치지 않는다.


 weak_ptr은 기본적으로 shared_ptr과 같은 주소를 가리키지만 객체에 직접적인 참조는 불가능하다. 참조를 위해서는 lock() 함수를 이용해 shared_ptr을 반환받은 후 사용해야 한다. 만약 weak_ptr이 남아 있는 상태에서 shared_ptr이 전부 사라지면 메모리는 해제되고 lock() 함수에서는 nullptr이 반환된다. 그 반대로 weak_ptr이 전부 사라진다고 해도 shared_ptr이 남아 있다면 메모리는 해제되지 않는다.

shared_ptr의 참조자와 비슷한 역할을 하는 것이다.


http://blog.naver.com/wlstn3273/220713667682


 좋은 예시가 여기에 있으므로 여길 보고 따라가 보면 개념이 제대로 잡힐 것이라고 생각한다.

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,

 C++의 가장 큰 장점이자 단점이라고 하면 대부분의 사람들이 공통으로 꼽는 것이 바로 '포인터의 사용'이다.

C++은 포인터를 이용하여 메모리를 직접 관리하고, 따라서 타 언어에 비해 훨씬 성능이 좋다.


하지만 포인터는 양날의 검이다. 잘 다루면 성능 좋은 프로그램을 만들 수 있지만 메모리 관리를 잘못하는 순간 프로그램이 박살날 수 있다.


 C++ 개발자들은 이런 메모리 관리 문제를 어떻게 해결하면 좋을지 생각하다가 '스마트 포인터'라는 개념을 만들었다.

이것을 이용해 메모리를 할당하면 메모리 관리를 자동으로 해 주는 아주 편리한 도구인 것이다.


 초기 스마트 포인터는 auto_ptr 이라는 예약어를 이용하여 할당할 수 있었다.

auto_ptr로 할당한 메모리는 소유권이라는 것을 가지고 있어, 이를 가리키고 있던 포인터가 사라지면 메모리를 자동으로 해제해 주는 편리함을 제공했다.

하지만 auto_ptr에는 여러가지 문제점이 있었는데, 바로 '소유권 이전'에 관한 문제였다.


 auto_ptr로 생성한 포인터는 다른 포인터에 복사할 경우 소유권을 이전하게 되는데, 복사한 포인터가 사라질 경우 할당된 메모리를 자동으로 해제해버리는 문제가 발생한다.

간단한 예제로 다음과 같은 코드를 돌려보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "stdafx.h"
#include "memory"  
#include "iostream"  
 
class MyClass
{
public:
    int num;
    MyClass()
    {
        std::cout << "Ctor" << std::endl;
    }
 
    ~MyClass()
    {
        std::cout << "Dtor" << std::endl;
    }
};
 
void print_num(std::auto_ptr<MyClass> myClass)
{
    std::cout << myClass->num << std::endl;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    std::auto_ptr<MyClass> myClass(new MyClass);
    myClass->num = 1234;
    std::cout << "print start" << std::endl;
    print_num(myClass);
    std::cout << "print ended" << std::endl;
    std::cout << myClass->num << std::endl;
    return 0;
}
 
cs




 아름답게 박살이 나는 프로그램의 모습을 볼 수 있다.

출력된 것을 보면 알겠지만 print_num 함수 내부의 매개변수로 main의 myClass가 복사되면서 소유권이 이전되었고, print_num 함수가 끝나면서 myClass가 할당된 메모리가 해제되어 main에서 해제된 메모리를 참조하려다 에러가 나는 것이다.


 이런 auto_ptr의 단점을 보완한 것이 shared_ptr이다.

본래 boost 라이브러리에 속해있던 기능이지만 C++11에서 표준으로 포함되었다.

auto_ptr과 달리 shared_ptr은 레퍼런스 카운팅 방식으로 메모리를 관리하기 때문에 해당 인스턴스를 가리키는 포인터가 전부 사라져야 메모리가 해제된다.


auto_ptr을 shared_ptr로 바꾼 코드를 실행시켜보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "stdafx.h"
#include "memory"  
#include "iostream"  
 
class MyClass
{
public:
    int num;
    MyClass()
    {
        std::cout << "Ctor" << std::endl;
    }
 
    ~MyClass()
    {
        std::cout << "Dtor" << std::endl;
    }
};
 
void print_num(std::shared_ptr<MyClass> myClass)
{
    std::cout << myClass->num << std::endl;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    std::shared_ptr<MyClass> myClass(new MyClass);
    myClass->num = 1234;
    std::cout << "print start" << std::endl;
    print_num(myClass);
    std::cout << "print ended" << std::endl;
    std::cout << myClass->num << std::endl;
    return 0;
}
 
cs




 이렇게 정상 작동하는 것을 확인할 수 있다.

이 외에도 스마트 포인터에는 unique_ptr과 weak_ptr이 존재하는데, 이는 다음번에 공부하면서 작성하도록 하겠다.

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


 이 글은 아직 완성된 글이 아니며, 공부하면서 알게 된 내용들을 바탕으로 짤막한 지식들을 나열해 나갈 것입니다.

잘못된 부분이 있으면 덧글이나 방명록 등으로 알려주시면 감사하겠습니다 :)



1. IO 객체 std::cin/cout/cerr/clog 중 cerr는 un-itbuffered이다.


 흔히 우스갯소리로 printf 디버깅 또는 cout 디버깅이라고 부르는 오류 해결 방식이 오류가 나는 지점 주변에 출력문을 넣어 어디까지 정상적인 값이 출력되었는지를 살펴보는 것이다. C++에서는 출력 방식으로 흔히 std::cout을 사용하는데, 기본적으로 std::cout은 buffered 로 동작하기 때문에 원하는 위치에서 정상적인 출력이 되지 않을 수 있다. 따라서 std::cout으로 로그를 찍기 위해서는 버퍼를 비우는 동작을 추가로 진행해 주어야 하며, 이를 std::endl이 수행한다.


 하지만 그렇게 번거롭게 하지 않더라도 버퍼를 비우는 방법은 한 가지가 더 있는데, 바로 std::cerr를 사용하는 것이다. std::cerr는 디폴트로 un-itbuffered 로 동작한다. un-itbuffered란 '이 연산은 buffered이기는 하지만 출력 이후 바로 버퍼를 비운다'는 것을 의미한다. 따라서 추가로 버퍼를 비우는 행위를 하지 않더라도 정상적인 위치에서 출력이 가능하게 된다.


* buffering이란 효율적인 입/출력을 위해 프로그램에서 일정 크기만큼을 메모리에 임시로 보관하고 있다가 일괄로 처리하는 것을 의미한다.



2. stream의 operator<<, operator>> 는 자기 자신을 반환한다.


  C++을 사용하면서 operator<<를 사용할 때,

1
std::cout << "Hello World!" << std::endl;


 이런 식으로 연속하여 사용해 본 적이 있을 것이다.

이것이 가능한 이유는 앞에서부터 연산을 수행하되, ostream::operator<< 의 리턴 값이 자기 자신이기 때문이다.

즉, 앞의 연산인 std::cout << "Hello World!" 가 먼저 수행되고 자기 자신이 리턴되어 다음 명령도 std::cout << std::endl이 되는 것이다.



3. method와 function은 다르다.


 보통 함수라고 부르는 function은 '이름으로 불려지는 특정 코드의 집합'을 의미한다.  메서드라고 부르는 method는 '특정 객제에 포함된 이름으로 불려지는 특정 코드의 집합'이다. 간단하게 '멤버 함수' == '메서드' 라고 볼 수 있다. 함수가 메서드보다 더 큰 범위라고 할 수 있겠다.



4. std::endl은 함수로 쓸 수 있다.


 std::endl을 보통 '\n'을 출력하는 것과 같다고만 알거나, 조금 더 나가서 버퍼를 flush해준다고 알고 있는 사람들은 많지만 사실 std::endl은 함수로써 사용도 가능하다. 인자로 output stream을 받으며, 사용법은 다음과 같다.

1
std::endl(std::cout);



...계속 추가됩니다.

'Programming' 카테고리의 다른 글

[C++] unique_ptr, weak_ptr  (0) 2016.12.15
[C++] auto_ptr, shared_ptr  (0) 2016.12.14
[C++] 얕은 복사, 깊은 복사, 복사 생성자  (0) 2016.12.13
[C++] std::for_each  (0) 2016.12.12
[Python] Pacro : Python 기반 매크로 프로그램  (5) 2016.11.28
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


 C++에서 가끔 클래스를 복사하게 되는 일이 생긴다.

클래스를 복사하는 방법에는 크게 얕은 복사와 깊은 복사라고 부르는 두 가지의 방법이 있다.

MSDN에서는 전자를 멤버 단위 복사라고 부른다.

클래스 내부의 변수들을 하나하나 똑같이 복사한다고 해서 그렇게 부르는 듯 하다.


 디폴트 생성자와 마찬가지로 멤버 단위 복사 생성자도 따로 복사 생성자를 선언하지 않는 이상 자동으로 생성된다.

따라서 따로 작업을 해주지 않는 이상 컴파일러는 디폴트로 얕은 복사를 수행한다.


 클래스 내에서 포인터를 이용해 메모리 작업을 하지 않는 이상 얕은 복사가 큰 문제가 되는 일은 많지 않을 테지만 만약 클래스 내에서 메모리를 할당하고 소멸자에서 이를 해제하게 하는 등의 작업을 한다면 치명적인 문제가 된다.


다음과 같은 클래스가 있다고 가정해 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
class MyClass {
private:
    char *name;
public:
    MyClass(char*);
    ~MyClass() { delete[] name; }
    void printName() { std::cout << name << std::endl;  }
};
 
MyClass::MyClass(char* newName) {
    name = new char[strlen(newName) + 1];
    strcpy(name, newName);
}
cs


 멤버 변수로 name이라는 char형 포인터를 갖고, 생성자에서 이를 입력받아 할당하며 소멸자에서 해제하는 간단한 클래스이다. 클래스 멤버 함수로 name을 출력해주는 printName을 가지고 있다. 생성자에서 할당하고 소멸자에서 해제하므로 메모리 관리에 아무런 문제가 없어 보이지만, 이를 복사하게 되면 얘기는 달라진다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void printMyClass(MyClass m)
{
    std::cout << "<printMyClass>" << std::endl;
    m.printName();
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    MyClass myClass("John");
    std::cout << "<main>" << std::endl;
    myClass.printName();
 
    printMyClass(myClass);
    return 0;
}
cs


 MyClass를 인자로 받고 main에서 인스턴스를 만들어서 이를 인자로 넘겨주면 printMyClass에서는 매개변수로 MyClass를 하나 만들고, 거기에 main에서 생성한 인스턴스를 그대로 복사한다.


얕은 복사가 진행되면서 main에서 생성한 인스턴스 속의 변수도 똑같이 복사되며, 문자열의 주소를 담고 있는 name 변수의 값도 똑같이 복사된다. 즉, 포인터 주소값이 그대로 복사되므로 main의 인스턴스와 같은 주소를 가리키게 된다.


이제 printMyClass 함수가 끝까지 정상적으로 실행되고 함수가 끝나면서 문제가 발생한다.

함수 시작 시 생성된 인스턴스가 할당 해제되면서 소멸자를 호출하고, 메인의 인스턴스의 변수와 함께 가리키고 있는 name 공간도 자동으로 할당이 해제되어 버린다.


이후 main에서 return으로 빠져나가면서 main에서 생성한 인스턴스가 또 할당 해제되고, 소멸자를 한번 더 호출하면서 이미 할당 해제된 공간을 한 번 더 해제하려고 하므로 에러가 발생한다.


 이런 식으로 얕은 복사를 하게 되면 예상치 못한 곳에서 치명적인 에러가 발생할 수 있다.

이런 문제를 해결하기 위해서 보통 class 내부에 복사 생성자를 생성하여 깊은 복사를 진행한다.

깊은 복사를 위해 class에 다음과 같이 복사 생성자를 추가해 주었다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyClass {
private:
    char *name;
public:
    MyClass(char*);
    MyClass(MyClass&);
    ~MyClass() { delete[] name; }
    void printName() { std::cout << name << std::endl;  }
};
 
MyClass::MyClass(char* newName) {
    name = new char[strlen(newName) + 1];
    strcpy(name, newName);
}
 
MyClass::MyClass(MyClass& newClass) {
    name = new char[strlen(newClass.name) + 1];
    strcpy(name, newClass.name);
}
cs


 이제 인스턴스를 복사할 때는 복사 생성자의 소스를 이용하여 깊은 복사를 진행하므로 새로 생성된 인스턴스의 name에도 따로 공간이 할당되고, 값이 똑같이 복사될 것이다. 이 메모리가 해제되더라도 main의 인스턴스가 가리키는 주소와는 연관이 없으므로 아무런 문제가 발생하지 않는다.



'Programming' 카테고리의 다른 글

[C++] auto_ptr, shared_ptr  (0) 2016.12.14
[C++] 알아두면 좋은(?) C++ 지식들  (0) 2016.12.13
[C++] std::for_each  (0) 2016.12.12
[Python] Pacro : Python 기반 매크로 프로그램  (5) 2016.11.28
[C++] CreateMutex  (2) 2016.11.22
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,

[C++] std::for_each

Programming 2016. 12. 12. 18:13


많은 언어에 존재하는 for-each 구문이다.

C++ 공부도 할 겸 공부한 내용을 정리하면서 이런 글을 자주 작성할 것 같다.


for_each는 <algorithm> 내에 정의되어 있다.

범위를 정해서 루프를 도는 for문과 유사하지만 다른 점은 포인터를 이용해 시퀀스의 변수에 접근한다는 점이다.

따라서 for문처럼 시작과 끝을 정하는 것이 필수적이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "stdafx.h"
#include <algorithm>        // for `std::for_each`
#include <vector>            // for `std::vector` 
#include <iostream>            // for `std::cout`
 
void square(int& num) {
    num *= num;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> int_vector = { 13579 };
    std::for_each(int_vector.begin(), int_vector.end(), square);
    for (auto num : int_vector)
        std::cout << num << " ";
    std::cout << std::endl;
    return 0;
}
cs


첫 번째 인자로 int형 vector의 시작인 begin()을 주었고, 두 번째 인자로 마지막 변수 다음 값인 end()를 주었다.

각각 시작과 끝을 나타내며, 세 번째 인자에는 함수 객체를 넣어 주어야 한다.


for_each를 통해 참조되는 vector의 각 멤버들을 레퍼런스로 넘겨 이를 제곱하고 있으므로 for_each문이 끝난 이후 모든 멤버들이 제곱되어 있을 것이다.


실제 출력 결과를 확인해 보면 다음과 같이 예상한대로 되어 있는 것을 볼 수 있다.



블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


 거의 20년 인생 살면서 처음으로 가 본 라이브 공연이었습니다.

이 표 얻겠다고 밤 12시에 눈에 불켜고 컴퓨터에서 마우스를 광클했었죠...

가장 좋아하는 밴드라 원래 인천 펜타포트 락 페스티벌에서 보려고 했었는데 기회가 되지 않았었습니다.


 Yes24 라이브홀에서 열렸고, 공연장 크기는 대략 2000석이 들어갈 정도로 그리 크지는 않았습니다.

맘속에서는 스파이에어정도면 몇만석짜리 공연장에서 해도 충분할 거라고 생각하지만, 어쨌든 예매에는 성공했으니 만족합니다.


(클릭하면 원본으로 볼 수 있습니다)


 6시 공연 시작이라 좀 일찍 가자 싶어서 4시에 도착했는데 세상에 이미 줄이 엄청나더라구요.

어버버 하고 있었더니 라커도 다 차버리고 결국 짐을 넣어놓지도 못한 채로 공연장에 갖고 들어갔습니다...

우선 갖고 있는 티켓에 맞는 팔찌를 받아서 착용해야 합니다. 이후 공연장에 들어갈 때는 각 섹션별로 두 섹션씩 두 번에 걸쳐 입장했습니다. A, B 섹션의 1~200번이 먼저 들어가고 이후 201~400번, 그 다음 C, D 섹션이 들어가는 식이었습니다.




 저는 A섹션의 300번대여서 무대 앞 섹션의 뒷자리였는데요, 라이브 시작하고 나니까 자리고 뭐고 없더라구요.

흥나는대로 뛰다 보면 어느순간 무대 앞으로 가있곤 합니다.

라이브 후기를 한 단어로 말해보면 감히 '최고'라고 할 수 있겠습니다.

난생 처음으로 간 라이브이긴 한데 정말 파워풀했고 멤버들도 다 너무 멋있고 노래들도 다 잘부르고...

살면서 이렇게 뛰면서 소리질러본건 처음인 것 같네요.


 기억이 맞다면 첫곡은 Firestarter였던 것 같습니다.

시작이 좀 늦어지길래 상당히 불안해하고 있었는데 시작부터 강렬한 곡이 나와서 분위기가 순식간에 업됐죠.

이후 I'm a believer, Imagination 등 하이큐 곡들과 벚꽃만월, 사무라이 하트 등 은혼 곡들... 최고였습니다 정말.


이 다음부터는 그냥 무아지경으로 손흔들면서 노래 따라부르고 떼창하느라 정신없었습니다.


기억에 남는 장면을 좀 되돌려 보면...


이케가 곡들 끝나고 잠시 쉬는 타임에 앉아서 얘기를 했는데, 기억나는대로 대충 적으면...

' 우리는 일본인입니다. 국적도 민족도 다르지만 우리는 한국이 정말 좋습니다. 모두 함께 즐기면서 최고의 무대를 만들어가고 싶습니다. 모두 정마아아알 사랑해요! 내년에 또 올게요! (환호성) ' 

정도였던것 같습니다. 환성과 박수가 정말 대단했습니다.


중간에 무슨 곡인지는 잘 기억이 안나지만 이케와 유지가 모자를 쓰고 노래하는 부분이 있었습니다.

이케는 정상적인 모자였는데 유지 모자에는 '유지오빠'라고 한국어로 씌여있어서 보고 뿜어버렸습니다 ㅋㅋㅋㅋㅋ


중간에 '벚꽃만월'이 나올 때 예상했었지만 라이트가 보라색이라 역시 연출이 좋다고 느껴버렸습니다. My Friend 도 어쿠스틱 버전으로 떼창해보고, 라이브 마지막 곡이었으면 좋겠다고 생각했던 Singing이 정말로 마지막 곡으로 나와서 너무 기뻤습니다. 


2시간 내내 오른팔 또는 왼팔(팔이 너무 아파서 바꿔가며)들고 점핑했던 터라 다리며 팔이며 많이 아프네요.


중간에 This is how we rock과 I'm a believer, 벚꽃만월 등이 나올 때는 (사실 거의 모든 곡이) 너무 좋아서 눈물까지 났네요.



라이브 첫 관람자로서 알아두면 좋은 몇 가지 팁.


- 짐은 적고 가볍게, 불가능하다면 최대한 일찍 가서 라커를 선점해야 한다.

=> 날이 추워서 라커에 넣을 수 있을 줄 알고 패딩 입고 갔는데 라커가 다 사용중이더라구요. 급한대로 지하철역의 물품보관함에도 가봤지만 같은 생각을 하는 사람들이 많았는지 다 사용중이었고... 결국 갖고 들어가서 가방과 패딩을 들고 뛰었습니다. 훨씬 일찍 와야 하는 필요성을 강하게 느꼈죠.


- 예매 시 자리는 크게 중요하지 않다

=> 예매할 때 자리가 A섹션의 가장 뒤 열이어서 안보일까봐 불안했는데, 사실 그 번호라고 하는게 정확히 정해진 자리가 아니라 입장하는 순서일 뿐으로 라이브 시작되고 나면 자리고 뭐고 다 섞여버립니다. 안보일 거라고 걱정은 하지 않으셔도 됩니다. (물론 섹션이 너무 안좋으면 어쩔 수 없습니다 ㅠㅠ)


- 꼭 볼일은 보고 들어가고, 물은 꼭 사가지고 들어가자

=> 물을 많이 마시라는 뜻이 아니고, 공연 시작 후 화장실을 가는 것은 거의 불가능에 가깝고 집중도 덜 되기 때문에 꼭 화장실에 미리 갔다 오는 것이 중요합니다. 6시 공연 시작인데 5시에 입장을 시작했고, 그전부터 줄을 섰기 때문에 공연 시작 2시간정도 남겨두고 모든 처리를 마치는 게 좋습니다. 그리고 공연장에서 뛰고 떼창하다 보면 목이 정말 심각하게 마릅니다. 조금씩만 마실 정도로(배 안아프고 화장실 안 갈 정도로) 물을 준비해서 들어갑시다.


- 야광봉은 가능한 있는게 좋다, + 공연에 맞는 소품도

=> 시간이 없어서 아무것도 안사고 그냥 들어갔더니 손만 흔들게 되었습니다. 아무것도 안들고 손만 흔드려니 좀 허전하더라구요. 야광봉이 있으면 정말 좋습니다. 사무라이 하트 곡이 나올 때쯤 이케가 스파이에어 타올 돌리라고 하면서 불러서 있었으면 정말 좋겠다는 생각도 했습니다. 결론은 일찍 와서 일찍 굿즈를 지르자 (._.




이번 공연 전후로 산 스파이에어 관련 물품들입니다.

돈이 상당히 들긴 했지만 무지 만족스럽습니다!


Rage of Dust 한정판 앨범 - 13000원

SPYAIR BEST 앨범  - 20000원

SPYAIR 4집 앨범   - 15000원

SPYAIR 티셔츠      - 25000원

SPYAIR 카드지갑   - 15000원


+ 공연 티켓 88000원...


대략 18만원정도 든 것 같네요. 하지만 전혀 아깝지 않습니다!

첫 라이브부터 정말 제대로 꽂혀버렸습니다. 

아마 다음 라이브는 내년 중순정도가 되지 않을까 싶은데 꼭 다시 가고 싶습니다.


'Hobby' 카테고리의 다른 글

일렉기타 연습할 곡 리스트업  (0) 2018.07.01
Schecter C-1 FR S Apocalypse 구매  (1) 2018.04.19
일렉기타 셋업 - 닥터에이 방문  (0) 2018.04.06
Line6 POD HD500X 구매  (0) 2018.02.24
Fender Mustang MG-69 MH CAR  (1) 2017.12.27
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,



 2003년, 그리니까 지금으로부터 대략 13년 전에 나온 책이다.

상당히 오래된 책으로 실제로 이 책 내용은 모두 16비트와 32비트에 맞춰져 있으며 64비트는 등장하지도 않는다.

볼 필요도 없을 거라고 생각했던 16비트와 32비트 OS의 차이 등도 설명한다.


 처음 이 책을 펴고 웃음이 먼저 나왔다.

'컴퓨터'라는 개념이 무엇인지부터 설명하고 있었기 때문이다.

이후로 나오는 내용을 보아하니 왜 윈도우가 쓰기 편하고 친숙하고 범용적인지에 대해 설명하고 있었는데, 그 어떤 전문적 지식이 없이도 간단히 이해할 수 있을 만큼 쉬운 이야기들 뿐이었다.

솔직히 여기까지만 보고 '아, 이건 내가 볼 책이 아닐 수도 있겠구나' 싶었었다.


 하지만 그런 생각은 조금 진도를 나가면서부터 싹 사라졌다.

초반부에 OS가 무엇인지 개념을 설명하더니 놀라울 정도로 자연스럽게 프로그래밍->라이브러리->범용성으로 나아가기 시작했다.

윈도우의 역사를 설명하며 16비트 -> 32비트로 넘어가더니 멀티태스킹이 등장했고, 이에 따라 16비트에서와 메모리를 다루는 방식이 어떻게 달라졌으며 따라서 어떻게 멀티태스킹을 구현했는지에 대해서 설명했다. 여기에서 끝나지 않고 응용 프로그램이 어떻게 드라이버와 OS를 거쳐 하드웨어를 컨트롤할 수 있는지, 네트워킹은 어떻게 하는지, 프로세스간 통신은 어떻게 하는지 등에 대해서 넒게 설명했다.


 중후반부에서 하드웨어와 드라이버 관련 설명을 할 때에는 처음에 들었던 '너무 쉽다'는 생각은 사라진지 오래였다.

오히려 이 책의 가장 적절한 독자는 'IT에 대해서 아무것도 모르는 완전한 초보자'보다는 '어느 정도 공부한 경력이 있는 IT 전문가'라는 생각이 들었다.

질릴 만큼 깊숙히 들어가지도 않았고, 그렇다고 너무 방대한 양을 설명하지도 않았다.

학구열과 얻은 지식에 대한 적당한 만족감을 갖게 해주는, 딱 그 정도의 내용을 담고 있었다.


 이미 윈도우 전반에 대해 어느 정도의 지식을 가지고 있다면 이 책을 봐서 얻을 수 있는 것이 그리 많지 않을지도 모른다.

하지만 나처럼 윈도우에 대한 기초 지식이 많이 부족함을 스스로 느끼고 있다면 이 책을 보면서 많은 것을 느낄 수 있을 것이라 생각한다.


 오래됐다고 내용이 부족하고 얕을 것이라고 생각하지 말고 한번쯤 보기를 추천한다.

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,


 네트워크를 공부하려면 필수적으로 거쳐야 하는 것이 바로 사설망이다.

NAT가 무엇인지 알고는 있었지만 새로운 사실을 공부한 김에 다시 개념을 정리하도록 하겠다.



NAT란 무엇인가


 NAT는 Network Address Translation의 약자이다.

현재 사용하는 XXX.XXX.XXX.XXX 형태의 IP 주소는 IPv4 형식으로 4 옥텟으로 표현하도록 되어 있다.

여기서 옥텟이란 8개의 연속적인 비트의 집합을 의미하는 것으로 바이트와 같은 단위라고 봐도 무방하다.

즉, IPv4 에서의 주소는 4바이트로 표현할 수 있고 따라서 최대 개수는 2^32 = 4,294,967,296 이다.

이는 약 43억 개이므로 충분하다고 생각할 수 있지만 사실 IP 주소는 그렇게 여유롭지 않다.

그래서 IP 주소의 절약을 위해 NAT 시스템을 도입하였다.


[NAT 개념도]


 NAT는 하나의 공인 IP를 여러개의 사설 IP로 변환하는 시스템이다.

랜카드를 두 개 이상 가진 공유기(라우터)가 사설망과 외부망의 사이에서 중개자 역할을 하는 것이다.

주변에서 많이 쓰는 공유기가 바로 대표적인 NAT 시스템이다.



NAT의 장점


NAT를 사용하는 이유는 크게 두 가지가 있다.


  1. IP 주소 절약


위에서 언급했다시피 IPv4는 최대 43억개 까지밖에 사용할 수 없다.

하지만 사설망을 사용하게 되면 그 활용도가 훨씬 늘어남을 알 수 있다.


[NAT 사용 시 공인IP 주소를 효율적으로 사용할 수 있다]


 한 공인IP당 A클래스 사설망의 경우 16,777,216개, B클래스 사설망의 경우 1,048,576개, C클래스 사설망의 경우 65,536개의 내부 주소 사용이 가능하다. 물론 네트워크 주소와 브로드캐스트 주소를 빼고 서브넷 마스크까지 계산한다면 훨씬 적어지겠지만 원래라면 한 IP만이 사용 가능한 주소를 저렇게 많은 수의 기기가 연결하여 사용 가능하다는 점은 분명히 큰 이점이다.


  2. 보안


[NAT를 사용하면 외부에서 접근이 불가능해져 보안이 강하다]


 밑에서 설명할 내용이지만 사설망은 특별한 설정을 해 주지 않는 이상 외부망에서 사설망 내부 PC로의 접근이 불가능한 구조로 되어 있다. 따라서 네트워크를 통한 공격에 매우 안전해진다.


  3. IP 주소 관리의 편의성


 이건 개인적으로 생각하고 있던 것이지만 서술해두겠다. IP 주소는 통신을 위한 것이므로 충돌이 일어나서는 안된다. 다시 말해, 한 IP 주소는 무조건 한 PC만이 사용해야 한다. 하지만 43억 개나 되는 IP 주소를 개개인의 PC나 휴대폰 등에 전부 등록하는 것은 당연하게도 무리이다. 사설망을 사용하게 되면 공유기가 자신에게 접속하는 기기의 IP만 관리하면 되므로 훨씬 간편하게 IP를 관리하는 것이 가능하다. 실제로 지금 대부분의 공유기는 DHCP를 이용해 사설IP를 동적으로 할당한다.



NAT의 통신 원리


 사설망에서 외부망으로 통신을 시도하면 해당 패킷은 무조건 공유기를 거치게 되어 있다. 여기서는 의미상 게이트웨이라고 하겠다. 당연하게도 처음 발신자가 게이트웨이에게 패킷을 전달했을 때 '보내는 사람의 IP'를 나타내는 SRC_IP는 사설망 내부의 발신자 주소로 채워져 있다. 하지만 만약에 이것이 그대로 전달될 경우, 수신자가 응답하는 상대의 주소는 사설망 내부의 IP가 되므로 전 세계의 수많은 사설망중 어디로 보내야 할지 알 수가 없게 된다.이런 이유 때문에 외부에서 사설망으로의 접근이 불가능하여 NAT가 보안이 뛰어나다는 장점도 있다.


[사설망의 통신 과정. Gateway->PC1은 어떻게 할까?]


 그래서 통신을 위해 게이트웨이는 패킷을 받아서 패킷 안의 IP주소를 자신의 공인IP로 임의수정하여 목적지로 발신한다.

패킷을 받은 수신자는 목적지 IP 주소에 게이트웨이가 집어넣은 공인IP를 넣어서 패킷을 발신할 것이고, 해당 패킷은 게이트웨이에게 도달하게 될 것이다. 이전에 이렇게 거기까지 공부한 이후 어떻게 다시 사설망의 특정 사용자에게 도달이 가능했는지 궁금했었다.


[NAT가 패킷을 전달하는 과정]


 게이트웨이가 발신자의 IP를 수정하여 발신할 때 게이트웨이는 내부에 갖고 있는 테이블에 이를 기록해 둔다. 어떤 주소에서 어떤 주소로, 무슨 프로토콜을 사용하여 발신했는지를 기록한 후, 응답 패킷이 되돌아오면 그 값을 찾아서 해당하는 사설망 기기에게 발신하는 것이다. 이렇게 테이블을 만들어서 저장해놓고 찾아가는 방법으로 이 문제를 해결할 수는 있지만 문제가 한 가지 더 생길 수 있다. 이는 다음에 설명할 NAPT에서 해결된다.



NAPT란 무엇인가


[NAT의 통신 문제. 만약 두 기기가 동시에 접속을 요청한다면?]


 NAT의 통신 방식은 큰 문제가 하나 있다. 바로 여러 개의 사설망 내의 기기가 동시에 같은 외부망 주소로 접속을 요청하는 경우이다. 원래라면 요청한 곳의 주소와 포트를 보고 해당하는 사설망 주소를 찾아서 보내주어야 하는데, 해당하는 주소가 여러 개일 경우 중복되므로 이를 처리할 방법이 없는 것이다.


이를 해결하기 위해 만들어진 것이 NAPT이다.

[NAPT의 통신 과정. 발신자 포트번호까지 사용하므로 문제 없이 통신할 수 있다]


 NAPT는 Network Address Port Translation의 약자로, NAT에서는 발신자의 사설망-외부망 IP를 바꿔서 보내주는 역할만을 수행했다면 이제는 포트까지 바꿔서 보내는 역할을 한다. 이러면서 NAPT의 테이블은 NAT의 테이블에서 Port에 해당하는 컬럼이 추가된다. 이렇게 변경한 결과 게이트웨이는 발신자의 포트 번호를 보고도 구별할 수 있게 되었다. 만약 발신자의 포트 번호까지 같게 패킷이 보내지면 어떻게 되느냐고도 할 수 있는데, 그럴 경우에는 위 그림처럼 Private Port를 임의의 SRC 포트로 바꿔서 보내면 되므로 아무런 문제가 없다.


'Knowledge' 카테고리의 다른 글

리눅스 커널 공부 정리 0x01  (0) 2017.06.20
Memory Segmentation  (0) 2016.12.27
멀티 태스킹(Multi-Tasking)의 원리  (0) 2016.11.21
PCB (Process Control Block)  (0) 2016.11.14
[Assembly] Intel x86, Local JMP [0xE9]  (0) 2016.11.07
블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

,