코딩스탠다드, 정말 이리 빡셀 필요있나?

김포프 2012-03-01

이젠 피할 수 없는 진실이 되고 말았습니다. 사실 실력도 좋은데… 워낙 꽃미남이 되어놓으니… 비주얼로 자꾸 기억해주시는군요…. 뭐 사실은 사실 겸허하게 받아들이겠습니다… -_-

거부할 수 없는 진실은 힘들다.. 어쩌지 이제 잡지 표지모델 제의도 들어오는데…

왠만한 게임 회사에는 프로그래머가 준수해야하는 코딩스탠다드(코딩 스타일이라고도 하죠)가 있는 것 같습니다. 제가 여태까지 프로그래밍을 해오면서도 상당히 많은 코딩 스탠다드들을 봤는데요 (수백만장씩 팔린 패키지 게임에 사용한 엔진만도 5~6개 만져봤으니 뭐 온갖 꼴은 다 봤죠) 요즘들어 코딩스탠다드가 정말 이렇게 빡셀 필요가 있나 하는 의문이 들고 있답니다. (잡생각이 많죠.. 때로…)

우선, 대충 배경지식….. 코딩스타일에서 정의하는 것은 대충 다음과 같습니다.

  • 인덴테이션/줄바꿈
  • 빈칸의 사용
  • 변수이름 짓는 법
  • 함수이름 짓는 법
  • 주석다는 규칙
  • 등등…

코딩스타일의 존재이유?

결국 코딩스타일을 강제함으로 인해 회사에서 얻으려고 하는 건 가독성입니다. 코드 스타일을 통일시키면 다른 프로그래머의 코드를 읽을 때 쉽게 이해할 수 있고, 따라서 생산성을 높일 수 있다는 미신적인 믿음이 존재하죠.

이렇게 하면 프로그래머의 생산성이 높아진다는 부두교의 미신이 있다….. (믿거나 말거나)

코딩 스타일에서 정의하는 것들의 예

우선 코딩 스타일의 예부터…..

인덴테이션/줄바꿈

다음 형태 중에 어떤 놈을 이용할까? 하는 고민…

a)

for ( int i = 0; i < 10; ++i ) {
  sum += i;
}

b)

for ( int i = 0; i < 10; ++i )
{
    sum += i;
}

c)

for ( int i = 0; i < 10; ++i )    sum += i;

빈칸(white space)의 사용

대충 이런 것들 중에 어떤 놈을 써야하는지…

a)

int a = c * ( d + e );

b)

int a=c*(d+e);

등등

변수이름 짓는 법

단어별 대소문자, 멤버변수앞에 m 접두어를 붙이는지 등등…

a)

mMemberVariable = temp_variable * 2.0f;

b)

MemberVariable = tempVariable * 2.0f;

등등

함수이름 짓는 법

단어별 대소문자, private, public 대소문자 등등

a)

int MyClass::getNumPrivate();
int MyClass:GetNumPublic();
int do_something();

b)

int MyClass::_getNumPrivate();
int MyClass:getNumPublic();
int doSomething();

등등

주석다는 규칙

  • 클래스 선언 마다 주석을 달아야 하는가?
  • 함수 선언마다 주석을 달아야 하는가? 변수명 설명? 반환값 설명?
  • 그 외 어떤 코드에 주석을 달아야하는가?
  • 주석 달때 스타일은 어떤걸로? /* … */, //, ///, // 등등
  • 기타 잡다한 것들…

하지만 의문이 들다

저도 좀 뭔가 깔끔하게 정리되어 있는 걸 좋아하는 놈이라 한동안 이런 미신에 푹 빠져살았습니다. 그런데 최근 몇 년 동안에 '정말정형화된 코딩스타일이 생산성을 향상시키나?'하는 의문이 들더군요. (물론 게임업계에 한정된 이야기입니다. 의료업계에서는 계속 빡세게 해주세요… 수술대 올라갔다가 버그 때문에 뻗은 기계 때문에 죽긴 싫습니다… -_-)

사실 코딩 스타일이란게 종교와도 같은 것이어서 이렇다 할 정답이 없습니다. 프로그래머 10명 잡고 물어보면 다들 선호하는 코딩 스타일이 다릅니다. 일례로 함수이름만 들어도 어떤 프로그래머는 private 함수는 getNum() 이런식으로 작성하고 public 함수는 GetNum()이라고 작성하자고 하는 반면 다른 프로그래머는 get_num()GetNum()이라고 하자고도 할 겁니다.

