»
S
I
D
E
B
A
R
«
[나쁜 팀 문화] 너는 생각할 필요 없어. 생각은 나 혼자..
Dec 11th, 2009 by Wegra Lee

내가 최근 과제를 진행하면서 가장 불만이 많았던 문화 중 하나로, 간단히 이야기하면 소수의 누군가가 생각해서 가이드를 만들고 다수의 사람들에게 기계적으로 적용하는 문화이다. 얼핏 생각에 괜찮은 어프로치로 생각될 수 있고, 심지어 권장되는 상황도 많다. 하지만 잘못 남발하면 부작용이 큼을 몸소 느꼈기에 주의하자는 차원에서 정리해보았다.

시작..

우리 팀은 ‘아키텍트(Architect)’라는 멋진 이름의 조직을 갖추고 있다. 이름에 걸맞게 팀내 주요 아키텍쳐적 이슈들을 논의하고 해결안을 찾아 지침을 내려준다. 팀원들도 나름 팀내에서 선별된 사람들로 구성되어 있다. 여기까지만 보면 문제가 있기는 커녕 모범적이라 할 수 있다.

하지만 아키텍트 그룹이 내놓은 가이드의 상당수가 많은 헛점을 보여왔다. 지침대로 적용을 하려던 개발자들로부터 많은 공격을 받아 갈팡질팡하고 번복되기 일쑤였다. 아키텍트들의 결정에 대한 신뢰가 점점 떨어졌고, 개발자들 사이에서는 ‘최대한 늦게 적용하는게 좋다’ 라는 말까지 공공연히 오고가기도 했다.

무엇이 문제였을까? 단순히 아키텍트들의 실력이 부족해서는 아니었다. 이런 현상이 발생할 수 밖에 없었던 상황을 나름 조명해보았다.

팀 환경/문화

팀의 아키텍트 그룹이 제 역할을 하지 못하게 된 데에는 수많은 문제들이 복합적으로 작용한 것으로 보인다. 팀의 전반적인 상황은 지금까지 기술되었던 (그리고 앞으로 더 추가될) 모든 Bad Team Culture 시리즈[1]의 종합 선물세트라 보면 된다. 빠른 진행을 위해 간략히 요점을 정리해보았다.

우리 팀은 거의 항상 무리한 일정에 맞추기 위해 과속 주행을 해왔다. 산적한 모든 일들이 최상의 시나리오대로 완료되어야만 한다. 그 시나리오도 실무자가 아닌 윗선에서 정한 deadline 에 기반한다. 팀 창설 이래 단 한 번도 deadline 에 맞춰본 역사가 없음에도 항시 같은 패턴이다.

거의 모든 아키텍트들의 주 업무는 사실 관리다. 이들은 대부분 서브팀의 리더들로, 자신의 서브팀 업무 처리로도 이미 숨이 벅차다. 더구나 이들은 개발 실무를 담당할 여력도 없다. 큰 그림의 아키텍처나 팀원들이 제기한 구현 상의 이슈에 대해 의사 결정은 참여하지만 직접 구현에 참여하거나 팀원들이 작성한 소스를 살펴보진 못한다.

개발자들 역시 발등에 떨어진 업무들로 다른 논의에 참여할 마음의 여유를 갖지 못한다. 구현 하나만으로도 일정이 빠듯한데, 각종 요청들이 ‘가능한 빨리’ 라는 수식어와 함께 동시 다발적으로 날아온다. 코드 리뷰나 리펙토링 같은 사치스런 용어는 책속에서나 볼 수 있을 뿐이다.

다수 모듈에 적용되는 공통 가이드에 대해서도 깊이 있는 논의와 충분한 공유 대신, ‘일주일 내로 모두 적용해!’ 와 같은 명령이 떨어진다. 가이드 자체도 결함 없는 완벽한 것이라는 이상적 결과를 기준으로 한다. 보완책으로 일부 모듈을 대표로 적용해보기도 하지만 서브팀 내에서의 커뮤니케이션도 부족한 상황에서 도메인이 다른 특정 모듈이 전체를 대표하리란 기대는 품지 않는 것이 좋다.

부작용과 악영향

결과는 아주 부정적이다.

