오늘 agile practices seminar를 다녀왔다. 전반적으로 여러가지 생각해 볼 만한 거리가 많았던 세미나였던 것 같다. 개인의 노력이 요구되는 것들 보다는 팀의, 더 나아가 고객과 팀의 협력과 노력이 필요한 부분이 많았기에 더욱 도전적인 과제이다.
TDD는 어렵다. 리팩토링도 어렵다. 많은 부분에 있어서 TDD를 시도하지만 스스로 도대체 어떤 테스트를 만들어야 할 지 몰라 그냥 진행할 때도 많다. 테스트 작성이 쉽지 않으면 당연히 리팩토링도 어렵다. 그러나 TDD와 리팩토링은, 나에게 있어서는 그나마 쉬운 agile method에 속했다. 개인적인 실천이 가능하기 때문이다.
오늘의 세미나를 계기로 가장 많이 생각해보게 된 주제는 '고객참여'와 'code ownership'이다. 각각의 주제에 대해 생각도 정리해볼 겸 간략하게 요약해보자(세미나 내용의 요약이 아니라 내 생각의 요약이다).
1. 고객참여
개발 프로세스에 고객을 참여시키는 것이다. 이 고객참여에는 여러가지 난관이 존재한다. 첫 째로, 고객이 참여하기를 원하지 않는 경우다. 약간의 게으른 고객을 예로 들 수 있겠는데(아마 정부쪽 과제가 이렇지 않을까 싶다), 신경도 안쓰고 있다가 마지막에 완성된 결과물만을 받기 원하는 경우다. 이 부분에 대해 고객참여가 개발에 필수적이라고 생각하는 내 이유는, '고객은 스스로 무엇을 원하는지 모르기 때문에 항상 확인시켜줘야 할 필요가 있다'는 것이다. 이럴 경우, 고객을 개발에 참여시키기 위해 어떻게 고객을 설득하느냐가 또 문제가 된다. 하지만 얘기가 길어질 것이므로 여기까지.
두 번째, 고객이 적극적으로 참여하지만 의도한 대로 움직이지 않는 경우다. 이 경우는 개인적으로 심각한 악례가 좀 있는 편인데, 고객(갑)이 개발사(을)를 '노예'로 취급하는 경우가 많다. 개발자의 출퇴근까지 관리하기를 원하고, 하물며 문제가 없는 상황에서도 개발자의 퇴근을 기분나빠한다. 구체적인 실례를 들자면, 얼마전까지 내가 투입되었던 과제에서는 고객이(고객사의 직원들이) 번갈아가며 개발자들을 감시하고 혹시나 퇴근하지 않았는지 확인한다. 매일매일 다음날 아침 해 뜰때까지 과중한 업무가 반복되는걸 고객이 당연하게 여기고 그것을 요구한다.
아무리 agile에서 제시하는 실천사항중에 잦은 릴리즈와 지속적인 test, 빠른 피드백이 있다지만, 주말포함 일주일에 5번씩 하는 릴리즈와 QA팀의 쉴 새 없는 검증, 개발자들의 실시간 응답을 기대하는 고객과는 일하는게 너무너무 힘들다. 실제로 나는, QA에서 언제든지 문제를 올리기만 하면 바로바로 응답하기 위해 상시대기하며, 문제가 하나라도 올라올 경우 실시간으로 응답하고 디버깅하면서, 또한 각각의 문제 수정이 이루어질때마다 곧바로 다시 QA가 검증에 들어가고, '검증 - 수정 - 릴리즈'의 반복이 밤샘으로 하루밤만에 5~6번씩 반복되는 과제에서 일했다. 또한 앞서 말했든 그러한 매일이 일주일에 최소 이틀, 많으면 5일까지도 발생했다. 고객이 그러한 것을 원했고, 고객이 원하는 일정은 언제나 '당장' 이었다. 고객은 필요 이상으로 적극적으로 개발에 참여하면서, 특정 모듈의 일정이 지연되면 그 모듈의 담당 엔지니어의 이름까지 거론해가며(내가 많이 당했다) 마녀사냥을 했다. 이런 고객과는 agile에서 말하는 '진짜' 고객참여는 이루어지기 힘들다.
이러한 상황이 나에게는, 특히나 나의 두 번째 경험과 같은 고객과 함께 일해야 할 때, 어떻게 agile을 실천할 수 있을지가 매우 도전적인 과제다.
2. Code ownership의 확산
오늘의 세미나에서 인상깊었던 문구중에 하나가 'That's not my job'이다. 회사가 한 사람 한 사람에게 professionalism을 요구할 때 발생할 수 있는 문제다. 한명의 엔지니어가 특정 모듈에 대해 너무 강한 ownership을 갖게되면, 그 모듈을 벗어나는 순간 그 일은 내 일이 아닌것이 된다. 오늘의 세미나에서 나왔던 말은 아니지만 개인적으로 인상깊게 느꼈던 문구중에 하나가 'who's wrong이 아니라 what's wrong을 고민하라' 였는데, 엔지니어가 모듈별로 ownership이 분산되면 문제가 발생했을 때 마녀사냥 - who's wrong? - 이 이루어지기 쉽다. 이는 엔지니어 개개인을 매우 방어적으로 만들고, 의견제시를 주저하게 만든다.
Non-agile한 상황, 그러니까 팀이 code ownership을 함께 공유하지 않는 경우 발생할 수 있는 또 하나의 문제는, 누구도 ownership을 갖지 않은 문제가 발생했을 때이다. 이런 문제는 기술적으로 해결이 쉽든 어렵든 불필요한 회의를 하게 만든다. 그리고 모두가 외친다. That's not my job. 앞서 언급한 문제와 동일하다고 생각할 지 모르지만 여기에는 한가지 추가적인 쟁점이 있다. 결국 문제는 문제이고 누군가는 해결해야 한다는 것이다. 그 이야기는 즉, 누군가는 추가적인 일이 부과된다는 것이다. 이런 상황에서는 일반적으로 해결책에 대한 아이디어를 먼저 제시한 사람이 문제를 떠안게 된다. 사람은 대부분 - 테레사 수녀같은 예외도 있겠다 - '나만' 고생하는 것을 싫어한다. 누군가 한명이 해결책을 제시하면 함께 숙고하고 발전시키기 보다는, '아, 그럼 되겠네. 말 꺼낸 사람이 해야지'가 되어버리는 것이다.
팀이 code ownership을 공유하는 경우는 이런 문제가 없다. 전체 코드에서 '내 코드'는 존재하지 않는다. 마찬가지로 '남의 코드' 또한 존재하지 않는다. 모든 것은 '우리의 코드'이며 '우리의 문제'이다. 이런 분위기는 의견 제시를 자유롭게 만든다. 내가 제시한 의견이 나를 불편하게 하지 않는다. 다른사람이 제시한 의견에 오류가 있다면 문제를 해결하기 위해 들어야 할 '내 노력'이 추가된다. 따라서 나는 항상 다른 팀원의 의견을 숙고하고 더 나른 방법이 없는지 고민해야 한다.
Code ownership이 팀 전체로 확산될 경우, 또 하나의 이득이 있다. 일반적으로 소프트웨어 엔지니어는 학습의 욕구가 강하다. 많은 경험을 해보아 고민없이 해결할 수 있는 문제는 별로 선호하지 않는다. 하나의 큰 시스템은 다양하고 복잡한 문제가 혼합되어 있기 때문에, 팀이 함께 모든것을 공유할 경우 이런 엔지니어 각각의 학습욕구를 충족시킬 수 있다.
Code ownership의 확산을 위한 방법으로, review되지 않은 코드는 repository에 merge되지 않도록 하는 시스템(e.g. gerrit)을 사용하는 것도 가능할 것 같다(Thanks to 재원). 팀이 함께 코드리뷰할 시간을 정기적으로 가지고, 팀이 동의한 코드가 repository에 merge되게 한다면 팀원 '개인의 죄'는 사라진다. 시스템에 문제가 발생했을 때 팀의 누구도 '너 때문이야' 라고 말하지 못한다. 그 코드에 대한 리뷰의 책임이 모두에게 있었기 때문이다.
코드리뷰는 귀찮다. 코드리뷰가 귀찮아서, '컴파일 되네? 돌려봐. 잘 돌아? 뭐 대충 멀쩡한거 같네. OK'와 같은 상황이 발생 할 수 있다. 이를 위해 떠오르는 해결방안은 역할 돌리기다. 아주 작은 스텝으로, 팀원은 코드를 교환한다. 어제는 내가 계산기의 덧셈연산을 만들었다면(물론 이정도로 작은 단위로 움직이진 않겠지만), 오늘은 다른사람이 곱셈을 만든다. 내일은 나눗셈을 만들기로 했다면, 누가 내일 나눗셈을 만들어야 할 지 모르므로, 오늘의 곱셈 리뷰에 모두가 적극적으로 참여해야 한다.
그러나 이 방법은 위험을 동반한다. 엔지니어라면 누구나 동의하지만 코딩이 매일매일 잘 되는 것이 아니다. 따라서 어제 리뷰를 열심히 했더라도 오늘 내가 맡은 부분에 진척이 없을 수도 있다. 그리고 그것이 내일 누군가에게 돌아갈 것이라고 기대한다면, 팀원은 다시 게을러 질 수 있다. 코드리뷰는, 여전히 어려운 문제다.
3. Pair Programming
서론부분에서 언급하진 않았지만 agile에서 협업의 대명사는 pair programming이다. 오늘의 세미나에서는 다른 팀원에 비해 performance가 뛰어난 일부의 팀원이 pair programming을 거부할 경우 어떻게 할 것인가에 대한 질문이 있었다. 패널들의 다양한 의견이 있었지만 패널의 의견은 배포되는 세미나 자료를 통해서 다시 볼 수 있을거 같아 여기서는 내 생각을 정리하도록 한다.
일단 performance가 뛰어난 팀원이 pair programming을 거부하는 이유를 생각해보자. 가장 큰 이유는 pair programming으로 인해 자신의 개발속도가 더뎌진다고 느끼는 것이다. 혼자하면 더 빠를텐데, 파트너가 고민하는 사이 자신은 모든 답을 내어놓을 수 있고, 코딩도 내가 더 빠르다. 파트너의 '왜 그렇죠?'라는 질문이 반복될 경우 짜증을 느낄 수도 있다.
그러나 한가지 다행인점은, 진짜 못된 사람은 별로 없다는 것이다. 정말 성격이상이고 독불장군이라 pair programming은 죽어도 못해먹겠다고 주장하는 사람은 거의 없다. 일반적으로는 혼자 작업하는 것에 비해 갑갑함을 느끼고 짜증날 뿐이다. 이 경우에는, 적어도 내 생각에는 해결책이 있다.
먼저 임의로 경험많고 performance가 뛰어난 팀원을 senior, 그렇지 못한 팀원을 junior라고 표현하자. 소프트웨어는 기술적으로 변화가 심한 분야라서, senior라 할 지라도 모든 것을 알고있는 엔지니어는 없다. junior는, 아무리 경험이 부족하더라도 정말 아무것도 모르지는 않는다. 일반적인 경우 정말 아무것도 모른다면 엔지니어도 아닐 뿐더러 한 회사에 들어가는 것 자체가 불가능 했을 것이라고 보는게 옳다. 따라서 내가 제시하는 한 가지 방법은, senior를 그가 경험하지 못한 부분을 작업하고 있는 junior에게 붙이는 것이다. 이 경우 구지 pair programming을 언급할 필요는 없다. '안해본 거지만 당신은 실력이 좋으니깐 잘 할거야. 좀 도와줘'라고 말한다면, '나는 다른사람 도와주는 것 따위엔 흥미 없어요'라고 말할 사람 몇 되지 않는다. 진짜로 그런 사람이 있다면, 아무리 performance가 좋더라도 차라리 팀에 없는것이 이롭다.
말했듯이, 일반적으로 소프트웨어 엔지니어는 학습욕구가 매우 강하다. performance가 뛰어난 엔지니어라면 더욱 그러할 것이라고 예상할 수 있다. 학습욕구가 강하지 않았다면 실력이 좋을 수는 없는것이니까 말이다. '안해본 거지만 당신은 실력이 좋으니깐 잘 할거야. 좀 도와줘'라는 말은 senior 엔지니어에게 후배를 도와주겠다는 선의와 함께, 호기심을 자극할 수 있다. 소프트웨어는 언제나 경험해 보지 못한, 신기술에 목말라하는 사람들이기 때문이다.
그리고 이런 조합이 이끌어내는 또 하나의 장점이 있다. 나같이 성격 참 부담없고 맘 편한 사람은 문제가 없을지 모르지만, 전문분야의 senior를 붙여준다면 junior 엔지니어는 시험치는 기분을 느낄 수도 있다. 그리고 필요 이상으로 의존하게 된다. 어차피 내가 생각한 것보다 더 나은 훌륭한 아이디어를 이사람이 언제나 가지고 있을 것이라 무조건 적으로 믿어버린다면, pair programming의 의미가 사라진다. 아무리 실력 좋은 엔지니어라 하더라도, 처음 해보는 것이라면 이것저것 모를 수도 있다는 생각이 오히려 junior를 편하게 만들어 줄 수도 있다. 이는, 자유로운 의견 제시와 토론으로 이어질 것이다.
여기까지가 오늘의 세미나에서 나에게 던져진 생각할 과제였다. 하나하나 어렵지 않은 주제가 없으니, 역시 많은 사람들의 아이디어와 토론이 필요해 보인다.