어차피 회사란 집단체니까 그냥 일률적으로 정해놓고 프로그래머들을 다 강요하면 된다고 생각하는 건데… 정작 문제는 이 스타일로 개종해야하는 사람들에게는 이게 오히려 생산성 저하의 요소가 됩니다.

중요한건 프로그래머의 상식/배려/역량

그리고 참 웃겼던건.. 제가 지금까지 함께 작업했던 프로그래머만 해도 수백명인데… 그리고 이 엔진 저 엔진 옮겨다니면서 거친 코딩 스탠다드만도 대여섯은 될텐데….. 코딩 스탠다드하고 가독성은 정말 별 상관이 없었단 겁니다. 그보다는 오히려 어떤 코딩 스타일을 사용하던 간에 깨끗한 코드를 작성할 수 있는 프로그래머의 역량이 더 중요하더군요. 이런 분들이 대부분 이었습니다. 즉 굳이 코딩 스탠다드가 필요없는 인간들이 대부분…

회사에서 아무리 철저한 코딩 스탠다드를 만들어 놓아도 코드 드럽게 쓰는 애들(소수에 그칩니다)은 여전히 코드 이해 안되게 쓰더군요. 그래서 이런 애들을 좀 더 잘 관리하려고 코딩 스탠다드에 규칙을 더 추가합니다. 이러면 얘네들이 좀 나아질까요? 아닙니다. 얘네들이 코드가 드러운 이유가 있습니다. 남생각을 별로 안하거든요. 규칙이 얼마나 철저하던 간에 어떻게든 빠져나갑니다. 그 덕에 오히려 원래부터 깔끔한 코드 쓰던 사람들만 고생하죠. 이 사람들은 악법도 법이라고 존중하고, 다른 프로그래머들도 배려할 줄 아는 분들이므로 새로 생긴 규칙에 맞게 또 열심히 코드를 작성합니다. 이 규칙 없어도 원래부터 이해잘되는 깔끔한 코드를 작성하던 사람들인데 따라야 할 규칙만 늘어버렸죠.