‘아키텍트 = 관리자’ 이므로 논의가 계속 산으로 간다. 한국적 정서상의 문제도 있겠지만, 회의의 비효율성을 불평하면서도 둘을 분리하지 못한다. 어떤 회의에서건 두 이슈가 마구 섞여 논의되므로, 소수의 전담 아키텍트(non-관리자)는 진행 상황조차 파악하기 어려울 때도 많다. 예를 들어, 잠시 묻혀 있던 이슈를 결론짓기 위해 꺼내놓으면 ‘아! 그거 지난번 관리회의에서 x로 결정해서 a, b, c 가 진행중이야.’ 라는 이야기를 아무렇지도 않게 들려준다. 그러면서 전담 아키텍트이니 아크 이슈들을 추적 조율하라는 모순적인 요구를 한다.

팀 전체의 상황을 고루 파악하고 있는 아키텍트가 없다. 다른 서브팀의 상황까지 신경쓸 여유가 없으므로, 아키텍트 회의가 소집되어도 자신의 팀과 직접적으로 관련되어있지 않다면 잘 참석하지 않는다. 충분한 사전 조사와 깊은 논의 없이, 모인 사람만으로 쉽게쉽게 결론을 내는 경향이 생겨 추후 번복의 여지가 많다. 일부 모듈을 대표로 선정해 해결책을 검증해 보더라도, 다른 모듈에는 대대적 칼질을 요하는 경우가 많았고, 가끔은 적용 과정에서 지침을 수정해야만 하는 counter example 이 나오기도 한다.

General 아키텍트의 고뇌.. 에피소드

이러한 상황에서도 어쩔 수 없이 아키텍트로써의 일을 수행하며 개인적으로 많은 고충들을 겪었다. 다른 아키텍트들 대부분은 자신의 분야에 대해서만 직접적인 책임을 지는데 반해, 나는 어지간한 이슈들에는 다 끼어 들어가야 했다. 즉 general 아키텍트였고.. 팀에 단 한 명 뿐이었다.

그러는 와중, 여러 모듈에 걸친 가이드를 만들어야 하는 업무들이 자주 떨어졌다. 나름 최선의 안을 내보려 노력하지만, 결정 과정에서는 언제나 trade off 가 발생한다. 특히나 논의 단계에서의 실무자 참여를 배제하는 상황에서는 수많은 추측과 가정들 위에서 이리저리 저울질을 하게된다. 중간중간 상황을 공지하지만 관심을 주는 사람은 거의 없다. 관심 좀 가져달라고 애원을 해야 한 두 명 답변을 준다. 실무자들을 참여시켜달라는 요청에는 그들은 시급한 다른 일로 시간이 없다는 답변만이 메아리칠 뿐이다.

어찌저찌 가이드를 만들어 공지하지만, 본격적인 일은 이 때부터다. 가이드를 만들면 매니저는 N 일 내로 가이드를 적용하라고 공지한다. 그제서야 드디어 실무자들의 피드백들이 쏟아지기 시작한다. 질문이 터져나오고, 문제점을 지적하고, 나아가 대안을 제시하기도 한다. 개발자들의 성향과 경험이 다양한 만큼 다양한 안들이 나올 수 있다. 대부분은 사전 고려된 안들이기어, 그들들에게 trade off 와 이러저런 상황 요소를 열심히 설명한다. 결국 논리와 양해로 설득을 한다 치더라도 가이드와는 다른 이야기들이 오고가기 시작하면 개발자들은 우왕좌왕 하기 시작하고, 정리된 하나의 안으로 재공지될 때까지 자신의 모듈에 적용하는 것을 미루려 한다. 정리되는듯 싶다가도, 늦게서야 적용하는 모듈 때문에 또 한바탕 소란이 벌어지기도 한다.

묵묵히 가이드를 잘 따르는 것 역시 그리 좋지 않다. 대부분의 가이드는 이상 추구보다는 현실 수용적이다. 과제 초기라면 누가봐도 깔끔한 가이드를 제시하며 떳떳해할 수 있겠지만 현실은 너무도 다르다. 수년에 걸쳐 이미 수십만 라인의 코드를 만들어놨고, 개발자들을 릴리즈 일정에 쫓기고, 다수의 레거시 모듈들을 버무려야 하는 상황인 것이다. 그렇다면 변경량이 적고 에러 유발 가능성이 적으면서 그럭저럭 봐줄만한 절충안을 내놓을 수 밖에 없다. (싹 뜯어 고치자 하면 기획팀/매니저들이 동의하지 않는다.) 내가 봐도 부끄러운 가이드를 던져주면서 사람들이 뭐라고 생각할 지 걱정한 적도 있다. 실력있는 사람들은 보자마자 훨씬 좋은 방법들이 머릿속에 떠올릴 수 있었을 것이고, 그렇지 않은 사람들에겐 그닥 좋지 않은 가이드를 익히게 만든 것이다. 결과로 만들어진 가이드 자체는 부족하더라도, 그 결론까지의 여러 대안들을 연구/분석하고 장단점을 저울질하는 과정을 함께 한다면 모두의 역량 향상에 큰 도움이 됐을 것이지만, 안타깝게도 그럴 시간은 주어지지 않았다.

