약 5개월 전에, define 전처리문에 대해서 썼습니다. 이번 시간에는 조건부 컴파일을 할 때 많이 써먹는, #if와 #ifdef에 대한 글을 써보도록 하겠습니다. 당연하게도, 백준 사이트에서도 많이 볼 수 있는 코드이기도 합니다.

 


 먼저 위 코드를 보겠습니다. 이상한 va_list라던지 va_start, vprintf, va_end가 나오지만, 여기에서는 중요하지 않습니다. 단지, 가변 인자를 처리하기 위해서 저런 것들을 썼다 정도만 보시면 되고요. 여기서 중요한 것은 13번째 줄의 #ifdef입니다. 이것은 무엇을 하는 것일까요? 위에 보니까 DEBUG라는 것이 정의가 되어 있지 않아요.

 

 

 아무 결과도 나타나지 않았습니다.

 

 

 반면에, 이 코드는 위에서 DEBUG라는 필드가 정의되어 있었습니다. 이 경우에는 vprintf가 호출이 됩니다.

 

 

 5 0.000100 is my foo라는 결과가 호출이 되어 버립니다. 이 구문이 많이 보이는 이유는, 사실 디버깅하기도 편하기 때문입니다. 그냥 일일히 printf 주석처리하고 주석 해제하고 할 필요가 없이, 위에서 DEBUG라는 것만 딱 한 번 정의해 주면 mprintf를 호출했을 때 디버그가 정의되었다면 상세한 정보가 출력이 될 거고, 그렇지 않으면 정보가 출력되지 않을 것이기 때문입니다.

 

 그러면 뒤에 오는 endif는 뭐 하는 녀석일까요?

 

 

 이 코드는 DEBUG가 정의되어 있지 않습니다. mprintf를 하였을 때 출력 결과를 보겠습니다.

 

 

 그러면, 1과 3만 출력이 되었음을 볼 수 있는데요. 이는 ifdef와 endif 사이에 있었던, 디버깅 결과를 출력하는 것과 2를 출력하는 문장이 수행되지 않았음을 의미합니다.

 


 그런데, 무언가가 정의되었다면 수행하는 전처리문 말고도, 0으로 정의되었다면, 1로 정의되었다면. 이렇게 특정한 조건을 가지고 처리를 해야 할 때가 있습니다. 예를 들어서, ENV가 local이면 포트를 몇 번 써야 하고, TEST면 포트 몇 번을 써야 하고, REAL이면 몇 번을 써야 한다는 것이 있을 겁니다. 배포하는 환경이 달라지면 포트를 몇 번을 물 것인가. 충분히 있을 수 있는 상황입니다.

 

 

 단순히 ifdef로만 처리를 한다면, 그것도 나쁘지는 않습니다. LOCAL이 정의되어 있으면 7770을, TEST가 정의되어 있으면 7775를, REAL이 정의되어 있으면 7780을 써라. 괜찮은 아이디어입니다만, 직관적으로 생각해 보면 뭔가 어색하다는 것을 알 수 있습니다. 왜냐하면, env는 어떠한 배포 환경에서 배포할 것인지 setting 된 것에 가깝기 때문입니다.

 

 즉, 이 경우에는 단순히 정의 되었느냐 보다는 배포해야 하는 환경이 A인가? 아니면 B인가? 아니면 C인가? 를 판단하는 것이 더 맞습니다. 즉, if, else 구조가 더 알맞습니다. 그러면, 우리는 해당 환경들을 1, 2, 3, ... 등으로 정의를 할 수 있습니다.

 

 

 그리고 7번째 줄에 ENV를 LOCAL로 정의했습니다. 4번째 줄부터 6번째 줄까지는 다른 헤더에 넣어두고 그 헤더를 include 하는 방식이 더 좋겠네요.

 

 

 순서도로 따지면, env가 LOCAL이면 7770을 쓸 거고, 그게 아니라 TEST면 7775를 쓸 거고, 그게 아니라 REAL이면 7780을 쓸 거다. 라는 의도가 명확하게 드러납니다. 그러면, 조건 처리기에서는 아래와 같이 작성해 주면 됩니다.

 

 

 여기서 주목해야 할 것은, ENV 값에 따라서 PORT를 다르게 정의했다는 것입니다.

 

 

 프로그램의 실행 결과는 위와 같습니다.