이게 배려라는 거다…. 밥그릇 까지도 깔끔하게… (이미지 출처: http://garul.tistory.com)

결국 제값주고 산 놈들만 손해란 건가?

이렇게 생각을 하다보니…. 꼭 게임에 DRM 입히는거와 마찬가지란 생각이 들더라구요. DRM을 아무리 빡세게 입혀도 해적질 할 애들은 다 해적질하고 쓰니 아무 상관없는데, 정가내고 산 사람들만 그 DRM에 얽매여서 온갖 귀찮은 일을 다 당해야 하는….

차라리 개별적으로 갈구자. 짜르던가. 칼부림도 가끔?

결국 제가 내린 결론은 저희가 너무도 당연하게 여기며 쓰던 코딩 스탠다드가 생각보다 별로 효과적이지 않단 겁니다.

물론 코딩스탠다드를 싸그리 없애자는 건 아닙니다. 좀 최소한으로 줄이자는 거죠. 그리고 코드 드럽게 쓰는 애들을 개별적으로 갈궈서 좀 고치게 하던가… (인간이 직접 갈구는게 문서 던져주고 따라하라는 것보다 훨씬 효율적입니다… 칼부림이 가끔 날 뿐이지… -_-)…… 안되면 그냥 짜르던가….

이런 생각을 하게 된 또 다른 계기는 게임업계가 엄격한 코딩스타일이 필요한 분야가 아니란 겁니다. 어차피 코드작성한 건 다 내부적으로 쓰는거고, 문제 있으면 소스코드가 다 떡하니 있으니 아무나 가서 고칠 수 있으니까요. 게임업계가 아니라 미들웨어를 만들어서 판매하는 회사라던가 군사업체 및 의료장비에 들어가는 소프트웨어를 만드는 회사에서는 이게 좀 더 엄격해야겠죠. 미들웨어 회사는 라이브러리만 던져주는 경우가 많으니 그렇고, 군사업체 및 의료장비는 사람 생명이 걸린 일이라서 어쩌다 뭔 짓을 하더라도 버그를 아예 처음부터 만들지 않는게 중요하니까요. 어차피 게임이 엔터테인먼트 산업이고, 게임의 요구사항은 하루가 멀다하고 바뀌므로 차라리 유연하게 재빨리 코드를 작성할 수 있는게 게임 품질 향상에 더 기여한다고 봅니다. 게임의 품질이란건 사실 게이머가 느끼는 품질일 뿐이거든요. 인간의 목숨이 걸린 의료소프트웨어에서의 품질하고는 전혀 다르죠.

그냥 이정도면 하면 안될까요?

그래서 과연 '코딩스탠다드를 어디까지 줄일 수 있을까?' 하는 걸 좀 생각해봤죠. 이게 좀 간단해야 정작 남 배려할 줄 아는 프로그래머의 인생도 편해지지 않을까 해서….

위에서 들었던 목록을 한번씩 살펴보면서 이야기하죠.

인덴테이션

코드의 가독성을 위해서는 여전히 중요하다고 생각합니다. 특히나 코드의 scope를 보여주는데 도움이 되니까요. 근데 이제 Visual Studio 가 이런 인덴테이션을 직접 알아서 해주므로 크게 걱정할 필요가 없습니다. 20년 전에 이런 게 자동으로 안될때나 문제였지…

빈칸사용

뭐 이건 사실 int k = a * ( b + c );로 해주냐 int k=a*(b+c);로 해주냐 차인데… 어떻게 쓰던 코드 이해하는데 별 차이가 없습니다…. 굳이 목숨 걸 필요 없지 않나요? -_-

변수명/함수명

일단 멤버변수 이름앞에 m을 붙이니 public 함수는 대문자로 시작하니 마니 하는 건 이젠 별 의미가 없는거 같습니다. 어차피 IDE가 워낙 좋아져서 그냥 마우스만 올려도 나오는 경우가 많고 아니면 F12키 한번 누르면 곧바로 선언된데로 이동하니까요. 그리고 다시 돌아올땐 Ctrl + -키 누르면 끝이고… Visual Studio의 인텔리센스가 잘 작동안하면 Visual Assist 를 깔아도…..

단, 가독성을 위해 변수명이나 함수명을 잘 작성해주는 건 찬성입니다. 즉 int a = 1; 이라기보단 int numLoop = 1; 이란 식으로 변수명을 작성해주는거죠.. 딱 보면 이해가 되게… 함수명도 마찬가지고요.

주석다는 규칙

사실 주석달아야 할 곳에 안달아서 헷갈리는 경우도 많고, 달지 않아도 될 곳에 달아서 오히려 코드만 지저분해지는 경우 허다하죠… 이건 사실 어떻게 정의해도 코드 드러운 애들은 여전히 드럽고 코드 깔끔한 분들은 여전히 깔끔한.. 그런 부분…

저 개인적으로는

  1. 클래스 이름만 잘 정하면 굳이 클래스마다 주석을 달 필요가 없다. 이름보고 이해안될때만 기재.
  2. 함수/변수 이름만 잘 정하면 굳이 함수/변수마다 주석을 달 필요가 없다. 이름보고 이해 안되거나 변수의 반환값이 기묘할 떄만 기재.
  3. 코드에서 곧바로 이해되면 주석은 필요없다.
  4. 옆에 앉은 놈이 코드만 보고 곧바로 이해가 안되면 코드블럭 별로 그 위에 주석으로 기재 정도가 젤 난거 같습니다.

대충 정리

이렇게 써보고 보니 결국 제가 괜찮다고 생각하는 법은 코딩 스타일의 통일성을 유지하려고 괜히 쓸데없는 규칙을 만드는 대신에 개발자들의 상식을 믿으란 쪽이 되어버린듯…

어쨌든 제가 좋다고 생각하는 코딩스타일은 이것 정도입니다.

  • 변수명/함수명에 의미를 담을것
  • 코드의 스코프를 보여주기 위해 인덴테이션을 잘 할 것
  • 동료 프로그래머가 코드에서 곧바로 이해못할 만한 내용이면 코드 블럭 위해 간단히 주석을 달 것

개종 안하셔도 되요~

뭐, 다들 이러세요~ 라는 걸로 쓴 글은 아니고…. 그냥 한 번 생각해보시라고… 그리고 토론 좀 해보잔 의도로… (어차피 종교적인 토론이라… 난장판이 될 가능성이 높지만…-_-)