그나마 현 상황을 함께 겪고 있는 지금의 동료들은 부족함을 이해해 주겠지만, 나중에 합류한 사람들은 어떨까? 결과물만 보고 전임자의 무능함을 욕해도 딱히 비난할 수도 없다. 그리고 그 제품이 세상에 공개된다면? 이력에 적어 넣기도 부끄럽고, 공백기로 둘 수도 없는 계륵 경력이 되어버린다.

가정 자체가 틀어질 때도 있다. 한 번은 개발자들이 도메인에 익숙하지 않고 영향 범위가 제법 크다는 가정으로 2~3주에 걸쳐 좀 억지스러운 가이드를 만들었다. 첫 설명회에서 모두들 ‘우린 그런 문제 없어.’, ‘해당 사항이 거의 없으니 조금만 신경쓰면 충분히 할 수 있을 거 같아.’ 라는 반응들이 것이다. 그 자리에서 바로 정석적인 방식으로 진행키로 결정하고 그에 맞게 약간의 보강 설명을 해주는 것으로 설명회를 마무리했다. 2~3주의 시간을 쓸데 없이 허비한 꼴이 되었다. ‘사전 조사해서 상황을 파악해달라’ 는 초창기 요청에는 한 두 모듈만 피드백을 주었고, 그래서  ’모듈별로 실무자들을 한 명씩만 배정해달라’는 몇 차례의 요청 역시 묵살되었던 케이스였다.

아키텍트 시절 초기에는 의욕을 불태워봤지만, 나의 개선 요구들이 매번 거절당하면서 점차 회의를 느끼게 되었다.

다시 돌아가..

이런 현상의 더 근본적인 원인은 지도층의 마인드 때문이 아닐까 싶다. 리더가 아닌 매니저(관리자) 중심[2]의 팀이라, 중장기 비전을 위한 팀원들의 역량 향상보다는 눈앞의 단기 목표 달성을 최우선시한다. 심지어 팀원 역량 개발은 관리자의 롤에서 배제시키기도 한다. 같은 맥락에서, 소수의 핵심 멤버가 의사를 결정하고 그 외의 다수는 기계적으로 구현만 하면 된다고 얘기하는 것도 가끔 들을 수 있었다.

물론 윗사람들 모두가 이렇지는 않다. 어쩌면 대부분은 단지 정신없는 일정 압박에 어쩔 수 없이 끌려가고 있을 수도 있다. 하지만 일부는 분명 위와 같이 생각하고 있고, 그들의 힘이 강하게 작용하고 있다.

100% 틀렸다고 얘기하는 것도 역시 아니다. 상황에 따라선 이런 어프로치가 도움이 될 때도 있다. 단발성 프로젝트라던가, 초단기로 1차 결과물을 내놓아야 한다던가, 너무나도 자기 주장이 강한 독불장군들이 모인 팀이라던가, 명확한 스팩/설계의 외주 과제라던가, 누구나 인정하는 천제 아키텍트가 이끌고 있다던가 등 다양한 상황들이 떠오른다. 심지어 커뮤니케이션만 잘 이루어진다면 보통의 팀에서도 크게 문제될 것이 없다. 하지만 어설프게 머리를 정하고 권한을 주기에 앞서 팀의 모습을 세심히 살펴보도록 하자.

그리고 앞으로 몇 년 몇 십년을 이 분야에 종사해야 할 지 모르는데 나의 미래에는 아무런 관심도 없는 상사를 만났다고 생각해보자. 변화의 여지가 보이지 않는다면, 오래 함께하고픈 타입은 아닐 것이다. 소프트웨어는 사람이 머리로 만드는 것임을 잊지 않기를 바란다. 지금의 아주 일부만이라도 미래를 위해 투자하자. 팀원을 키우라는 이야기다.

