겸손한 개발을 위한 자양분


namespace 에 대해 오해하고 있는 소수의 분들을 위해...

Static Library 를 제작하고, 또 사용하다보면 Name Conflict 에러가 발생하는 경우가 있습니다.
이 에러는 프로젝트에 포함된 이종 라이브러리가 같은 이름의 함수명/변수명을 갖게 될 경우 나타납니다.

가령, 프로젝트에서 a.lib , b.lib 두개의 라이브러리를 link 할때에
a.lib 에서 fnA() 라는 함수가 선언되어있고,
b.lib 에서 fnA() 라는 함수가 선언되어있는 경우
두 함수의 이름이 같기 때문에 발생하는 에러입니다.

이 때 conflict 를 피하기 위하여 생긴것이 namespace 입니다.
namespace 는 내부에 정의된 이름들에 대해 마치 class의 캡슐화와 같은 효과를 줍니다.

.net 프로그래밍을 하셨다면,
using namespace std;
라는 구문을 보셨을텐데요,

이 명령은
소스코드 내에서 cout 등의 함수들을 호출할때
std::cout 을 호출하는것으로 인식하게 해 줍니다.

즉, 표준 함수의 namespace 가 std 인 셈입니다.

개발을 하다보면,
동일 소스를 사용해서 이종 Static Library 를 생산해야할 때가 있습니다.
이럴때에는 소스가 동일하기 때문에 똑같은 이름의 함수/변수를 갖는 Static Library 가 생기게 됩니다.
( 물론 소스를 복사해서 쓸수도 있지만, 동일 소스가 여러개로 보관되면 관리상의 치명적인 문제점이 생기게 되겠죠 )

이럴때, 프로젝트를 기준으로 하여
소스가 동일하더라도, 프로젝트별 namespace 를 달리하게 되면
하나의 코드로 여러개의 library 를 만들더라도 conflict 문제 없이 빌드할 수 있습니다.

일반적으로 namespace 를 사용하는 소스의 예는 다음과 같습니다.

using namespace myprojectns;
 
namespace myprojectns{

int g_nCount;

void fnA(){
Sleep(0);
}

}


마치 Class 와 비슷한 모양을 갖게 되는데요
위의 예에서는 myprojectns 로 설정된 네임스페이스 내에
직접 코딩을 하게 되면 외부의 소스에서는 접근할때에 ( extern 되어있다고 가정 )
myprojectns::g_nCount
myprojectns::fnA()
로 접근 할 수 있습니다.

다음은 이를 간단히 적용하기 위한 매크로 입니다.

// MyNamespace.h

#pragma once
#if defined(_LIB_SDK_PROJECT_Y)
#define MYNAMESPACE MYNAMESPACE_LIB_PROJECT_Y
#elif defined(_LIB_SDK_PROJECT_Z)
#define MYNAMESPACE MYNAMESPACE_LIB_PROJECT_Z
#else
#error MYNAMESPACE Required. Check MyNamespace.h
#endif
#define MN MYNAMESPACE 

#define _START_OF_INTERNAL_SRC  namespace MYNAMESPACE {using namespace MYNAMESPACE ;
#define _END_OF_INTERNAL_SRC  }
#define _SO_INTERNAL_SRC   _START_OF_INTERNAL_SRC  
#define _EO_INTERNAL_SRC   _END_OF_INTERNAL_SRC 

_LIB_SDK_PROJECT_Y 는 Project의 Properties 에서 설정한 Preprocessor definitions 입니다.
Project별로 다른 정의를 주어야하는 부분입니다.

위의 매크로는 Preprocessor definitions 에서 프로젝트 특성을 읽어
서로 다른 namespace 를 적용할 수 있도록 해줍니다.

예에서는 Preprocessor definitions 가
_LIB_SDK_PROJECT_Y 인경우 MYNAMESPACE_LIB_PROJECT_Y
_LIB_SDK_PROJECT_Z 인경우 MYNAMESPACE_LIB_PROJECT_Z
의 namespace 가 정의됩니다.

cpp 소스에서의 사용은 다음과 같습니다.

// _LIB_SDK_PROJECT_Y 의 소스일 때

#include <stdio.h>
#include "MyNamespace.h"

_SO_INTERNAL_SRC


VOID fnA()
{
...
}

BOOL fnB()
{
...
}

_EO_INTERNAL_SRC 

헤더파일을 포함하고, 소스의 위 아래를 _SO_ , _EO_  매크로로 감싸주면
헤더에 정의된 namespace 가 project 별로 적용됩니다.

외부에서 위 소스의 함수를 호출하고자 할때에는 다음과 같이 호출할 수 있습니다.
//_LIB_SDK_PROJECT_Y 라이브러리를 링크했을 때

#include <stdio.h>

void initialEntry()
{

MYNAMESPACE_LIB_PROJECT_Y::fnA();
MYNAMESPACE_LIB_PROJECT_Y::fnB();

}

혹은,
//_LIB_SDK_PROJECT_Y 라이브러리를 링크했을 때

#include <stdio.h>

using namespace MYNAMESPACE_LIB_PROJECT_Y;

void initialEntry()
{

fnA();
fnB();

}


외부 library 제작이 필요없는 실행파일 기반 프로젝트이거나
소형 프로젝트일 경우에는 namespace를 사용하지 않아도 될것 같습니다.

하지만, 여러명이 작업하는 프로젝트이거나 ( 소스별 extern function name conflict 문제 )
static library 를 만드는 프로젝트일 경우에는
사용할 필요성이 높아 보이는 부분입니다.

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