p.s. 이 주제는 정말 오랫동안 수정에 수정을 거듭했다. 아무리 고치고 고쳐봐도 내가 진정 하고픈 말을 정확하고 효과적으로 표현하지 못하겠다. 여전히 맘에 들지 않는 상태이지만.. 언제까지고 고치고만 있는 것도 지겨워서 포스팅한다.


References

  1. [나쁜 팀 문화] 시리즈 (wegra.org)
  2. 리더 vs. 매니저 (wegra.org)
[나쁜 팀 문화] 점진적 지연
Nov 19th, 2009 by Wegra Lee

점진적 지연이란 아주 짧은 간격으로 릴리스 날짜를 조금씩 미루는 행태를 뜻한다. 일단 릴리스를 시도해보고, 안되면 조금  (보통 1~3일) 미룬 후 다시 시도한다. 역시 잘 안되면 또 다시 미룬 후 시도한다. 이렇게 릴리스가 될 때까지 무한 반복하는 릴리스 관리 방식이다.

사례

내가 경험해본 최악의 상황은 이러했다. 원래의 릴리스 목표일은 금요일이다. 금요일이 되어서 시도를 해보았으나, 도저히 릴리스할 만큼의 품질이 나오지 않는다. 그래서 월요일로 목표를 바꾼다. 월요일에도 역시 원하는 품질에 도달하지 못했다. 다음날 다시 한 번 시도해보기로 한다. 마찬가지로 실패했다. 이와 늦은거 금요일로 다시 미룬다. 금요일도 여전히 실패.. 토요일.. 월요일.. 수요일.. 금요일.. 월요일.. 화요일.. 토요일.. ..

이런 식으로 가장 길게는 6주간 계속 릴리스만 한 경우도 있었다. 릴리스가 이렇게 한달 가량 지연되면 당연히 다음 릴리스에 일정에 지장을 주게 된다. 새로운 기능을 추가하는데 필요한 최소 시간이 있으므로 차례차례로 전체 일정이 연기된다. 하지만 다음 릴리스 시점에 와서도 크게 다르지 않다. 역시 또 몇 주의 지연이 발생한다. 그래서 ‘릴리스가 끝나면 (다음) 릴리스 일정이 바뀐다’, ‘릴리스가 되는 날이 릴리스 날이다 (역: 릴리스 날에 릴리스를 한다)’ 라는 말까지 하게 되었다.

위의 경우는 continuous integration (CI) 도 도입되지 않은 열악한 환경에서의 상황이었고(도입을 요구했지만 관심 갖는 사람이 없었음), 그 후 CI 가 도입되면서 상황은 많이 호전되었다. 하지만 여전히 제 때 릴리스 되는 경우는 전무했고.. 심한 경우 3주가 밀리기도 했다. 금요일 릴리스를 (주말을 열심히 일해서) 그 다음주 월요일 저녁에 할 수 있다면 대단히 이례적인 성공이 케이스가 될 정도였다.

악효과

Incremental Delay 가 팀 문화처럼 정착되면서 다음과 같은 부작용들이 나타나기 시작했다.

팀원들은 윗선에서 정한 릴리스 날짜(deadline)에 큰 의미를 부여하지 않게 되었다. 한 차례도 성공적으로 릴리스한 경험이 없으며, 릴리스가 연기되어도 아무 일도 발생하지 않음이 학습되었기 때문이다. 꼭 지켜져야하는 중요한 릴리스라 강조해도 마음속으론 ‘어짜피 안될걸..’이란 생각을 자연스레 하게된다.

서브팀별 개발 일정이 꼬이기 시작한다. 팀별로 이터레이션(iteration) 주어진 일의 양이나 생산성, 예측 정확성 등의 차이가 생겨 발생하는 현상으로.. 일부 팀은 일정에 맞춰 일을 끝내놓고 다음 릴리스를 위해 할 일을 준비하고 있다. 하지만 곧 될 듯 말 듯 하면서 릴리스는 기약없이 지연된다. 처음엔 2~3일 후면 될 거라 기대하고 잠시 쉬던 것이 하루 이틀씩 밀리면서 결국 이 주 삼 주 동안 제대로 진행할 수 없게 된다. 이런 경험이 잦아지면서 일부에선 중간중간에 변경된 코드를 밀어 넣는다. 다음 릴리스를 위한 개발 코드 브랜치와 (지연중인) 릴리스 브랜치 간에 코드 격차가 심해져, 개발 브랜치에서 해결된 문제를 릴리스 브랜치에 반영하는데 한참을 씨름하기도 한다.

윗선도 계속되는 릴리스 관련회의로 시간을 낭비하기는 마찬가지다. 현황을 파악하고, 얼마나 더 지연시킬 지 정하고, 지연이 미치는 영향을 분석하고, 이왕 지연된 것 미리 구현된 간단한 기능을 포함시킬 지 논의하고.. 자료를 준비해 더 윗선이나 마케팅, 기획, 운영(예산) 팀 등과도 계속 조율을 해야 한다.
야근과 주말 근무가 늘어난다. 일주일 단위로만 지연시켜도 호흡 조절과 재충전이 가능하겠으나, 지연 단위가 보통 1~3일 정도이고, 특히나 금요일 일정은 반드시 토/일/월로 지연된다.

고찰

무엇하나 좋을 게 없는 이런 비합리적 문화가 왜 개선되지 않는 것일까?

이런 현상이 반복되고 있음은 윗선에서 과제가 어떻게 돌아가고 있는지 전혀 파악하지 못하고 있다는 확실한 반증이다. 릴리스를 하기 위해 해야할 일이 얼마만큼 남아 있는지 도통 감이 없다. 개발자들의 생산성과 문제 해결능력에 대한 어떠한 정량적/경험적 데이터도 갖춰져 있지 못하다. 개발자 각각이 지금 무슨 일들로 얼만큼의 로드가 걸려있는지도 잘 파악이 안되고 있다. 해결해야할 문제들이 얼마만큼의 노력이 들어가야 하는지도 역시 감이 없다. 아직 드러나지 않은 문제들은 또 얼마나 될 지 역시 예상하기 어렵다. 결국 위에서 할 수 있는 말은 보통 ‘언제까지 이 문제들을 해결해라’ 정도에서 그친다.

제품의 설계나 코드의 품질이 크게 떨어지거나, 다뤄야할 대상을 개발자들의 완벽하게 이해하지 못하고 있을 경우 사태는 더 심각해진다. 분석하고 수정하는데 필요한 시간을 예측하기 힘들고, 수정시 부작용(side-effect)이 따를 가능성이 높다. 동작 여부만이 아니라 코드의 품질을 챙기는 개발 문화를 조성해야 하고, 서로 간의 잦은 리뷰를 통해 다른 팀원들과 개발 패턴, 노하우 등을 공유해야 한다.

관련 개발팀간 커뮤니케이션 효율성도 큰 영향을 미친다. 심한 경우는 핵심 모듈을 전혀 다른 팀에서 관리하고 있고, 우리 과제를 지원하는 것은 그 팀의 최우선 역할이 아닐 때이다(실제로 자주 접해보았다). 유관 팀들이 지리적으로 멀리 떨어져 있고, 원격지에선 문제를 재현하기 어려울 때도 마찬가지.. 어떠한 경우건 커뮤니케이션 지연은 일의 진행 속도를 현저히 떨어뜨리는 주요 원인이 된다. 과제를 기획하고 팀을 조직할 때 그 과제와 팀이 적시에 충분한 지원을 받을 수 있도록 고려해야 한다. 필요하다면 조직 구성을 바꿔 같은 명령 계통 내로 흡수할 필요도 있다.

미흡한 인프라에 의한 불확실성도 크다. 기본적인 테스트 자동화 시스템도 갖추지 못해 매번 개발자들이 수동으로 테스트하는 것도 많이 보아왔다. 나름 도입한 continuous integration 이 기껏 빌드만 해주고 기본적인 unit test 도 수행하지 못한는 경우를 상상해보자. 내가 경험한 어떤 팀은 unit test 를 CI 에 통합해달라는 요청을 한 지 1년이 넘도록 반영하지 못했다. 다른 자동화는 물론 말할 것도 없었다. 과제 규모가 커질 수록 그에 걸맞게 인프라 효율성에도 투자를 해야한다. 발등에 떨어진 일정에만 쫒겨 제때 투자를 못하면 일을 해야할 정작 개발자들의 시간을 어먼 곳에 낭비하게 만든다.