덧붙혀서,
매크로를 자세히 보신 분은 MYNAMESPACE 가 MN 으로 정의된걸 보셨을텐데요
이는 내부에서의 사용편의성을 위한 정의입니다.

가령, 배포용 라이브러리를 제작할때에
내부소스에서 사용되는 함수/변수들은 namespace를 주고,
extern 되는 함수에 대해서는
(사용편의성을 위해) namespace없이 unique한 이름으로 정의하는 경우
내부에서 사용되는 소스의 경우 _SO_, _EO_ 매크로를 사용하고,
외부에 extern 되는 소스는 _SO_, _EO_ 매크로의 사용없이
MN::fnA() 등과 같이 바로 접근할 수 있도록 정의한 부분입니다.

가령,
// extern source

#include <stdio.h>
#include "MyNamespace.h"

extern "C" void fnProjectInit()
{
MN::fnA();
}

( extern의 위치는 이해의 편의를 위해... )

lib 제작시 외부에 제공되는 함수는 위의 모습처럼 _SO_, _EO_ 없이 사용하고,
내부에서 다른소스의 함수를 가져다 쓰는 형태를 만들어주면,
외부에서는 namespace 없이 fnProjectInit()을 바로 호출할 수 있고,
소스의 내부에 정의된 함수나 변수이름등은 중복확률이 낮아지게 되는 효과를 갖게 됩니다.


원문 : http://www.techmixer.com/install-windows-vista-from-bootable-usb-flash-memory-drive/

Create a bootable Windows Vista on Flash Memory

1. Flash memory drive 를 FAT32 file system 으로 포멧

Windows Vista 가 설치된 PC에서 CMD.EXE 를 실행하여 다음의 명령어를 수행합니다.
( 아래는 USB 드라이브가 "disk 1" 인 경우입니다. 사전에 "list disk" 명령어를 사용하여, USB 의 장치 번호를 반드시 확인하세요 )

  1. diskpart
  2. select disk 1
  3. clean
  4. create partition primary
  5. select partition 1
  6. active
  7. format fs=fat32
  8. assign
  9. exit

2. Vista DVD 를 Flash Drive 로 복사

아래의 명령어를 사용하여, 비스타 DVD를 플래시 드라이브로 복사합니다. ( 비스타를 d: , USB가 e: 드라이브인 경우의 예 )

  • xcopy d:\*.* /s/e/f e:\

3. BIOS 설정에서 USB Drive 로 부팅을 설정

4. USB flash memory drive 로 부팅하여, Vista 를 설치


아웃룩으로 일정관리를 해왔는데,

하루에 수십통씩 메일이 오다보니
메일 저장 공간을 1년마다 분리해줘야 하는 불편함이 있었다.
( 분리를 하지 않으면 1Gb 가 넘는 저장공간에 느려지고 멈추고 막 그런다 아웃룩... )

다음으로, 구글으로 일정관리를 하려 했으나,
내 일정은 괜찮겠지만, 회사 일정이 타사의 DB에서 관리된다는
보안상의 취약점이 있어 포기해야했다.

그래서 찾게된 것이
ical 을 지원하는 웹베이스의 일정관리 프로그램 phpicalendar 되겠다.

ical 은 애플에서 지원되는 캘린더인데,
많이 유명한가보다.
아웃룩에서도 지원이되고, 구글 캘린더, 무슨 캘린더, 저런 캘린더 왠만한 캘린더에서는 다 지원한다.
이것이 가장 큰 장점.

즉, phpicalendar 를 사용하면,
자신의 서버에 ical 형식의 데이터를 두어,
웹에서 일정을 볼 수 있고,
사용자는 자신이 사용하기 편한 툴을 사용하여 일정을 갱신하면 된다.


다음은 지금 구축하고 있는 일정관리의 진행.


phpicalendar 를 설치하고 주의 일정을 웹상에 게시한 화면이다.
ical이 공유된 상태에서 자동으로 갱신된다.


ical 을 관리하고 공유하기 위해 사용하는 툴로는
windows calendar 를 사용하고 있다.
vista 에서 기본제공되는 프로그램으로
기능은 오피스보다 떨어지지만,
오피스보다 가볍다는 장점 하나만으로... 쓰고있다...

일단, 더 봐야하겠지만
ical은 플랫폼의 특성을 타지 않고 사용할 수 있다는
장점. 그 확장성으로 진행에 무리는 없을것 같다.


http://phpicalendar.net/

환경 :
  WindowsServer 2003
  Apache 2.x
  WebDav모듈사용.
  phpicalendar 2.24 설치


phpicalendar 2.24를 설치하고
한글테스트를 진행하였는데,
메인화면에서는 잘 표시되는 한글이
이벤트를 클릭하면 깨져서 표시된다.

이벤트를 출력해주는 소스파일은 다음과 같다
/phpcalendar2.24/includes/event.php

에디트 툴을 이용해서
해당 파일을 열고

$event['description']  = stripslashes(utf8_decode(urldecode($event['description'])));
$event['event_text'] = stripslashes(utf8_decode(urldecode($event['event_text'])));
$event['location'] = stripslashes(utf8_decode(urldecode($event['location'])));

위의 문장을 찾아 붉은색 부분을 삭제해 준다

$event['description']  = stripslashes((urldecode($event['description'])));
$event['event_text'] = stripslashes((urldecode($event['event_text'])));
$event['location'] = stripslashes((urldecode($event['location'])));

이처럼 수정하고, 저장후에
이벤트를 확인하면
한글이 정상적으로 출력되는것을 볼 수 있다.