개발 문화와 생산성 향상, 효율성, 팀웍에 대한 인식이 부족하다. 위에서 가장 중요시 하는 것은 언제 릴리스 되는가이다. 어떤 때는 그것 외에는 전혀 관심이 없는 것 같다는 인상을 받곤 한다. 일벌레인 사람들이 지배하는 조직에서 더 심한 경향이 있는 것 같다. 종종 일찍 퇴근하고 싶어하는 사람을 이해하지 못하는 듯한 발언을 듣기도 한다. 아무래도 사람은 자신의 기준에서 남을 이해하는 성향이 있으니, 어찌보면 당연한 것일 수 있다. 하지만 사람(뿐 아니라 모든 생물)은 기계와 달리 충분한 휴식 없이는 높은 집중력과 생산성을 유지할 수 없음을 주지시켜야 한다.

[개발자 역량] 주석.. 다느냐 마느냐 그것이 문제로다
Oct 7th, 2009 by Wegra Lee

(특히) 팀으로써 소프트웨어를 개발하다보면 주석을 잘 달라는 이야기를 자주 듣는다. 하지만 반대로 주석이 필요없는 코드를 짜라는 이야기 역시 심심치 않게 들려온다. 얼핏 생각하기엔 서로 모순되는 주장 같기도 한 두 가이드들에 대해  정확히 이해해보고, 또 좋은 주석을 달기 위한 팁과 고려 사항들까지 일부 정리해보도록 하겠다.

주석의 역사

이야기를 시작하기 전에 주석에는 어떤 종류가 있는지부터 명확히 해야 하는데, 주석의 역사에서 시작하는 것이 자연스러울듯 하다.

놀랍게도(?) 태초의 소프트웨어 코드에는 주석이란 개념이 아얘 없었다. 그도 그럴 것이 종이카드에 0011000 구멍 뚫어서 프로그램하던 시절에 주석을 삽입한다는 것은 사치일뿐 아니라 기술적인 도적이었다. ^^ 이 시절 펜으로 종이 위에 이것저것 적어놓던 것이 주석의 시작이라고 보면 된다. (사실 이 부분은 직접 경험해보진 않아서 추측성임)

컴파일러(사실 전처리기)가 주석을 인식하기 시작한 것은 당연히 소스 코드를 디지털화시킨 이후이다. 이마저도 처음엔 지금과 같은 형태는 아니었다. 초창기 언어들은 주로 line by line 으로 해석되었기 때문에 주석 역시 single-line 형태가 먼저 등장했다. 복잡한 인터페이스 설명이나 알고리즘 설명 같은 것보다는 영역/블록 구분과 간단한 커맨트 중심이어서 그리 불편하지 않았다. 그 후 등장한 multi-line 주석은 편집 편의성 증대를 위한 욕구 해결 정도여서 전혀 신선하지도 혁신적이지도 않았다.

Java가 등장하면서 (최초인지는 모름) API 문서 생성 ‘표준’ 툴(Javadoc)을 SDK 가 내장하기 시작하였고, 이는 주석의 개념을 한 단개 발전(not 혁신)시키는 계기가 되었다. Javadoc 의 특징이라면 ‘스펙 기술용 주석‘과 ‘구현 설명용 주석‘을 명백히 구분하기 시작한 것이다. 물론 그 전부터 주석을 구분해 사용하고는 있었지만, 언어의 표준적인 방식으로 도입했다는 것이 큰 의미가 있다.

이를 계기로 주석에 대한 인식은 한층 개선하였고, 그 후 등장하는 대부분의 언어들도 같은 어프로치를 취하게 되었다. 하지만 아직까지 컴파일러는 스펙/구현 가리지 않고 모든 주석을 무시하였고, 스펙을 얻어내려면 별도의 툴을 돌려야만 하였다. 이는 ‘스펙 기술’ 이라는 오늘날에 있어 아주 중대한 개념을 ‘주석’ 이라는 사소한 범주에 함께 묶는 한계에서 아직 벗어나지 못했음을 의미한다.

이에 대한 개선은 최근 Noop 언어 프로젝트를 통해 가시화되고 있다. Noop 의 여러 특징 중 ‘Executable documentation that’s never out-of-date’ 는 주석을 프로그래밍 언어 스펙에 포함시키고 컴파일러가 컴파일 워닝/에러와 같은 수준에서 직접 핸들링한다는 의미이다. 형식적으로는 거의 변화가 없지만, 주석의 위상은 거의 코드 수준까지 격상되게 된다.

나아가 annotation 이라는 개념이 추가된다. Annotation 을 주석으로 한데 묶는데는 의 아해할 사람들이 있을 수 있겠으나, 수행 코드가 아니라는 점에서 주석의 범주에 속한다. 더구나 annotation 의 한글 해석 자체가 ‘주석( 달기)’이다. ^^ (Noop 에서 annotation 을 어떻게 처리할 지는 명시적인 언급은 없다.)

주석의 중요성이 점차 커지는 것은 소프트웨어 산업의 변화 과정을 봤을 때 아주 자연스러운 결과이다. 개인이 다룰 수 있던 작은 소프트웨어에서, 이제는 수백 수천명이 수년에 걸쳐 만들고, 완전히 없어지기까지 또 수년이 더 필요한 수준까지 변화하였기 때문에, 공간과 시간을 초월한 개발자간의 커뮤니케이션이 그만큼 중요해진 것이다.

주석의 분류

이쯤에서 현재 우리가 주석이라 부를 수 있는 것들에는 어떠한 것들이 있는지 다시 정리해보자.

  • 문서화 주석 – API 명세(specification) 기술을 주목적으로 하며, 해당 소프트웨어를 black box 로 바라보는 제3의 개발자와의 커뮤니케이션을 담당한다.
  • Annotation 주석 – 코드를 처리하는 툴들에게 특정 지시를 내리는 주석으로, 이를 인식할 수 있는 툴에게만 의미가 있다. 툴의 목적에 따라 다양한 용도로 응용될 수 있다.
    또한 팀원간에 정해진 약속으로 사용하기도 좋다. 대표적인 사례로는 @todo @fixme 같은 것이 있다.
  • 구현 주석 – 내부 구현에 대한 주석으로 여타의 툴들에서는 완전히 무시된다. 이해하기 어려운 코드에 대한 설명, 추가로 해야할 일, 코드 수정 시 주의점 등, 코드 레벨에서 직접 봐야하는 개발자들 간의 디테일하고, 종종 자질구레한 커뮤니케이션을 담당한다.

이처럼 현재까지는 크게 3 가지의 대표적인 주석이 있으며, 소프트웨어 산업이 변화하면서 앞으로도 기존 주석이 변화/갈라지거나 새로운 형태의 주석이 추가될 것이다.

상세한 주석 vs. 주석이 필요 없는 코드

“상세한 주석이 좋다.” – 주로 문서화 주석에 해당하는 지침이다. 제공하는 소프트웨어 모듈의 동작 명세는 가능한 모든 케이스에 대해 명확하게 설명해 주는 것이 좋다.

“주석이 필요 없도록 코딩하라.” – 주로 구현 주석에 해당하는 지침이다. 구현 주석이 있다는 것은 코드만으론 의미 전달이 불충분하다는 반증이므로, 가능한 코드를 명확히 작성하여 구현 주석 없이 읽고 이해할 수 있게 하는 것이 좋다.

보통은 위와 같이 받아들이면 되지만, 반대의 경우도 얼마든지 있다.

문서화 주석이 최소화 되도록 코딩하라.” – 이는 문서화 주석을 생략하라는 의미보다, ‘문서화 주석에서 군더더기 설명이 필요 없도록 API 를 명확하게 만들라’ 정도로 이해해야 한다. 문서 없이 API 만 봤을 때 오해의 소지가 있다거나, 다양한 예외 상황이 존재하거나, 한 API 를 너무 다목적으로 사용할 수 있다거나, pre/post 조건을 주렁주렁 달고 있는 API 들은 이 가이드를 제대로 지키지 못한 예들이다.

“상세한 구현 주석이 좋다” – 어쩔 수 없이 구현 주석이 필요할 시에는 명확하고 상세한 설명을 달라는 의미이다. 최적화를 위해 어쩔 수 없이 복잡한 코드를 작성했다거나, 컨트롤 밖에 있는 외부 종속성 때문에 비효율적인 구조를 가져갈 수 밖에 없었다거나, 일정 등의 이유로 임시 코드를 넣어놨거나 일부 기능을 구현해놓지 않은 상황에서는 상세한 주석을 달아주어야 한다. (이 주석을 보게될 사람이 자신뿐이라는 가정은 절대 하지 말라.)

좋은 주석 작성을 위한 팁

좋은 주석 작성 팁까지 집대성 해놓으면 최고의 글이 되겠지만.. 이 글의 범주에서는 제외하도록 하겠다. (다른 누군가 집대성 해주시거나, 이미 잘 되어 있는 좋은 링크들을 보내주시면 해피할텐데 ㅎ)

  • 문서화 주석 작성에 대한 가이드는 표준화 단체에서 공개하고 있는 것이 많이 있다. 적어도 문서화가 잘 된 유명 플랫폼/라이브러리 등은 찾을 수 있다. 자신의 도메인과 가장 유사한 가이드를 찾아 적용해보는 것은 좋은 시작이 될 것이다. (e.g. Requirements for Writing Java API Specifications)
  • Annotation 주석 활용 – 같은 목적의 주석들에 동일 키워드를 사용하는 방법으로, annotation 이 정식으로 지원되지 않더라도 전혀 문제는 없다. 가장 추상화된 @todo (더 해야할 일) 부터 시작해서 @fixme (명백한 결함), @review (리뷰 커맨트), @pending (미결사항), @thread (스레드 안정성 보장 필요), @dependon (특정 기능/이슈 종속적 – 해당 기능/이슈 해결 후 일괄 검토 요구) 등 상황에 따라 적절히 응용하면 최소한의 주석으로 커뮤니케이션 효과를 극대화시킬 수 있다.
  • Aspect 를 고려한 코드 영역 구분 – 코드를 작성하다 보면 로그 작성, 접근 권한 체크, 멀티 스레딩을 위한 락 처리, 에러 처리, 부하 조정, 캐시 사용 등등 비즈니스 로직과 직접적으로 관련되지 않은 로직들로 코드가 지저분해지기 쉽다. 이 문제를 다루기 위해 Aspect Oriented 언어를 사용하는 방법도 있지만, 여건이 되지 않는 경우엔 어쩔 수 없이 모든 로직을 한데 몰아 두어야 한다. 이럴 때에는 아쉬운데로 부가적인 로직 처리 블럭과 비즈니스 로직 블럭을 구분해주는 안을 적용해볼 수 있다. 동일 룰이 코드 전반에 일괄적으로 적용되어 있다면, 코드를 보는 사람들은 목적에 맞는 코드 블럭만 정확히 찾아 검토할 수 있다.
    영역 구분을 위한 구현 주석이 필요할 수도 있지만, 그 외 구현 주석의 필요성을 감소시켜주는 효과가 있다.
  • 예외 처리 코드 주의 – 한 눈에 들어올 간단한 로직도 과도한 예외 처리가 가미되면 금새 난해한 코드로 둔갑한다. (필요악이라 할 수 있는 예외에 대한 다양하고 심도있는 관점은 C++ Exceptions: Pros and Cons 을 참조하기 바란다.) 가장 선행되어야 하는 노력은 물론 ‘불필요한 예외가 발생하지 않도록 설계’하는 것이고, 꼭 필요한 예외에 대해서 일반 로직과 명확히 구분되는 형태로 처리해주는 것이 좋다. 예를 들어 예외 발생 여부 확인을 위해 전용 매크로를 정의해 ‘if’ 절을 사용을 피하는 것도 한 방법이다. ‘if’ 절은 일반 로직에서도 등장하기 때문에 로직을 따라가다 rollback 하여 다시 시작하게 만든다.
  • 읽을 수 있는 코드 작성 – 당연하지만 너무 일반적인 가이드이다. 수많은 종속 팁들이 있을 수 있지만 너무 길어질듯 하여 생략한다. (Developer Capacities – Writing Program 참조)

결론

주석을 주석으로만 취급하는 시대는 끝났다(끝내야 한다^^). 하지만 아직도 대부분의 개발자들 주석에 대한 인식은 가볍기만 하고, 진정한 가치와 중요성을  제대로 교육/훈련시키는 모습은 찾아보기 쉽지 않다.

이제부터라도 주석과 관련한 명확한 개념 정리와, 용도별 좋은 주석 작성을 위한 가이드를 정리해 소프트웨어 입문 초기부터 익히고 생활화할 수 있도록 지도해야 한다. 지금과 같은 소셜 개발 시대에서 훌륭한 개발자가 되려면 시공간을 넘나드는 4차원적인 커뮤니케이션 능력도 갖춰야 한다.

»  Substance: WordPress   »  Style: Ahren Ahimsa