블로그


Youngrok Pak at 10 years, 8 months ago.

블로그 태그를 붙인 글을 최신 순으로. 좀더 개인적인 글은 일기장에. 블로그 글 전체 목록은 내 글 모음에.


개발자가 모자라요

개발자가 모자라요#

개발자라는 직업 특성상(?) 다양한 회사들을 만나고 다니다보니 꽤나 자주 들려오는 이야기가 있다. 개발자가 모자라요. 근데 이것도 크게 보면 두 가지 종류가 있다. 스타트업이 개발자를 제대로 구하지 못해서, 혹은 구한 개발자를 붙들어두지 못해서 개발자 공백 상태가 되는 경우. 그리고 또 하나는 개발팀을 그런대로 확보해놓았지만 그 개발팀의 생산성이 만족스럽지 않은 경우. 두 경우의 공통점도 있는데, 그건 개발자가 모자라는 것이 현상이지 원인이 아니라는 것이다. 그래서 https://twitter.com/pakyoungrok/status/296225395940921344 이런 트윗도 날렸었고. 근데 이 트윗에 대한 반응을 보면 주로 전자 쪽에 집중되는 것 같다. 물론 전자도 이미 SNS에서 여러 사람의 글로 화제가 되었고 심각한 문제임은 틀림 없지만, 이미 많은 사람들이 다루었으니 나는 오늘 후자 쪽에 초점을 맞춰보려고 한다.

좀 풀어서 설명하면 이런 경우다. 회사가 투자를 받거나, 혹은 매출을 내거나 해서 그럭저럭 유지가 되는 상황이라 개발자들 월급도 제대로 줄 수 있고, 개발자도 적지 않게 뽑아놓았다. 개발자의 머리 수는 적지 않다. 그런데, CEO를 비롯한 많은 부서에서 쏟아내는 요청들을 개발팀이 다 감당하지 못해서 여러 부서에서 한 목소리로 "개발팀이 안 받쳐줘서 아무 것도 못해요"라고 외친다. 개발팀도 매일매일 바쁘게 일하지만 밀려드는 일을 감당하지 못해 일을 해결하는 속도보다 쌓여가는 속도가 훨씬 높고, 개발 속도도 덩달아 점점 느려진다. 다른 부서들은 개발팀을 비난하고, 개발팀은 점점 방어적으로 변해간다.

이런 일은 회사 규모와 상관 없이 일어난다. 내가 아는 바로 6명 짜리 회사도 겪고 있고, 500명 짜리 회사도 겪고 있는 문제다. 사실 개발자 품귀현상 문제도 이 문제와 관련이 있다. 이런 회사는 개발자를 붙들어둘 수도 없고, 좋은 개발자를 데려올 수도 없기 때문이다. 다른 부서로부터 매일같이 비난의 눈초리를 받는 개발팀에 오래 머물고 싶은 사람이 누가 있겠는가? 밥줄 때문에 버티고 있는 것 뿐이지.

더 골(The Goal)#

그럼 이 문제는 왜 일어나는가? 그리고 이 문제는 해결 가능한 문제인가?

물론 해결 가능하다. 이 문제는 이미 인류의 지성이 정복한 바 있는 문제다. 다만, 그 지성이 아직 충분히 확산되지 않았기 때문에 해결하지 못한 조직이 많은 것이다. 아, 그렇다고 이게 당신의 조직이 해결할 수 있는 문제라는 뜻은 아니다. 페르마의 정리는 이미 수학자들이 정복한 문제지만, 그렇다고 니가 그 문제를 풀 수 있는 건 아니지 않은가. 이 문제는 비록 해법이 쉽고 단순하지만 정말로 이걸 실행할 수 있는 조직은 극히 드물다. 뭐 그렇다고 실행 난이도가 엄청 높다거나 그런 건 아니고, 대개의 경우 CEO가 이런 변화를 받아들이지 못하기 때문이다. 에시당초 CEO가 이 문제에 대한 개념이 있으면 이런 문제는 발생하지도 않겠지.

그럼 그 쉽고 단순하다는 해답은 무엇인가? 더 골이다. 옛날 같으면 링크 걸어줬으니 책 읽어보셈, 하고 끝냈겠지만, 오늘은 시간이 많으니 좀 상세히 적어보려고 한다.

핵심은 병목자원 관리다. 병목자원이란 최종 제품으로 나오는 공정 중에서 생산성이 가장 낮은 공정이다. 이런 병목자원이 있을 때는 병목 자원을 중심으로 프로세스를 짜야 한다. 요는 병목자원에서의 시간 낭비를 제거하는 것이다. 낭비를 제거하는 건 당연하잖아 할 수도 있는데, 중요한 건 병목자원의 시간 낭비만 제거하는 것이다. 심지어 다른 공정에는 시간을 더 낭비하게 되더라도 상관 없다. 아니, 병목자원의 시간 낭비를 제거하려고 하면 거의 필연적으로 다른 공정에서는 낭비가 발생한다. 하지만 그래도 해야 한다.

낭비 제거의 포인트는 크게 두 가지. 하나는 병목자원이 대기하는 시간이 생기지 않도록 하는 것이고, 다른 하나는 병목자원에서 불필요한 일을 처리하지 않는 것이다. 이 두 가지를 충분히 해놓고 나서 병목자원의 생산성을 높이는 방안을 강구해야 한다. 이 두 가지가 안되면 병목자원을 확장해도 대개 소용 없다. 

이 문제를 개발팀 문제로 치환해보자. 일단 개발팀이 안 받쳐준다는 이야기가 나온다는 것은 개발팀이 병목자원이라는 뜻이다. 사실 개발팀이 얽혀야 하는 대부분의 조직에서 병목자원은 개발팀이다. 개발자가 10명이든 100명이든 개발팀이 병목이 아닌 회사는 드물고, 또 개발팀이 병목이 아니라면 그 회사는 더 큰 문제가 있는 건지도 모른다. 그래서, 개발팀을 병목자원이라고 놓고 다시 문제를 보자.

 #

병목자원의 시간을 어떻게 낭비하게 되는가#

우선 개발팀이 어떤 식으로 시간을 낭비하게 되는지를 보자. 위의 두 가지 중 첫번째를 개발에 대입하면, 개발하기에 필요한 정보가 충분치 않아서 개발자가 개발을 진행할 수 없어서 답변을 기다리면서 대기하는 상태이다. 디자인이 늦게 오거나, 세부기획에 빠진 부분이 있거나, 요구사항이 불명확하거나 등등. 이 문제를 한 마디로 설명한다면 "완벽한 기획서가 존재하지 않기 때문"이다. 개발자의 책상 앞에 기획서를 수북히 쌓아놓지만 개발자는 그 기획서만으로 개발할 수 없다. 디테일은 늘 빠져있게 마련이다. 그럼 개발하면서 계속 이 기획을 낸 사람과 커뮤니케이션을 해서 필요한 정보를 공급 받아야 한다. 그런데, 그 기획자가 이 프로젝트만 하고 있고, 개발자 옆에 딱 붙어 있어서 필요할 때 바로바로 의문을 해결해줄 수 있으면 되는데, 그런 경우는 드물다. 기획이 CEO에서 나오는 경우도 있고, 기획만 전담하는 사람이 아니라 다른 핵심 업무가 있는 부서에서 나오는 경우도 많기 때문이다. 이를테면 영업 부서에서 영업에 필요한 기능을 개발팀에 요청한 경우를 보자. 영업팀의 요청사항이 자세할 리는 없다. 개발자가 보고 개발하다보면 계속 영업팀에 물어봐야 한다. 그런데, 영업팀이니까 영업하느라 바빠서 개발자의 질문에 바로바로 답해주지 못한다. 그럼 그만큼 개발이 늦어지는 것이다.

기획 전담팀이 있어도 마찬가지다. 개발팀의 생산성 문제가 대두된 상황이니만큼 기획자가 만든 기획서는 바로바로 개발되지 않을 것이다. 그럼 기획자는 시간이 남으니까 새로운 기획을 또 하게 되고 개발자의 책상에는 또 새로운 기획서가 쌓인다. 그럼 개발자 앞에 쌓인 재고가 늘어나니까 다른 부서의 요청들은 더 대기시간이 길어진다.

이런 문제를 제대로 이해하고 있는 사람은 드물다. 이를테면 이런 식이다. 개발자는 지금 주어진 기획서를 개발하느라 여념이 없다. 근데 기획서에는 지금 검색조건을 입력하는 인터페이스에 대한 설명이 부족하다. 그래서 개발자가 그 부분에 대한 설명을 기획자에게 요청하려는데 기획자는 다른 일 하느라고 답이 늦어져서 개발이 지체된다. 기다리다 못한 개발자는 다른 업무로 잠시 전환했는데, 그러느라 컨텐스트 전환 비용이 소모된다. 근데 그런 찰나 기획자가 찾아온다. 그래서 필요한 정보를 물어보려는데 기획자가 이미 개발된 기능 중에 하나를 다르게 바꿔달라고 한다. 어, 아직 유저한테 deploy되지도 않은 기능인데? 기획자가 생각이 바뀌었댄다. 온 김에 기획자에게 검색조건 인터페이스를 물어보려고 하니 그건 놔두고 일단 자기가 지금 요청한 거 먼저 해달라고 한다.

자, 여기서 기획자는 무슨 짓을 저지른 것일까? 일단 병목자원의 가동을 멈추게 만들었다. 개발자가 1시간 기다리면 전체 일정이 1시간 늦어진다. 기획자는 1시간을 놀든 하루를 놀든 개발자에게 필요한 정보만 제 때 주면 일정에는 영향을 미치지 않는다. 하지만 기획자는 자기가 개발되길 기다리는 시간이나 개발자가 필요한 정보를 얻기 위해 기다리는 시간이나 같은 가치라고 생각한다. 동등한 사람인데 시간의 가치는 같겠지. 하지만 두 사람의 시간의 가치는 같지 않다. 개발에 필요한 정보를 제때 공급하는 것이야말로 생산성의 핵심이다.

이것만이 아니다. 기획자는 아직 제품화되지 않은 기능의 수정을 요청했다. 제품화는 되지 않았지만 개발이 완료된 기능은 다른 말로 하면 병목자원을 한 번 통과한 기능이다. 그런 기능을 수정한다는 것은 앞서 병목자원을 통과한 시간을 그냥 낭비했다는 것이다. 제품화되서 사용자의 검증도 받기 전에 바꿔버렸다는 것은 불필요한 재고를 생산했다는 것이다. 심지어 그 재고를 생산하기 위해 병목자원의 시간까지 썼으므로 이 기획자가 낭비한 시간은 엄청난 것이다. 이것은 병목자원 낭비의 두번째 케이스다. 덤으로 새로운 재고까지 쌓아서 다른 재고의 리드 타임마저 떨어뜨렸다.

이처럼 별 것 아닌 것 같은 일상적인 기획자의 행동이 개발팀의 생산성을 크게 낭비한다. 이것이 "개발팀이 제 때 제 때 개발해주지 않아요"라고 불평하는 조직에서 일상적으로 일어나는 일이다.

 #

병목자원의 시간을 낭비하지 않게 일하는 법#

그럼 어떻게 일해야 병목자원, 곧 개발팀의 시간을 낭비하지 않게 할 수 있는가? 제일 중요한 것은 개발자는 기다리는 시간이 없어야 한다는 것이다. 이게 온전히 가능하려면 어쩔 수 없이 다른 사람이 기다려야 한다. 예를 들어, 기획팀이 A 프로젝트의 기획서를 개발팀에 넘겨준 상태라고 가정해보자. 개발팀은 다른 할 일들이 쌓여 있으니 이 기획서를 당장 수행할 수 없다. 그럼 기획팀은 손이 빈다. 이 때 손이 빈다고 다른 프로젝트를 시작하면 악몽의 시작이다. 이게 중요하다. 개발팀이 A 프로젝트를 시작하기 전까지 아무 것도 하지 말아야 한다. 설령 뭔가를 하더라도 개발팀의 작업 리스트에 또다른 리스트를 올려놓아서는 안된다.

그럼 개발팀이 A 프로젝트를 이제 시작했다고 해보자. 그럼 기획팀은 무엇을 해야 하는가? 마찬가지다. 아무 것도 하지 말아야 한다. 해야 하는 일은 단 하나, 개발팀의 요청에 신속하게 응대하는 것이다. 개발팀이 A 프로젝트를 개발하는데 도움이 되는 일 외에는 아무 것도 하지 말아야 한다. 물론 그러면 기획팀의 시간은 낭비된다. 하지만 이건 상관 없다. 전체 생산성에 영향을 주지 않기 때문이다. 전체 일정에 영향을 주는 요소는 오로지 병목자원의 시간이다. 이것이 핵심이다.

영업팀이나 CEO, 고객지원팀 등에서 요청하고 싶을 때는 어떨까? 마찬가지다. 개발팀이 개발을 시작하면 영업하러 나가지 말고 대기해야 한다. 안 그러면 당신이 요청한 기능은 영원히 완성되지 않을 것이다. 근데 여기서 하지 말아야 할 것 하나는 요청한 사람이 개발자를 재촉하러 오는 것이다. 개발자의 생산성을 심각하게 떨어뜨린다. 자신이 급할 때 개발자에게 가지 말고, 개발자가 필요할 때 가야 한다. 쉽게 말해서 개발팀에 기능을 하나 요청했고, 개발팀이 일단 그 기능을 개발하기로 OK했다면, 그 다음부터는 개발자가 호출할 때까지 얌전히 대기해야 하고, 개발자가 호출하면 즉시 응답해줘야 한다. 이게 제대로 되어야 병목자원 관리를 제대로 하는 팀이라고 할 수 있다.

아니 같은 인간인데 왜 개발자의 시간만 중요하냐고 항변할 수도 있겠다. 정치적으로 모든 사람의 시간은 동등한 가치가 있고, 경제적으로는 각자의 수입과 비례하는 기회비용으로 따질 수 있겠지만, 프로젝트의 관점에서는 병목자원의 시간은 비병목자원과 100배 이런 차이가 아니라 1과 0의 차이다. 비병목자원 수백 명의 시간보다 병목자원 한 명의 시간이 더 중요하다.

 

비병목자원의 활용#

병목자원 관리의 첫번째 포인트가 대기시간의 제거라면, 두번째 포인트는 병목자원에서 불필요한 일을 제거하는 것이다. 불필요한 일은 두 가지다. 하나는 아예 할 가치가 없는 일이고, 또 하나는 프로젝트에는 필요한 일이지만 병목자원을 통과하지 않고 처리할 수 있는 일이다. 여기서 첫번째 아예 할 가치가 없는 일은 사실 해보기 전엔 알 수 없으므로 초점을 맞춰야 하는 것은 병목자원을 통과하지 않아도 되는 일을 식별해내는 것이다. 그러니까, 개발자가 안해도 되는 일은 최대한 다른 팀에서 처리해야 한다는 것이다. 이것도 두 가지 포인트를 잡을 수 있는데, 하나는 개발자가 어드민 시스템을 잘 만들어줘서 되도록 어드민 작업을 개발자의 도움 없이 할 수 있게 해주는 것이다. 물론, 개발자가 이런 어드민 시스템을 만들 시간은 줘야겠지. 또 하나는, 개발자가 하고 있는 업무 중에서 일반인(?)이 할 수 있는 업무는 최대한 다른 팀이 가져가는 것이다. 이건 창의력이 좀 필요하다.

전에 소셜커머스에서 일할 때의 예를 들면 이런 것이다. 소셜커머스에서 대개는 하나의 딜에 하나의 상품이 있지만, 여러 개의 상품이 있는 경우도 있고, 상품별로 가격은 다르게 책정할 수 있다. 그런데, 부가 옵션은 상품별로 붙일 수 없다. 그러면 이 딜은 현재 시스템으로 소화할 수 없고, 상품별로 옵션을 붙일 수 있는 기능을 개발해야 한다. 하지만 이런 종류의 딜은 드물기 때문에 이 딜 하나를 위해 시스템을 개발하기엔 다른 더 중요한 일이 너무 많고, 데이터베이스 설계도 유연하게 되어 있지 않아서 변경 비용이 크다. 이런 경우에 보통의 회사라면 그래도 개발자가 이 기능을 추가로 개발하도록 만들 것이다. 하지만, 그 때 내가 선택한 방법은 딜을 여러 개로 분리하는 것이었다. 아예 분리된 별개의 딜인 것처럼 올려서 처리해버리면 어드민에서 입력하는 사람은 좀더 일이 많아지겠지만, 개발 비용은 추가로 들어가지 않는다. 상품별로 링크를 걸어두면 되니까 딜 판매량에도 영향을 주지 않는다. 아마도 각 회사의 업무에 따라 이런 식으로 개발이 필요한 일 같지만 개발하지 않고 넘길 수 있는 경우가 아주 많을 것이다. 이런 방법을 찾아내는 것도 개발팀이 아니라 다른 팀에서 해주면 더욱 좋고.

이런 복잡한 일만 있는 건 아니다. 사소한 일도 도와줄 수 있다. 이를테면 기획팀이 할 일이 없다면 개발팀에 와서 개발자들이 하고 있는 잡무를 도와줄 수도 있다. 어찌되었건 비개발자가 1시간을 들여서 개발자의 1분을 절약해줄 수 있는 일이라면 뭐든지 팀에 보탬이 되는 것이다. 물론, 이렇게까지 할 수 있는 팀웍을 갖춘 팀은 매우 드물겠지.

 

일거리의 선별#

자, 그럼 개발자의 시간 낭비를 최소한으로 줄이는데 성공했다. 다른 부서들도 모두 개발팀을 중심으로 사고하는데 익숙해졌고, 프로세스는 개발팀을 중심으로 돌아가기 시작했다. 그러면 산처럼 쌓여 있던 많은 일들이 착착 진행될까? 아닐 것이다. 여기서 하나 더 생각해야 할 것이 있다. 어떠한 개발자도 생각하는 속도보다 더 빠르게 개발할 수는 없다는 것.

이게 왜 중요할까? 그런 조직이 겪는 문제 중에 중요한 것은 개발팀이 할 일의 분량 자체가 너무 많다는 것이다. 부서마다 다 자신들의 아이디어를 쏟아내서 개발팀의 작업 큐에 쌓아버리면 어떤 개발팀도 감당할 수 없다. 생각의 속도는 엄청나게 빠른 반면, 개발 속도는 생각하는 속도의 수백 배에서 수백만 배로 느리기 때문이다. 그 어떤 개발자도 생각의 속도를 온전히 작업 속도에 반영할 수 없다.

그러므로 마인드 자체가 생각나는 아이디어를 모두 실행한다가 아니라 고도로 필터링하고 정제된 아이디어를 실행하는 것으로 바뀌어야 한다. 문제는 이것이 스타트업의 문화와 안 맞는 것으로 보이기 쉽다는 것이다. 스타트업에는 실행이 가장 중요하다. 떠오르는 아이디어를 열심히 정제하는 것보다 바로바로 실행에 옮겨서 반응을 보는 게 중요한 것도 사실이다. 그리고, proof of concept에 성공한 스타트업들도 아이디어를 정제하는데 많은 시간을 쓰기보다 바로바로 실행에 옮기는 것을 중시했다. 그럼 어떻게든 개발팀은 모든 부서의 아이디어를 실현할 수 있도록 병목자원의 생산성을 증가시켜야 하는 것 아닐까?

이것이 바로 proof of concept에 성공한 스타트업의 착각이다. 이런 말이 있다. 기업에서 가장 위험한 것은 왜 성공했는지 모르고 성공하는 것이라고. 떠오르는 아이디어를 바로 실행에 옮기는 것이 스타트업의 핵심 성공 요인임은 분명하다. 그러나, 그것만이 아니다. 그게 효과를 볼 수 있었던 것은 떠오르는 아이디어의 종류가 적었고, 모든 멤버들이 그 아이디어를 실행하는데 집중할 수 있었기 때문이다. 초기에는 모든 사람이 한 가지 핵심에 집중하게 마련이다. 그런 상황에서 나오는 아이디어 역시 잘 포커싱되어 있다. 그런데, proof of concept가 되고 매출을 성장시키기 시작한 회사에도 이 방식이 들어맞을 것인가? 당연히 불가능하다. 이제 사람 수도 많고 부서도 많고, 이해관계도 복잡하다. 당연히 이 많은 사람들에게서 나오는 요구들은 핵심에 잘 집중되어 있지도 않고, 아이디어의 종류도, 개수도 많다. 이 모든 것을 소화할 수 있는 개발팀을 구축하는 것은 이미 물리적으로 불가능한 상황이 된 것이다.

이런 상황에서 개발팀이 예전처럼 요청을 다 소화해주기를 바라는데 개발팀은 그렇게 할 수 없으니 "개발팀이 안 받쳐줘서 아무 것도 못해요" 같은 소리가 나오는 것이다. 개발팀이 안 받쳐주면 개발팀이 받쳐주는 만큼 일을 주어야 한다. 아니, 사실은 그보다 더 적게 주어야 한다. 그래야 스스로를 개선해가면서 개발 속도를 올릴 수 있기 때문이다. 그런데, 그런 점은 감안하지 않고 모든 부서에서 중구난방으로 개발팀에 요청을 쏟아내면 개발팀은 중요한 일을 구분할 수 없게 되고 점점 중요하지 않은 일에 시간을 소비하면서 중요한 일을 해내는 속도는 더 느려지는 것이다. 그러니까, 개발팀이 아무 것도 할 수 없게 만드는 건 바로 무작위로 요청을 쏟아내는 다른 팀들인 것이다.

그래서 정말 proof of concept 전처럼 기민하게 움직이고 싶다면 그때처럼 충분히 핵심에 집중할 수 있는 상황도 같이 만들어줘야 한다. 아이디어를 무작정 쏟아낼 게 아니라 잘 정제해서 꼭 필요한 일들만 병목자원을 통과시켜야 한다. 

안타까운 일이지만 proof of concept도 하기 전의 스타트업들도 이런 식으로 무작위적인 아이디어를 쏟아내는 경우가 많다. 마치 개발자를 CEO의 아이디어를 실현해주는 사람 취급을 하는 것이다. CEO가 머리 속으로 이것저것 떠오르는대로 다 개발자에게 전달하면 아주 작은 팀도 위와 같은 문제를 그대로 발생시키게 된다. 아니, 사실 이 경우는 훨씬 심각하다. 성공할 가능성 자체를 낮춰버리기 때문이다.

린 스타트업도 기민하게 움직이기를 요구하지만 아무 아이디어나 생각나는대로 실행하라는 게 아니다. 치밀하게 가설을 세우고, 그 가설을 검증할 수 있는 작업만 하는 것이 린 스타트업이다. 가설을 검증하는데 도움이 되지 않는 일은 1그램도 하지 말아야 한다. 이런 린 스타트업의 방식을 유지할 수 있다면 기업이 작든 크든, proof of concept를 해냈든 아니든 기민하게 움직일 수 있다. 

 

기능조직의 문제#

그런데, 여기서 이런 일이 일어나는 좀더 근본적인 원인을 파고들어보고 싶다. 왜! 다른 조직들은 마치 개발팀의 생산성을 저하시키는 게 목표라도 되는 것처럼 행동하는가? 그들은 나쁜 사람들이라서? 아니면 머리가 나빠서? 단지 더 골을 읽지 않았기 때문에? 난 그렇게 생각하지 않는다. 역량의 차이가 크지 않은 팀의 경우에도 개발팀과 매우 조화롭게 협업해내는 경우가 많이 있다. 그리고 나는 개발팀이 안 받쳐줘서 아무 것도 못한다고 투덜대는 모든 회사들에게서 아주 강력한 공통점을 발견했다. 그것은 기능조직이라는 것이다. 더 많이 세분화된 기능조직일수록 이 현상은 더 심하다.

기능조직의 문제는 크게 두 가지다. 하나는 포커스가 안된다는 것. 기능별로 분리되어 있으니 개발팀은 여러 가지 업무를 맡게 될 수 밖에 없다. 한 개발자가 여러 업무를 맡게 되는 것도 이런 조직에선 자연스럽다. 그러니 개발자는 당면 프로젝트에 집중하기 어렵고, 개별 프로젝트에 대한 이해도도 떨어진다. 업무를 요청한 쪽도 마찬가지로, 개발팀이 지금 어떤 업무들을 하고 있는지 모르니까 자신들의 요청을 우선적으로 처리해달라고 요청할 수 밖에 없다. 그러니까 모든 부서가 다 자신들의 일을 최우선으로 해달라고 요구하게 되고, 그 중에 어딘가는 낮은 우선순위를 배정받을 수 밖에 없으니 개발팀의 퍼포먼스에 불만이 생기게 마련이다.

사실 기능조직은 회사의 규모와 상관 없이 지식노동을 하는 조직에는 적합하지 않다. 기능조직의 우수성이 입증된 사례도 거의 존재하지 않고, 이론적인 장점도 없는, 그냥 틀린 방식이다. IT 회사가 기능조직으로 일을 하고 있다면 경영진의 역량 부족이다.

목적조직에선 위에서 언급한 많은 문제가 저절로 해결된다. 영업부서에서 개발팀에 요청하는 게 아니라 영업부서에 개발자 한 명이 배치되어 있다고 생각해보자. 그리고 그 개발자는 영업부서의 업무만 처리한다. 그럼 이 개발자에게 과도한 업무가 쌓일 일도 없고, 서로 간에 업무 이해도도 높아지므로 개발자가 정보를 얻기 위해 대기해야 하는 시간도 줄어든다. 늘 붙어 있으니까 서로 기민하게 대응할 수 있다. 물론 이렇게 하면 개발자가 일이 없는 순간이 생길 수 있다. 그렇지만 그게 무슨 문제인가. 일이 없어서 노는 건 병목자원이 아니라는 이야기고 이건 문제 없다.

기획팀이 따로 존재하는 것이야말로 인간이 생각해낼 수 있는 최악의 조직 구조다. 마케팅 부서에서 새로운 마케팅을 한다고 가정해보자. 마케팅 부서에 담당 개발자가 있다면 그냥 그 개발자랑 계속 커뮤니케이션하면서 만들어가면 된다. 근데 기획팀이 따로 있으면 마케팅 부서에서 기획팀에 요구사항을 넣고 기획팀은 그 요구사항을 바탕으로 기획안을 만들어서 개발자에게 전달한다. 그러면 그 개발자는 개발하다가 의문사항이 생기면 또 기획자에게 물어보고 기획자는 다시 마케팅에 물어본다. 이런 복잡한 과정을 거쳐서 생산성이 날 리가 없지 않겠는가.

작은 스타트업에서도 이런 현상은 나타난다. 대기업에서 기능조직으로만 일해온 사람들은 5~6명 짜리 스타트업에서도 같은 방시으로 일하면서 기능조직의 문제점을 그대로 노출한다. 5명인데 팀으로 동작하는 게 아니라 따로따로 논다면 그 팀이 성공할 리 있겠는가.

기능조직은 당장 폐기해야 할 구시대의 잔재다. 설령 당장 바꿀 수 없다 해도 경영진이 의식을 가지고 외형적인 구조는 기능조직이더라도 목적조직처럼 일할 수 있게 서포트해야 한다.

 

개발자는 도구가 아니다#

하지만 기능조직도 근본 원인은 아니다. 앞서 말한 것처럼 작은 스타트업도 기능조직처럼 일하는 경우가 많다. 왜 이런 현상이 생길까? 내가 보는 이유는, 개발자를 자신의 아이디어를 실현해주는 도구로 보기 때문이다. 개발자를 함께 회사를 이끌어나가는 동반자로 보느냐, 그저 내 아이디어를 실현해주는 사람으로 보느냐에 따라 일하는 방식이 결정된다. 개발팀이 안 받쳐줘서 뭘 못한다고 생각하는 것 자체가 개발팀은 자신을 받쳐줘야 되는 존재라고 보는 것이다. 그들은 개발팀이 겪고 있는 문제에 관심이 없다. 단지 자신이 요청을 실행해주느냐 아니냐에 따라 판단할 뿐이다.

병목자원 이론, 일거리 선별, 기능조직 등 구체적인 방안들을 이야기하긴 했지만, 사실 더 중요한 것은 개발자를 동반자로 보고 함께 머리를 맞대고 고민하는 것이다. 개발팀을 진정 동반자로 본다면 일거리가 산처럼 쌓여 있는 개발팀에 가서 자기 요청 안해준다고 투정부리고 있겠는가? 개발팀을 신뢰한다면 수시로 가서 해달라고 조르겠는가? 제대로 된 팀이라면 더 골 같은 거 안 읽어도 저런 문제들 안 생긴다. 팀이 붕괴되면 어떤 방안도 다 소용 없는 법이다.

이번 글에서는 "개발자가 모자라요"의 두번째 문제만 다루지만, 첫번째 문제, 스타트업이 개발자를 못 구하는 경우도 사실 마찬가지다. 말로는 기술 중심의 회사니 해커 문화니 떠들고, 함께 성장하는 회사를 말하지만, 사실은 그냥 내 아이디어를 실현해줄 사람을 찾는 경우가 대부분이다. 그런데 그런 마인드를 개발자가 눈치 못 챌 리 없다. 그러니까 개발자를 못 구하는 것이다. 특히 제일 웃긴 이야기는 "개발자만 있으면 이 사업 성공시킬 수 있는데"라는 말이다. 이건 "여자만 있으면 장가갈 수 있는데"라는 말이랑 똑같다. 뭐, 둘다 ASKY지.

 

개발자는 모자라지 않다.#

개발자가 모자란 것은 원인이 아니라 결과다. 원인은 개발자들이 제대로 일할 수 있는 문화가 갖춰지지 않았기 때문이다. 문화가 갖춰지면 개발자들의 생산성은 몰라보게 올라갈 것이고, 뛰어난 개발자도 저절로 모여든다. 개발자가 모자란다고 불평하기 전에, 우리 회사는 왜 개발자가 생산성을 낼 수 없는지 고민하는 것이 우선이다. 그런 고민 없이 아무리 개발자 늘려봐야 소용 없다.


 

블로그 / 소프트웨어 개발

Youngrok Pak , 10 years, 8 months ago

성공은 과연 운인가

 

얼마 전 범준님 만나서 이야기를 나누다가 운 이야기가 나왔다. 범준님은 아마 예전부터 그런 입장이셨던 것 같은데, '성공'에서 가장 중요한 건 운이고, 스타트업은 여러 가지로 성공하기 위한 노력을 하지만 성공 확률을 비약적으로 높일 수 있는 방법은 없다는 말씀을 하셨다. 당시 더 중요한 이야기들(?)을 하고 있었기 때문에 대충 지나갔지만, 내 생각은 조금 다르다. 물론 공감하는 포인트도 있지만, 크게 보면 반대의 관점이다.
 
우선, 이런 운 이론은 아마도 성공 사례에서 나왔을 것이다. 비슷한 시도를 했음에도 시기, 환경 등등의 이유로 성공한 회사도 있고 아닌 회사도 있다. 그 차이에서 인과관계를 밝혀내는 것이 가능한가? 그냥 운이 아닐까? 실제로 성공한 회사들의 CEO들도 자신의 성공을 운이라고 말하는 경우가 많다. 그것도 진심으로. 하지만 그게 전부일까?
 
여기에 약간 다른 시각을 말하는 사람들이 있다. 운인 건 맞는데, 찾아온 운을 잡을 수 있는 실력이 있었기 때문이라는 주장. 그래서, 어쨋든 찾아온 운을 잡을 수 있는 실력이 있었다는 것만으로도 그들의 실력이라고 말할 수 있다는 이야기. 이것도 꽤 공감 가는 이야기이지만, 아직 부족하다. 그럼 성공이란 건 실력을 갖춘 사람들에게 우연히 찾아오는 행운이 더해져서 만들어지는 것인가? 그러면 실력이 아무리 있어도 행운이 안 찾아오면 다 소용 없는 짓인가? 이 질문에도 "그렇다"라고 대답할 수 있는가?
 
나는 우선 이 질문에 대답하기 전에, 아이템과 회사를 분리하고 싶다. 아이템을 성공시키는 것은 나도 확실히 운칠기삼이라고 생각한다. 운이 찾아오지 않으면 성공할 수 없다. 네이버 지식인의 성공? 카카오톡? 운이 절반 이상이다. 근데, NHN의 성공도 운인가? 지식인이 안 나왔으면 다음을 앞지르지 못했을까? 카카오의 성공도 운인가? whatsapp도 있고 추격자들도 금방 따라온 상황에서도 계속 앞서가는 카카오는 운으로 잘 나가고 있는 것인가? 난 이 질문만으로도 위의 질문에 답이 된다고 생각한다.
 
반대의 경우를 생각해보자. 5년 넘게 스타트업을 해왔지만 성공하지 못한 회사가 있다. 그럼 그 회사에는 5년 동안 단 한 번도 운이 찾아오지 않았을까? 그 회사는 충분한 실력이 있었는데 운이 따라주지 않아서 성공하지 못한 걸까? 전생에 나라를 팔아먹어서 지지리 복도 없는 사람이 CEO였을까?
 
난 그렇게 생각하지 않는다. 3년 쯤 하면 적어도 한 번은 기회가 찾아온다. 이콜레모에도 대박 기회가 5년 동안 최소한 두 번은 찾아왔다. 그걸 잡을 실력이 없었을 뿐이다. 물론 하나는 알고도 버리긴 했지만;; 작은 기회, 적어도 월급 걱정은 안해도 될 수 있는 기회도 서너 번 있었다. 안 잡은 것도 있고 못 잡은 것도 있지만 어쨋든 운이 없었다고 할 수는 없다.
 
흔히 망하는 스타트업은 1년 만에 망하고, 되는 스타트업은 평균 7년 만에 성공한다고 한다. 이건 결국 시도 횟수를 말하는 것이다. 성공 확률을 크게 변하게 할 수 없다면, 시도 횟수를 늘리면 된다. 5년 간 2번의 기회가 찾아온 이콜레모가 특별히 운이 좋은 편이라고 생각하진 않는다. 5년 쯤 사업하다보면 그 정도의 운은 다들 한 번씩은 찾아왔을 거다. 7년도 넘게 성공 못했으면 그건 실력이 없다는 말 외에 달리 설명할 말이 없다. 7년 내내 운이 따르지 않았다는 건 합리화를 넘어선 변명이다.
 
잠깐 새면, 린 스타트업도 이런 관점으로 볼 수 있다. 단위 시간당 유의미한 시도 횟수를 늘리는 방법. 단순히 시도 횟수를 늘린다고 허접한 시도들만 하면 확률이 올라가지 않는다. 같은 기간에 시도 횟수를 늘릴 방법을 찾되, 그 하나하나의 시도가 유의미한 시도여야 한다. 말하자면 이게 Minimum Viable Product다.
 
아뭏든, 아이템의 성공은 운일지언정, 스타트업 팀의 성공은 운보다 실력이라는 게 내 생각이다.
 
그럼 이콜레모는 지금까지 무슨 실력이 부족해서 성공을 이루지 못했는가? 내가 내린 답은 결국 돈이다. 사실 스타트업에 있는 사람들은 당연한 이야기를 왜 하냐고 할지도 모른다. 그럼 돈 없이 성공할 수 있을 거라고 생각했냐는 말도 들어봤다. 근데, 솔직히 난 돈 없이 성공할 수 있을 거라고 생각했다. 돈 그거 벌면서 하면 되는 거 아니냐고 생각했다. 근데 돈이 필요한 이유는 집중하기 위해서 필요한 거였다. 당장 다음 달 돈이 들어오지 않으면 월세를 못 낼 수도 있는 멤버들이 있고, 나도 집에 돈을 가져가지 않으면 선화에게 체면이 안 서는데, 돈 버는 거 외면하고 아이템에 충분히 집중할 수가 없었다. 이콜레모 4년째가 되어서야 그 점을 절실히 깨닫고 그 동안 번 돈으로 8개월 간 아이템에만 집중했지만, 8개월은 약간 모자랐다. 성공의 가능성을 충분히 엿보았음에도 불구하고 거기서 스톱할 수 밖에 없었다는 것이 너무도 안타까웠다. 어쨋든 돈이 없었던 것도 실력이고, 돈을 끌어올 능력이 없었던 것도 실력이고, 돈이 중요하다는 것을 몰랐던 것도 실력이다.
 
물론 돈 이외의 실력도 많이 부족했었다. 솔직히 3년 차까지의 이콜레모는 돈 이외의 실력도 부족했다. 하지만 4년 차부터는 충분히 실력을 채웠다고 자신한다.
 
그런 우리 팀에게 마음껏 집중할 수 있는 기회가 찾아왔다. 다시 정리하면, 나는 성공이 운이 아니라 실력이라고 생각하는 사람이고, 우리 팀에 딱 하나 부족했던 실력을 이제 채울 수 있게 되었다. 그러니까 내 이론대로라면 우린 이제 무조건 성공할 수 밖에 없다. 그게 1년이 걸릴지 2년이 걸릴지는 몰라도 3년은 안 걸릴 거다. 만약 내가 그 안에 성공을 해내지 못한다면 지금까지 내가 비즈니스에 대해서 해온 이야기들은 죄다 헛소리임을 인증하게 되는 셈이다. 
 
말하자면 이제 진짜 시험대에 오른 것이다.
 
Youngrok Pak , 10 years, 8 months ago

QuickAndDirty

난 예전에 프로그래머에게 필요한 피드백이라는 글에서 TDD, 리팩토링 등의 기법의 목적은 프로젝트를 더 빨리 완료하는 것이며, clean code니까 빨리 개발할 수 있다는 주장을 펼친 바 있다. 이번엔 이 주장을 한발짝 더 깊게 들어가되, 약간 다른 관점으로 풀어보려고 한다.

린 스타트업과 quick & dirty#

에릭 리스의 린스타트업에 보면 이런 스토리가 나온다. 처음에 스타트업을 할 때는 애자일의 주요 기법들을 잘 적용하면서 기술적으로 훌륭한 프로젝트를 했는데 아무도 쓰는 사람이 없어서 망했고, 나중에 다시 창업해서 수많은 버그가 있는 제품을 그냥 출시했는데 흥했더라. 매우 인상적인 이야기다. XP 기법들의 신봉자라면 좀 충격을 받을 수도 있을 것이다. 켄트 벡이 품질은 타협 대상이 아니며, 품질을 타협하면 오히려 프로젝트는 느려진다고 그랬는데 품질이 개판인 프로젝트는 돈을 벌고, 품질이 좋은 프로젝트는 망했다고?

오해를 덜기 위해 명확히 해두자면, 여기서 말하는 품질은 제품의 품질이 아니라 기술적인 품질이다. 그러니까, 에릭 리스의 이야기는 기술적인 품질이 낮은 프로젝트가 성공했다는 것이다. 그래서 그는 나중에 고객 관점에서의 품질을 이야기한다. 고객이 없으면 품질도 없다는 것.

아뭏든, 여기서 우리는 clean code를 위한 노력이 사실은 성공에는 도움이 안되는 게 아니었을까 하는 의심을 품게 된다. 합리적 의심이다. 린 스타트업을 읽고도 그런 생각이 안 들었다면 오히려 그게 더 이상할 것이다.

나도 스타트업은 quick & dirty를 해야 한다고 생각한다. 하지만, 이것이 clean code의 추구에 반하는 이야기는 아니다. 그러니까, 나는 모순처럼 보이는 quick & dirty와 clean code가 모순이 아니라고 주장을 하고 있는 것이다. 심지어, 이 주장은 옳기 때문에 따로 근거도 대지 않고, 이 글의 진짜 주제, 스타트업이 어떻게 quick & dirty를 할 것인가로 넘어갈 것이다. 만약 이 주장에 대한 논증을 보고 싶은 사람이 있다면 맛있는 점심 한 번으로 다 펼쳐보여주겠다.

Quick & Dirty How-to#

진짜 주제로 넘어가기 전에 잠시, clean code에 도달하는 가장 훌륭한 방법인 TDD의 사이클을 복습해보자.

  1. 제대로 동작하는지 확인할 수 있는 테스트를 작성한다.
  2. 실행 가능하게 만든다. 다른 무엇보다도 중요한 것은 빨리 초록 막대를 보는 것이다. 빨리 초록 막대를 보는 것은 모든 죄를 사해준다. 하지만 아주 잠시동안만이다.
  3. 올바르게 만든다. 이제 시스템이 작동하므로 직전에 저질렀던 죄악을 수습하자.

린 스타트업은 말하자면 TDD를 조금 더 큰 스케일로 하는 것이다.

  1. 가설을 수립하고, 가설을 확인할 수 있는 지표를 설정한다.
  2. 가설을 검증할 수 있는 MVP를 만든다. quick & dirty!
  3. 가설이 검증되었다면 완성도를 높여간다.
  4. 가설 검증 결과가 틀린 것으로 나온다면 새로운 가설을 수립한다.

2와 4분의 3 승강장#

문제는 바로 2와 4분의 3 승강장 2와 3 사이에 있다. 린 스타트업은 개발자를 위한 책이 아니라 스타트업을 위한 일반적인 방법론이므로, 2와 3 사이에 TDD 사이클의 3번 과정을 따로 시간을 할애해서 적어놓지 않은 것이다. 이게 바로 행간을 읽는다는 것이야. 가설 검증에 성공한 스타트업이 이 2.5 리팩토링을 놓치게 되면 바로 이어 등장하는 추격자들에게 자리를 내주게 된다. 추격자들은 모범 답안이 있으니 빠른 속도로 MVP를 만들 게 아니라, 처음부터 완성품을 보고 달려도 되므로, 완성품에 더 빨리 도달할 수 있다. MVP까지는 quick & dirty로 빠르게 만들 수 있지만, 완성품을 만드는 것은 clean code 없이 속도를 낼 수 없다.

하지만, 설령 개발자가 2와 3 사이에 숨겨진 2.5를 인지한다고 해도 문제는 간단하지 않다. CEO는 quick & dirty로 가설을 검증해냈기 때문에 이미 quick & dirty에 맹신이 생긴 상태이고, 앞으로도 쭉 quick & dirty로 해나가면 된다고 생각한다. 그래서, 계속 같은 속도로 움직일 수 있을 거라고 생각한다. 이런 CEO에게 코드를 정리할 시간이 필요하다고 말하는 것이 먹힐 가능성은 매우 낮다. 설령 말로는 동의해도 이후에 액션들은 2.5 작업을 할 수 있도록 내버려 두지 않는다. proof of concept 이후에도 쭉쭉 뻗어나가는 스타트업과, 경쟁에 뒤쳐지는 스타트업에는 결정적인 차이가 바로 이것이다.

뛰어난 엔지니어가 CEO이거나, 혹은 뛰어난 엔지니어가 어떻게 일하는지를 이해하는 CEO라면 2.5를 이해한다. 하지만 대부분의 CEO는 2.5를 받아들이지 못한다. 고속성장을 하다가 경쟁자에게 따라잡히는 스타트업들은 대체로 CEO가 엔지니어링에 대한 마인드가 부족하다. 국내에도 좋은 사례가 있다. 최근 2~3년 간 스타트업을 가장 떠들썩하게 했던 분야 두 개를 떠올려보라. 그리고, 그 두 개의 선두 업체였던 두 회사의 2년 전과 지금을 비교해보라. 하나는 지속적으로 새로운 성장 동력을 발굴해내며 성장을 가속하고 있지만 다른 하나는 외형적인 성장만 해오다가 그마저도 경쟁사에 따라잡혔다. 물론 차이를 만든 이유는 여러 가지가 있고, 여러가지 분석이 있겠지만, 결정적인 차이는 엔지니어링에 대한 마인드의 차이였다는 것이 내 판단이다.

MVP의 조건#

물론 위의 이야기는 어쨋든 다 행복한 스토리다. 내가 창업한 이후 5년 간 직간접으로 관련이 있었던 30여개의 스타트업 중 proof of concept에 성공한 스타트업은 단 둘 뿐이니까 말이다. 그럼 대부분의 스타트업에서는 개발자들이 고민해야 할 clean code는 2.5 단계가 아니라 2단계다. 2단계에선 그럼 무작정 quick & dirty를 하면 되는가? PHP라도 상관 없는가? (그건 물론 안됨) 여기서 quick & dirty를 어떻게 할 것인가를 이야기하기 전에 하나 더 짚고 넘어갈 게 있다. 개발이 아니라 MVP에 대한 조건이다.

MVP는 박병호가 아니고, Minimum Viable Product다. 아니, Minimum Viable Product다. 이게 대부분의 스타트업에서 잘못하는 것 중 하나다. MVP는 충분히 작아야 한다. 이베이의 첫번째 제품은 웹사이트에 중고 물품을 등록하는 기능과 열람하는 기능 두 개 밖에 없었다. 거래는 이메일로 하고 수수료는 우편으로 보내는 원시적인 웹사이트였다. 이런 제품에 버그가 많으면 얼마나 많겠으며 코드가 지저분해봐야 얼마나 지저분하겠는가. MVP가 충분히 작다면 quick & dirty로 매우 빨리 만들어도 그 과정에서 쌓는 기술 부채는 얼마 되지 않는다. 가설 검증이 되면 바로 갚을 수 있다.

하지만 대부분의 스타트업들은 Minimum은 커녕 Maximum을 만들기 위해 노력한다. 뭔가 기능이 없어서 고객이 안 온다고 생각한다. 그래서 점점 비대하게 제품을 확장해나간다. 가설 검증도 안되었는데. 그럼 quick & dirty로 인한 기술 부채는 점점 감당할 수 없을 만큼 쌓여간다. 가설 검증이 된다면 기술 부채는 별 거 아니다. 어차피 돈 벌고 있으니까, 혹은 돈 벌 예정이니까, 뛰어난 개발자 채용하고 시간 들여서 기술 부채를 갚으면 된다. 2.5 단계를 진행하면 되는 거다. 근데, 가설 검증이 안된 상태에서 quick & dirty로 개발한 제품이 점점 커져가면 점점 속도가 느려져서 어느 순간 아무 것도 할 수 없는 상태가 온다. 그리고, 이런 상태가 되면 개발자가 도망가거나, 도망은 안 가도 백기를 들곤 한다. 이렇게 된 스타트업에 헬프하러 간 게 몇 번인지 셀 수 없다.(사실은 셀 수 있다, 여덟 번)

그리고, 설령 어찌어찌 가설 검증이 되더라도, 그 사이 quick & dirty로 만든 제품이 이미 너무 비대하다면, 나중에 뛰어난 개발자를 데려와도 어찌할 수 없는 경우도 생길 수 있다. 2번도 통과했고 2.5번도 할 자세가 충분히 되어 있는데, 2.5를 할 수 없는 상황이 될 수 있는 거다.

그래서, 스타트업은 MVP를 만들 때 극도로 절제해야 한다. 가설-검증의 사이클을 활용하고, 가설의 성공/실패 여부가 가려지지 않았을 때 기능 추가하는 것이 결과적으로 성공 확률을 깎아먹는다는 것을 이해할 필요가 있다. 기술 부채를 통제할 수 있는 선에서 MVP를 만들어야 한다. 기술 부채도 부채이므로 많아지면 파산한다.

Quick & Dirty로 개발하기#

그럼 이제부터 본론(?) quick & dirty로 개발하는 방법에 대해 들여다보자. 이 방법들의 목적은 clean code의 궁극을 추구하는 것이 아니라, 기술 부채로 인해 파산할 수 있는 위험을 아주 작은 노력들로 막는 것이다.

추상화하지 말 것#

좋은 코드는 좋은 추상이다. 그러므로, 개발자는 좋은 추상화를 하기 위해 노력해야 한다. 하지만, 잘못된 추상화만큼 코드를 재앙으로 이끄는 것도 없다. 초기에 좋은 추상을 발견할 시간이 부족하다면, 추상화를 하지 말고 미루라.

Do not extract method#

조금 더 구체적으로 말하자면, Do not extract method다. 트위터에도 언젠가 설명 없이 저 문구만 쓴 적이 있는데, 이런 맥락에서 한 말이다. 우선, 함수는 그 자체로 GotoConsideredHarmful을 극복한 것이 아니다. Goto의 문제는 코드를 읽다가 흐름의 점프가 일어난다는 것이며, 함수도 그 문제를 똑같이 갖고 있다. 간혹 이 문제를 네이밍의 문제로 보는 관점도 있는데, 네이밍이 물론 중요한 것은 사실이지만, Goto도 라벨을 붙여서 라벨로 점프하니까 라벨만 잘 붙이면 되는가? 아닐 것이다. 라벨을 잘 붙여도 여전히 Goto는 해로우므로, 함수 역시 이름 잘 붙인다고 그 해로움을 피해가는 것은 아니다.

진짜로 Goto의 해로움을 피해가려면 관련된 변수들의 scope를 잘 정의하는 것이 중요하다. Goto에서 정말 피하기 어려운 것은 전역 변수를 써야 한다는 것이다. 그러니까 코드에서는 물리적으로 다른 공간에 점프를 했는데, 머리 속에는 여전히 여러 변수들의 상태를 담고 있어야 코드를 계속 추적할 수 있기 때문에 문제가 되는 것이다. 함수가 좋은 것은 변수를 지역적으로 제한시키기 쉽다는 것이다. 함수의 이런 장점이 오히려 OOP에 오면서 무분별한 멤버 변수 사용으로 퇴색되는 감이 있는데, OOP를 잘 활용하려면 메서드 역시 변수의 scope를 엄격하게 관리하는 게 중요하다. 그러면 함수는 점프를 한 부분만 따로 이해하는 것이 가능하다. 설령 그 전 코드를 잊어버렸더라도 함수를 이해하고 다시 돌아와서 볼 수 있다. 그런데 만약에 함수나 특히 메서드에서 변수 scope를 제대로 관리하지 않아서 기억해야 하는 상태가 많다면 goto랑 별 다를 바가 없는 것이다.

이런 고민 없이 그냥 extract method를 하게 되면 결국 goto와 같은 문제를 발생시키게 된다. 이렇게 되느니 차라리 1000라인 짜리 메서드가 나중에 리팩토링하기는 더 좋다. 그래서, 좋은 extract method가 떠오르지 않는다면, 그냥 하지 않는 게 더 낫다는 것이다.

상속 계층을 만들지 말 것#

마찬가지로, 상속 계층도 되도록 안 만드는 게 좋다. 상속 구조야말로 OOP에서 가장 잘하기 어려운 부분이고, 다형성에 대한 완벽한 이해가 없다면 좋은 상속 구조를 만들어낼 가능성은 거의 없다. 만약 스스로 OOP를 잘한다고 생각하지 않는다면, 상속은 전혀 쓰지 않기를 권한다. 다형성에 대해서는 OOP는 조건문을 줄이는 것을 참조하라. 참고로 나는 저 글에 완전히 동의하지는 않는다. Field Encapsulation도 여전히 OOP의 핵심이며 이건 앞서 Do not extract method에서 했던 이야기와 관련이 있는데 언젠가 다시 한 번 글을 쓸 예정이다.

중복은 한 파일에 몰아라#

리팩토링을 한 마디로 요약한다면 중복을 제거하고 의도를 드러내는 것이다. 그런데 중복을 제거하려면 결국 뭔가 추상화를 하게 되고 어렵다. 그러니까, 중복을 당장 제거하지는 말고, 일단 물리적으로 한 파일에 몰아 넣어라. 한 곳에 모여 있는 중복 코드는 나중에 손쉽게 리팩토링할 수 있다. 그러나, 중복이 여러 파일에 걸쳐 퍼지기 시작하면 감당할 수 없는 상황이 온다. 특히 조건절의 중복 코드는 전염되는 경향이 있다. 이런 코드에 대한 정답은 다형성이지만 다형성이 손에 익은 사람이 아니면 그리 쉽게 되진 않을 것이다. 그럼 그냥 한 파일에만 몰아두어라. 나중에 내가 가서 해결해주겠다.

Cyclomatic Complexity를 늘리지 말 것#

자세한 건 구글링을 해보시고, 쉽게 말하면 분기의 depth를 늘리지 않는 것이다. indent가 깊게 안 들어가게 해야 한다고 이해해도 좋다. 다른 건 리팩토링을 하지 않더라도 이것만은 꼭 해놓아야 한다. if문을 줄일 수 있는 다형성을 쓰지 말라고 해놓고 이제와서 if문을 줄이라고? if문을 줄이라는 건 아니다. if문을 flatten하라는 것이다. 예를 들면 GuardClause 같은 것. 

  public Foo merge (Foo a, Foo b) {
    Foo result;
    if (a != null) {
      if (b != null) {
        // complicated merge code goes here.
      } else {
        result = a;
      }
    } else {
      result = b;
    }
    return result;
  }

위와 같은 코드보다는 아래와 같은 코드가 낫다.

 

  public Foo merge (Foo a, Foo b) {
    if (a == null) return b;
    if (b == null) return a;
    // complicated merge code goes here.
  }

그리고 조건문도 자세히 보면 중첩 if로 된 것을 풀 수 있는 경우가 많다. 되도록 다 풀어두는 게 좋다. 물론 중첩 if를 풀면 중복이 더 많이 발생할 수도 있다. 하지만 그래도 괜찮다. 중복 코드는 나중에 쉽게 발견하고 리팩토링할 수 있지만, cyclomatic complexity가 높은 코드는 이해하는데 시간이 더 많이 걸린다. if가 나타났다고 그걸 다형성으로 대체하려고 하지는 말고, 그냥 그 if들이 중첩되지 않도록 하는 것만 신경 써도 충분하다.마찬가지로 SQL을 작성하더라도 FROM 절의 sub query depth가 깊어지는 것보다는 적절히 join으로 처리하거나, 정 안되면 성능이 좀 떨어지더라도 쿼리 여러 번 하는 게 좋다. 이런 것들은 리팩토링에 큰 에너지를 쓰지 않고 작은 노력으로 큰 효과를 볼 수 있는 것들이다. 

이름 규칙 정하기#

quick & dirty는 리팩토링도 대충하는 만큼, 네이밍도 그렇게 열심히 할 필요는 없다. 다만, 네이밍 룰은 잘 정해두는 게 좋다. 특히 각 언어의 코드 관례을 지키지 않으면 나중에 다른 개발자가 왔을 때 실제보다 더 코드가 저평가 받게 된다. 언어의 코드 관례는 존중하도록 하자.

이미지 파일의 이름 규칙도 꽤 영향이 크다. 이 규칙이 잘 정해져 있으면 개발할 때 디렉토리에서 다시 파일명을 확인하지 않아도 된다. 물론 Jetbrains처럼 이미지 파일명까지 추천해주는 IDE를 쓸 수 있는 경우도 있지만, 안 그런 경우도 많으니까. 이를테면 나는 이미지 이름을 붙일 때, artifactname_type_extra.png 같은 방식으로 쓴다. login_button_small.png, content_bg.png, table_header_bg_white.png 이런 식. 마찬가지로 CSS의 class명, 태그의 id 등도 이름 규칙이 잘 지켜지면 이득이 많다.

안 쓰는 코드, 파일 삭제#

나중에 레거시가 될 운명인 코드이니만큼, 나중에 이 코드를 만날 개발자들에게 중요한 것 중 하나는 봐야 할 코드량이다. 그런데 쓰지도 않는 코드 때문에 시간을 낭비해야 한다면 얼마나 끔찍할까. 나중에 리팩토링하다가 걸리는 파일들 일일이 다 수정했는데, 알고봤더니 그 중에 80%는 쓰지도 않는 클래스들이었다면? index_1.php, index_2.php 이딴 것들도 다 삭제하도록 하자. 한 눈에 들어오는 파일 개수도 유지보수에 큰 영향을 미친다.

안타까운 것은 이런 일이 대부분 소스 버전 관리를 하지 않기 때문에 일어난다는 것이다. 버전 관리를 하고, 안 쓰는 파일은 빨리빨리 삭제하도록 하자. 실험한 코드들도 다 삭제하는 게 좋다. 안 쓰는 코드를 주석처리한 것도 임시로만 하고, 작업 끝나면 꼭 삭제하자.

주석은 되도록 쓰지 말 것#

코드 분석에 도움될 정도의 주석을 쓸 시간이 있거든 리팩토링을 하든가, 구현을 더 빨리하는데 시간을 써라. 주석이 필요 없는 코드를 만들라는 게 아니다. 코드가 지저분하든 아니든 주석은 이해에 방해되는 경우가 더 많다. 코드만큼 실시간으로 업데이트되지 않기 때문이기도 하고, 나중에 보는 사람의 관점을 생각해서 주석을 쓰는 것이 쉬운 일이 아니기 때문이기도 하다. 특히 주석에 누가 언제 이 코드를 작성했는지 따위는 제발 남기지 말도록 하자. 불필요한 라인도 코드 분석을 방해한다. 어쩔 수 없이 비정상적인 방법으로 구현했을 때만 주석을 남겨라. 이를테면 다음과 같은 주석은 남겨둘 필요가 있다.

// 결제 처리 중에 왜 안되는지 몰라서 아래 코드를 넣었는데 작동함. TODO 나중에 분석해볼 것.
funckingKoreanPaymentGateway.setUndocumentedOption('blahblah', ...);
코드 외의 기술적인 사항은 반드시 문서를 남길 것#

레거시를 접할 때 가장 스트레스 받는 사항이 이거다. 소스를 어떻게 빌드하는지, 서버에 어떻게 deploy하는지, 서버에서 무슨 cronjob이 돌고 있는지, 퍼미션은 어떻게 줬는지, 서버 스타트/스톱은 어떻게 시키는지, 서버에 무슨 설정 파일을 건드렸는지 등등. 이런 건 시간이 들더라도 반드시 문서로 남겨야 한다. 이런 정보가 실종되는 바람에 뻔히 돌고 있는 서비스인데 더 이상 업데이트를 할 수 없게 된 회사도 본 적 있다. 궁극적으로는 각종 설정 파일, 스크립트 등도 모두 소스 코드로 간주해서 버전 관리를 해야 하고, 자동화도 시켜야 하지만, 처음부터 그런 데 시간을 투자하기는 어렵고, 문서로 남겨놓는 것만으로도 충분하다.

적정 기술#

소프트웨어 개발에도 적정 기술이 있다. 요즘 성능 관련 컨설팅을 좀 하다보니 가장 많이 받는 질문이 이거다. 우리도 분산 DB 기술을 도입해야 하나요? 앞으로도 물어볼 수많은 사람들을 위해 미리 답변하자면, "그냥 MySQL 쓰세요. 그게 정답입니다. 당신이 원하는 건 다 할 수 있어요." 물론 우리도 언젠가는 분산 DB를 해야 할 것이다. 당신의 비즈니스가 100억 valuation 쯤 될 때쯤에 말이지. 그 전에는 phpmyadmin과 MySQLWorkbench가 있는 MySQL을 쓰자. 아, 물론 팀 내에 DBA가 있고 TOAD 정품 사놨으면 오라클 써도 된다.(근데 요즘도 TOAD 쓰나?) 오픈소스에서 PostgreSQL 계속 써온 사람이 있으면 괜찮다. 그래도 큐브리드는 안됨. mongodb는 MySQL과 또 좀 다른 장점이 있고, 꽤 사용자가 많아져서 약간의 리스크를 걸고 쓰는 건 나쁘지 않다. 오라클에 더럽혀진 MySQL이 싫다면 MariaDB를 써라. MSSQL은? 글쎄, 윈도 개발자라면 더 편할 수도 있겠지만... 요즘 누가 윈도로 개발하나?

웹을 한다면 생산성이 높고 검증된 프레임웍을 사용하라. 두말할 필요 없이 Rails 아니면 Django가 답이다. Java는 검증되었지만 생산성이 너무 낮고, Node.js는 아직 시간이 더 필요하다. 그 외의 것들은 구글링해도 답이 안 나오는 상황을 자주 겪게 될 것이다. 뭐 그래서 하다가 직접 소스 고쳐가면서 오픈소스 커미터도 되고 좋은 거 아냐? 그래, 좋지, 그 개발자 커리어에는. 근데 그 스타트업에 좋은지는 모르겠다. 물론, 개발자가 다른 조직에서 이미 숙련된 프레임웍이 있다면 상관 없다. 여기서 검증된이란 표현에 주체는 스타트업의 개발자 당사자들이다. 이를테면, 도요타는 늘 검증된 기술만 production에 적용하는 원칙으로 유명하지만, 하이브리드 등의 최신 기술에서 오히려 시장을 선도해왔다.(몇 년 전까지는) 남들이 다 모르는 최신 기술이라도 우리가 충분히 써봤고 확신을 가질 수 있다면 그건 검증된 기술이다. 하지만, 우리도 삽질하고 구글링하고 뉴스그룹에 stackoverflow 뒤져가면서 써야 하는 기술이라면, don't even try.

특히 요즘은 매일매일 신기술이 쏟아져 나온다. 크로스 플랫폼으로 모바일앱을 쉽게 만들 수 있어요. 화려한 웹 효과를 코드 몇 줄로 쓸 수 있어요. 이제 웹앱의 시대에는 JS도 MVC 프레임웍을 써야 해요. 다 좋다. 익숙해지면 생산성을 크게 높일 수 있을지 모른다. 이런 거 흐름을 놓치면 시대에 뒤쳐지는 개발자가 되버릴 것 같은 느낌을 주기도 한다. 우리도 얼른 적용해서 뒤쳐지지 말아야지. 이런 생각으로 기술은 따라가면서 스타트업에선 뒤쳐지게 된다. 눈앞의 과제에 대한 최선의 해결책을 찾으려고 하다보면 필요한 신기술은 자연스럽게 적용하게 된다. 따라가려고 애쓰지 말고 당면 과제에 충실하되 변화의 흐름에는 귀만 열어둬라. 필요해질 때 찾아서 쓸 수 있도록.

동일한 목적의 프레임웍이나 라이브러리를 여러 개 쓰지 말 것#

이를테면 django를 쓰면서 템플릿 언어가 맘에 안 들어서 mako로 바꾸는 것까진 좋은데, django template으로 된 코드와 mako로 된 코드가 혼재하게 하지는 말라는 것이다. 그러면 뭔가 바꾸어야 할 때 작업이 두 배로 는다. 실제 예를 든다면, 지금 내가 유지보수하고 있는 코드는 PHP인데 Code Igniter를 전면적으로 쓴 코드, Code Igniter에서 일부분만 불러 쓰고 예전 PHP 스타일로 짠 코드, Code Igniter 쪽 완전 무시하고 짠 PHP 코드가 섞여 있다. 근데 페이스북 로그인 처리 쪽에 코드를 고치려고 봤더니 그 과정에서 호출되는 URL 네 개가 다 스타일이 다르다. 그래서 session에서 값 읽어오기, 로그인 여부 처리하는 코드 등등 전부 네 가지 방식을 모두 찾아내서 처리해야 했다. Code Igniter를 쓰기로 결정했다면 끝까지 써야 하고, 갈아엎을 꺼면 빨리 갈아 엎어야 한다.

물론, 현재 쓰고 있는 프레임웍이 맘에 안 든다면 점차적으로 갈아엎을 수는 있다. 그 과정에서 일시적인 공존은 괜찮다. 이런 작업을 할 때는 한 번에 갈아 엎는 것보다 점차적으로 갈아엎는 게 더 낫다. 하지만, 이건 빠른 시간 내에 끝내야 하고, 이런 작업을 할 때조차도 공통적인 코드들은 합쳐 놓으려는 시도를 해야 한다. 이를테면, config는 양쪽 스타일에서 같이 쓸 수 있도록 고쳐놓은 다음 전환 작업을 시작한다거나 하는 방법이 있다.

이미지 리사이징 같은 것도 마찬가지. 어디는 gd2 라이브러리로 하고, 어디는 python-imaging을 쓰고, 어디는 imagemagik 바이너리를 호출하고, 이런 식으로 섞여 있으면 나중에 리사이징 로직에 뭔가를 바꾸었을 때 어딘가 구멍이 생기게 된다. 추상화까지는 해놓지 않더라도, 사용하는 라이브러리만 잘 통일해도 이런 문제는 막을 수 있다.

마무리#

어쨋든 스타트업은 quick & dirty로 달려가야 한다. 기술 부채가 두렵다고 clean code를 극한까지 추구한다면 아무도 쓰지 않는 훌륭한 제품이라는 현실에 직면하게 될 것이다. 스타트업도 투자고, 부채로 레버리지를 한다면 원하는 이익 실현 시점을 앞당길 수 있다. 기술 부채 만드는 것을 두려워해선 안된다. 다만 그 기술 부채를 감당할 수 있는 수준으로, 파산하지 않게 유지하라는 것이다. 그렇게 큰 노력을 기울이지 않고도, 엄청나게 훌륭한 리팩토링을 해내지 않고도 그럭저럭 통제할 수 있는 수준을 유지할 수 있는 방법들이 있다. 물론 또 너무 저런 걸 다들 잘하면 내 밥벌이가 안되겠지. 너무 좋은 코드도, 너무 나쁜 코드도 스타트업에겐 좋지 않다. 적정 기술, 적정 품질을 생각하면서 일하는 엔지니어가 되도록 하자.


블로그 / 소프트웨어 개발

Youngrok Pak , 10 years, 8 months ago

아이폰과 맥 사진 관리 방법 정리

그동안 사진 관리에서 삽질 끝에 찾아낸 방법을 정리해본다.

우선 목표는 다음과 같았다.

  1. 어디서 찍은 사진이든 유실되지 않을 것
  2. 아이폰에서 찍은 사진 컴퓨터에서 보기 쉽게
  3. 아이폰 이외에서 찍어서 컴퓨터에 보관 중인 사진도 아이폰으로 볼 수 있게
  4. 여행 등 큰 이벤트는 별도로 정리
  5. 선화나 친가, 처가와 공유할 사진은 공유하기 쉽게
  6. 대용량 사진은 적절한 사이즈로 줄인 사진을 볼 수 있게. 원본은 별도 보관해도 된다.

히스토리를 좀 보자면, 윈도/리눅스를 쓸 때는 피카사를 쓰고 외장하드에 백업하는 방식으로 했는데, 편한 듯 불편한 듯 뭐 그저 그랬다. 그땐 폰으로 흘러간 윈도 모바일폰 알육이를 썼는데, 지금 생각해도 윈도 모바일의 싱크 기능은 아이폰보다 월등히 좋았다. 꽂기만 하면 문서고 사진이고 죄다 자동으로 양방향 싱크를 해주고, 충돌처리까지 어느 정도 해줬으니 iCloud 나오기 전의 iTunes 싱크보다 100배쯤 좋고, 심지어 지금의 포토스트림보다도 편한 부분이 있다. 뭐 아뭏든, 그 땐 사진이 그렇게까지 많진 않아서 좀 수작업 해도 별 문제 없이 관리할 수 있었다.

그러다가 맥으로 넘어가면서 iPhoto를 발견하게 되었는데, 처음에는 정말 너무 좋았다. 피카사도 좋다고 생각했지만 iPhoto가 훨씬 이쁘고 쉬웠다. 그래서 전에 모아둔 사진은 전부 iPhoto 보관함에 밀어넣고 아이폰에서 찍은 건 가끔 연결해서 iPhoto에서 가져오기를 했다. 그리고 iTunes의 사진 싱크를 통해서 아이폰으로 싱크. 여기까진 괜찮았다.

근데 문제는 iCloud를 쓰면서부터 발생했다. 포토스트림이 버그가 있는지 사진이 유실되기도 하고, 무엇보다 자동으로 가져오기를 했더니 이벤트에 "8월의 사진 스트림" 같은 게 딱 생기면서 가끔 아이폰 연결해서 가져오면 중복 사진도 생기고 뭔가 꼬여서 정리가 안되는 느낌. 그래서 이 때부터 고민을 다시 하기 시작했다. 어쨋든 예전에 쓰던 방식은 사진이 클라우드에 보관되는 건 아니라서 불편하고 불안했다. iCloud는 스토리지가 아니라 싱크 개념이라서 목적에 안 맞고. 그래서 Dropbox에 넣고 피카사를 쓰는 방안, iPhoto Library를 통째로 Dropbox에 넣기, 무제한이 된 구글 플러스 이용하기 등등을 검토해보았다. 

우선 사진 정리 도구로는 iPhoto 아니면 피카사다. Apperture를 사진 않을 테고, 우분투로 돌아가서 shotwell을 쓸까 하는 생각도 1초 정도는 했지만... 암튼, iPhoto는 내가 Xcode(아이폰 개발 안되면 맥이 한국에서 뭐 그리 많이 팔렸겠어?)와 함께 맥의 양대 킬러앱으로 꼽는 앱이라 애착이 있었고, 피카사를 3년 넘게 썼다는 게 믿기지 않을 만큼 피카사가 어렵게 느껴져서 결국 iPhoto는 어떻게든 쓰기로 했다.

보관용 클라우드는 iCloud, Dropbox, 구글 플러스 중에 하난데, iCloud는 보관 개념이 아니라서 탈락, 구글 플러스랑 Dropbox 중에서 고르기로 했다.

그리고 아이폰의 사진을 싱크시키기. 이것도 iCloud, Dropbox의 카메라 업로드, 구글 플러스 무제한 자동 업로드 중 하난데, 구글 플러스의 무제한, 그리고 피카사를 보조 도구로 사용하기 좋다는 점, 웹 앨범이 괜찮다는 점 등이 땡겨서 이걸로 먼저 시도해봤다. 근데 구글 플러스 앱을 실행한 직후에만 백그라운드로 업로드가 된다. 그러니까 구글 플러스를 계속 안 열면 사진 찍어도 업로드가 안된다는 것. 물론 이건 iOS의 한계다. 그리고 업로드 진행률 같은 게 적절히 표시되지 않았다. Dropbox 카메라 업로드는 아이폰, 맥 다 되고 구글 플러스에 비해 안정적이고 빨라서 좋지만, 역시나 포토스트림처럼 빨리 싱크가 되진 않는다. 결국 어떻게든 포토스트림을 쓸 수 밖에 없다.

포토스트림을 쓴다면 보관용 클라우드로 구글 플러스는 중복이라 내키지 않는다. 결국 답은 Dropbox.

결국 제약사항들을 따져보면 iPhoto, Dropbox, iCloud의 사진스트림을 조합할 수 밖에 없다는 결론. 이 제약 안에서 어떻게 쓸지 베스트 프랙티스를 만들어가봤다. 그래서 나온 방안은 이렇다.

  1. 아이폰 외에 찍은 사진은 모두 Dropbox의 Photos 폴더 아래에 넣는다. 적절히 폴더로 관리한다.
  2. iPhoto Library를 새로 만들고 그 파일 역시 Dropbox의 Photos 폴더 아래에 넣는다. 그럼 이제 iPhoto의 상태도 자동 백업되는 셈.
  3. iPhoto에서 가져오기할 때 보관함으로 항목 복사를 체크 해제한다. 그러면 사진 가져올 때 메타 정보 가져와서 썸네일만 생성하고 사진 파일 카피를 하지 않는다. 그래서 파일은 iPhoto에서 분류되는 구조가 아니라 원래 있던 위치에 그대로 있다. 이러면 중복 파일이 잘 안 생겨서 용량을 아낄 수 있고(아이폰이 16G라 용량 문제는 꽤 심각하다) 나중에 피카사랑 같이 쓸 수도 있다.
  4. 포토스트림을 켠다. 포토스트림에서 가져온 파일은 iPhoto Library 안에 복사가 된다. 보관함으로 항목 복사를 체크 해제했는데도 복사가 되는 게 뭔가 이상하지만 암튼 내 의도랑은 맞아떨어진다. 포토스트림의 파일이 Dropbox에 옮겨져서 백업되는 셈이기 때문에 안전하다.
  5. 포토스트림에서 자동 가져오기를 켠다. 그러면 "8월의 사진 스트림" 같은 이벤트가 생기는데, 주기적으로 이벤트 - 선택된 이벤트 자동 분리를 실행시켜서 이벤트를 정리해준다. 전에는 이걸 몰랐었다. 이게 있으면 사실 그냥 iPhoto와 iCloud 조합만 써도 백업 이외에는 꽤 만족스럽게 쓸 수 있다.
  6. 공유해야 하는 사진들은 Dropbox에 넣고 공유한다. 부모님도 다 스마트폰이라 public link를 생성해서 보내면 다 볼 수 있다. 경우에 따라 피카사를 띄워서 구글 플러스로 업로드해서 공유하기도 한다.
  7. iPhoto로 정리된 것들은 iTunes를 통해서 아이폰에 싱크한다. 어차피 새로 생기는 사진은 대부분 아이폰에서 생기기 때문에 자주 할 필요는 없다. iTunes 사진 탭에서 다음으로부터 동기화에 iPhoto를 고르면 된다.
  8. 대용량 사진들은 강석천씨가 아이디어를 내고 정성원씨가 개발해서 이콜레모가 출시한! 이콜레모에 매달 20만원씩 벌어다주고 있는! Photo Resizer를 이용해서 적당히 줄인 후, 원본은 외장 하드에 넣어두고 줄인 것만 Dropbox에 넣어서 iPhoto로 가져온다. 솔직히 이거 나도 쓰게 될 줄은 몰랐다.

이걸로 언제 어디서나 내가 찍은 사진들을 볼 수 있고, 사진 잃어버리지 않고 모두 만족스럽다. 다만, Dropbox 100G를 구매해서 매년 $99가 나간다.

이상~


 

블로그

Youngrok Pak , 10 years, 8 months ago

프로그래머에게 필요한 피드백

 

수십년 동안 전문가가 안되는 비결에 따르면, 믿을 수 있는 직관이 형성되려면 유효성과 피드백이 갖춰져야 한다고 한다. 믿을 수 있는 직관이 형성된다는 것은 곧 전문가가 된다는 이야기. 그렇다면 소프트웨어 개발자에게 필요한 유효성과 피드백은 무엇일까? 유효성 이야기는 조금 어렵고 복잡하므로 다음으로 넘기고 피드백을 보자. 프로그래머는 어떤 피드백을 받아야 전문가로 발전하는데 도움이 될까?

아마 많은 사람이 피드백 하면 상사나 동료로부터 잘했다 못했다 이야기를 듣는 것을 먼저 떠올릴지 모른다. 하지만 이건 다들 알다시피 답이 아니다. 상사나 동료가 정확한 판단을 내린다는 보장이 없기 때문이다. 드라이퍼스 모델에 따르면 전문가의 수는 극히 적고 대부분 초보자, 고급 입문자, 중급자에 머물러 있다. 그렇다면 상사나 동료도 전문가일 확률은 아주 낮다. 그렇다면 상사나 동료의 피드백은 비전문가의 피드백이며 그것이 정확한 의견일 가능성은 낮다. 또, 전문가라고 해서 꼭 자신이 왜 잘하는지를 알고 있는 것은 아니기 때문에 전문가 역시 좋은 피드백을 준다는 보장은 없다. 물론, 상사나 동료의 피드백에도 진실은 담겨 있다. 하지만 그것은 전체의 진실이 아니라 일부의 진실이고 열심히 듣되 스스로 판단해야 하는 종류의 피드백이다. 어찌되었건, 전문가로 가는 길과는 크게 상관이 없다.

잠시, 반대로 피드백이 아주 좋은 분야를 생각해보자. 어떤 분야가 있을까? 탁월한_조직이_빠지기_쉬운_5가지_함정에 한 가지 예가 나온다. 스포츠. 스포츠에는 점수와 승패라는 명확한 피드백이 있다. 1:1 경기일수록 피드백은 더 명확하다. 이런 분야일수록 전문가와 비전문가의 차이는 엄청나다. 투자한 시간에 어느 정도 비례해서 실력이 올라가기 때문에 취미로 하는 사람이 프로를 이길 가능성은 거의 없다. 하지만 프로그래머는 어떤가? 낮에는 바쁘게 환자를 치료하면서 밤에 백신을 만든 안철수는 다른 프로그래머들보다 훨씬 빨리 바이러스 대비책을 내놓았다. 수많은 프로그래머들을 제치고 한 고등학생이 한국 앱스토어에서 짱먹었다. 18세 브라질 청소년이 리눅스 커널 메인테이너가 되고, 입사 1년차가 7년 경력 사원보다 높은 성과를 내곤 하는 것이 프로그래머다. 프로그래머들이 프로 바둑기사만큼 전문성을 발전시킬 수 있었다면 이런 일은 일어나지 않을 것이다.

반대로 이야기하면 프로그래머에도 자신의 성과에 대한 명확한 지표가 있다면 더 전문성을 높여갈 수 있다. 탁월한_조직이_빠지기_쉬운_5가지_함정에서 스포츠의 예를 든 이유도 기업이 성과를 내기 위해서 성과를 평가할 수 있는 지표가 필요하다는 이야기를 하기 위함이었다. 프로그래머 역시 그런 지표가 필요하다. 내가 참여한 프로젝트가 얼마나 돈을 벌었는지, 얼마나 많은 사람에게 도움을 주는지, 혹은 얼마나 돈을 절약했는지 등등. 혹은 적어도 이 프로젝트가 납기 안에 잘 끝났는지라도 봐야 한다.

이렇게 성과 측면에서 평가할 때 TheGoal에서 지적하는 부분 최적화를 피해야 함은 물론이다. 나는 완벽하게 프로그래밍했는데 기획이 잘못되서 서비스가 망했어. 이건 제대로 된 평가가 아니다. 프로젝트 성공에 대한 책임은 모두가 같이 지는 것이다. 내가 더 빨리 프로그래밍해줬으면 기획자가 더 빨리 잘못을 인지하고 수정할 수 있지는 않았을까? 이런 질문을 해봐야 한다. 굳이 성과로 회사가 돈을 얼마 벌었는가까지 봐야 하는 이유도 그런 측면이 강하다. 나라는 틀을 벗어나 프로젝트라는 컨텍스트에서 나의 역할을 평가해야 한다.

그렇다고 서비스가 망했으니 우린 모두 루저야...라고 생각할 필요는 없다. 개인의 책임과 권한의 한계가 있기 때문에 프로젝트의 성공 여부가 전적으로 내 성과랑 연결되는 것은 물론 아니다. 때때로 사람들은 프로젝트가 성공하면 자기 역할이 컸다고 생각하면서, 실패하면 자기 권한으로는 어쩔 수 없었다고 말한다. 자연스러운 심리지만 이런 피드백으로는 전문가가 될 수 없다. 성공한 프로젝트의 팀원이었던 사람을 비싼 돈 주고 스카웃해왔는데 잘 못해내는 경우를 우리는 얼마나 많이 봐왔는가. 그게 바로 내가 될 수도 있는 것이다.

예를 들어 이런 식의 평가라면 괜찮은 피드백이 될 수 있을 것이다. 이 프로젝트가 망했는데, 내가 맡은 부분은 제대로 개발했지만 다른 동료들이 맡은 부분이 제대로 안되는 걸 알면서도 팀장에게 이야기해서 대책을 마련하질 않았어. 내가 그런 사실을 미리 팀장에게 알려주고 다른 사람을 도울 수 있었다면 좀더 나은 결과가 나왔을 꺼야. 혹은 이럴 수도 있다. 이 프로젝트는 대박이 났지만 사실 나 때문에 대박 난 건 아니야. 이 서비스는 플래시 컨텐츠 때문에 대박난 건데 난 웹개발 부분만 맡았으니까. 성공한 프로젝트에 참여한 것은 자랑스럽지만 내 성과로 자랑할 프로젝트는 아니야.

그런데, 이 최종 성과라는 측면도 중요하긴 하지만 프로그래머에게 직접적인 피드백은 아니다. 많은 변수와 맥락을 고려해서 깊이 생각해야 알 수 있는 것이다. 이보다 조금 더 쉽게 얻을 수 있는 피드백이 있다.

그건 바로 제대로 돌아가게 만드는 것이다. 프로그래머라면 당연히 이 정도는 해내야 하는 거 아니냐고? 나도 그런 줄 알았다. 품질이라든가, 버그라든가, 그런 이야기를 하는 게 아니다. 그냥 기능이 동작하게 만드는 것, 그걸 못하는 사람도 많다. 프로그래머라면 코드가 지저분하든 어떻든 일단 기능이 돌아가게 만드는 것은 할 줄 알고 볼 일이다. 그게 되고 나서 코드도 정리하고 버그도 잡고 품질도 생각하는 것이다. 내가 이 프로젝트에서 필요한 기능을 제대로 만들어 내고 있는가. 이것이 일차적인 피드백이다.

물론, 이것은 너무 낮은 목표다. 이 피드백을 받아본 결과 제대로 못하는 것 같다면 프로그래머를 그만둬야 하는지도 모른다. 여기에 한 가지가 더 필요하다. XP에서는 간혹 프로그래머의 목표로 clean code that works를 제시한다.(물론 여기서 이야기하는 목표는 미시적인 목표다.) 하지만 여기서 clean code는 정확히 말하면 목표가 아니라 수단이다. 왜 clean code가 필요한가? 미학? 유지보수를 잘하기 위해서? 남들이 알아보기 쉬운 코드가 좋은 코드니까?

내가 생각하는 답은 더 빨리 개발하기 위해서다. that works를 달성한다는 전제 하에, 더 빨리 개발을 해낼 수 없다면 clean code는 무의미하다. 여기서 더 빨리의 스케일은 1시간 이상이다. 1시간 이내라면 clean code 없이 막 짜도 더 빨리 뭔가를 달성할 수 있다. 하지만 1시간을 넘어가도록 지저분한 코드를 그대로 놔두고 있다면 이미 속도가 느려진 상태일 것이다. 뭐, 1시간은 사람에 따라 차이가 있을 수도 있다고 치자. 엄청나게 똑똑한 사람이라면 1시간 정도의 컨텍스트는 아무렇지 않게 머리에 담을 수 있을지 모른다. 그래도 하루가 넘어가면 어떨까? 아침에 출근하면 어제 코드가 생생하게 그대로 머리에 컨텍스트로 들어오는가? 좋다, 당신은 똑똑한 편이다. 그렇다면 일주일은 어떤가? 한 달은? 스케일이 커질수록 clean code 없이 개발 속도는 낼 수 없다. 아마 평범한 사람이라면 하루를 크게 안 넘어가는 선에서 리팩토링이 필요해질 것이다. 단지 필요하다고 느끼지 못하는 것 뿐.

결국 필요한 피드백은 내가 얼마나 빨리 개발하고 있는가이다. 여기에는 상대 평가도 필요하다. 하지만 대개의 프로그래머는 이런 식이다. 프로그래머가 어려운 기능을 구현하는 모습을 상상해보자. 처음 개발을 시작하고 처음에는 진도가 좀 나가는 것 같다가 막힌다. 이리저리 삽질을 해보지만 잘 안된다. 야근도 해가면서 월요일부터 끙끙 머리 싸매고 열심히 개발하다가 금요일, 드디어 완료했다! 프로그래머는 완료한 기쁨에 휩싸인다. 역시 난 해냈어. 난 훌륭한 프로그래머야. that works에 대한 피드백은 확실하게 챙긴다. 하지만, 비슷한 기능을 다른 프로그래머는 이틀 만에 완료했었다는 사실과 비교해보지 않는다.

아마 대부분의 프로그래머가 생각하는 피드백은 돌아가게 만든다 수준에서 멈출 것이다. 돌아가게만 만들면 난 잘한 것이다. 그래서, 전문가로 가는 성장도 여기서 멈춘다. 프로게이머가 겪는 패배를 프로그래머는 겪지 않는다. 기한 내에 못 마치면 일정이 무리한 것이니까 내 잘못은 아니야.

꼭 다른 사람과 비교해야 하는 것은 아니다. 중요한 것은 정량적으로 측정해보는 것이다. 측정이 불가능하다고? 측정이 정확할 필요는 없다. 흔히 정량적인 측정이라고 하면 정확한 수치가 나와야 하는 것으로 생각하는데, 사실 우리가 자로 재는 것조차도 정확한 수치는 안 나온다. 자의 오차, 눈의 오차 등등으로 오차 범위란 게 있다. 단지 이런 문제는 그 오차 범위가 훨씬 더 클 뿐이다. 그래도 여전히 우리는 판단할 수 있을 만큼의 숫자를 뽑아낼 수 있다.

예를 들면 난 이런 식으로 비교해본 적이 있다. 권한 프레임웍을 만드는데 NHN에서 할 때는 개발에 2주 가량 걸렸고 적용하는데 1주 정도 더 걸렸다. 비슷한 수준의 프레임웍을 이슈 트래커를 만들 때 django로 개발했는데 사흘 정도 페어로 완료했고, 올해 초 자원봉사 커뮤니티를 만들 때는 하루 만에 만들었다. 각기 디테일도 다르고 언어도, 프레임웍도, 환경도, 프로젝트도 다르지만 어느 정도 비슷한 부분을 뽑아내서 비교할 수 있다. 물론, 같은 부분을 한 것이기 때문에 반복 효과가 있어서 이게 곧 실력의 향상은 아니라는 점도 감안해야 한다. 이처럼 다양한 오차 요인이 있지만 대략적인 측정은 가능하다.

어쨋든 돌아가게 만든다는 전제 하에 얼마나 빨리 개발할 수 있느냐는 개발자의 능력에 있어 가장 중요한 척도이며, 이것에 대한 피드백을 계속 받아야 전문가로 성장해갈 수 있다.

하지만, 난 여기서 조금 더 과격한 주장을 하고자 한다. 사실 돌아가게 만든다는 말은 여러 가지로 해석할 수 있다. 품질에 대한 척도는 사람마다 다르기 때문에 이 정도면 기능은 돌아가잖아를 보고 또 어떤 사람은 뭐 이거 제대로 쓸 수가 없잖아라고 말하기도 한다. 그럼 어느 정도 품질을 기준으로 빨리 해야 할까?

난 여기에 품질과 상관 없이 무조건 빨리 하는 게 장땡이라고 말하고 싶다. 중요한 건 최종 릴리스 때 버그 없게 나가는 것이지 매 순간순간 버그가 없어야 하는 것은 아니다. 빨리 개발하면 그만큼 빨리 버그를 발견하고 더 빨리 버그를 고칠 수 있다. 개발자가 꼼꼼히 살펴본다고 모든 버그를 발견할 수 있는 것도 아니다. 그런데 품질을 높이기 위해 신경쓰다보면 고객에게 중요한 기능을 릴리스하는 것이 늦어진다. 프로젝트 진행 중에는 대부분의 고객이 버그보다 필요한 기능이 빨리 구현되는 것을 중시한다. 그래야 그 기능이 고객에게 맞는 기능인지 아닌지를 볼 수 있기 때문이다. 완벽하게 개발해놓고 고객한데 쨘! 하고 보여줬는데 나 이거 필요 없어하는 상황을 맞이한다고 상상해보라. 그보다는 버그가 있는 상태에서 고객과 소통하는 이득이 훨씬 클 것이다.

물론, 품질을 깎아 먹은 결과로 전체적인 프로젝트가 더 느려져서는 안된다. 하나하나의 개별 작업이 빨라야 하는 것 뿐 아니라 프로젝트 전체가 빨리 끝나야 하는 것이다. 더 빨리 프로젝트를 끝내기 위해 품질을 지키려 한다면 그것은 OK다. 다만, 정말로 그 품질을 지키는 것이 프로젝트를 빨리 끝내는데 도움이 되는지 심각하게 고민해봐야 할 것이다.

TDD니 리팩터링이니 각종 기법들의 목표는 모두 더 빨리 프로젝트를 완료하는 것이다. 간혹 XP 비판론자에게서 이런 이야기를 듣는다. clean code니 뭐니 상관 없이 빨리 만들어내기만 하면 되는 것 아닌가. TDD가 추구해야 할 그 무엇은 아니지 않은가. 맞는 말이지만 허수아비 공격이다. XP에서는 clean code 자체를 추구하지는 않는다. TDD가 생산성을 높여주지 못한다면 뭐하러 TDD를 하겠는가? 리팩토링이 시간 낭비이고 프로젝트를 느려지게 만든다면 리팩토링 할 필요 없다. 이런 것들이 다 실제로 생산성을 높여줄 수 있을 때만 해야 하는 것이다.

얼마 전에 이런 질문도 받은 적이 있다. 아니 어떻게 그렇게 빨리 개발했는데 모듈화까지 이렇게 다 하셨어요? 저는 그냥 막 짜는데. 비슷한 맥락이다. clean code니까 빨리 개발할 수 있는 것이다. 머릿속에 100라인 짜리 메서드를 담아야 한다면 빨리 개발하기는 힘들 것이다.

아마도 이런 오해가 나오는 것은 실제로 clean code를 추구하느라 느리게 개발하는 사람이 있기 때문일 것이다. 사실 애자일 커뮤니티에 이런 사람이 많이 보인다. 역시 얼마나에 대한 피드백이 부족한 경우다. 자신이 얼마나 빨리 개발하는지에 대한 피드백을 받지 못하니까 열심히 clean code의 극한을 추구하는 것이다. 게다가 짧은 기간 동안은 자신이 느리더라도 길게보면 자신이 더 빠를 것이라고 생각하는 경우도 있다. 역시 장기간에 걸친 얼마나 빨리 개발하는가에 대한 피드백이 없었기 때문이다.

정리하면, 프로그래머가 생각해야 할 피드백은 크게 세 가지다. 내가 참여한 프로젝트가 성공했는가. 내가 개발한 기능은 제대로 동작하는가. 나의 개발 속도는 얼마나 빠른가. 성장을 위해 가장 중요한 것은 세번째이다. 보다시피 다른 누군가가 말로 줄 수 있는 피드백이 아니다. 내가 직접 판단하고 평가해야 하는 것이다. 물론, 팀 차원에서 이런 피드백을 할 수 있다면 더 좋을 것이다.

슬램덩크의 강백호는 누구보다 눈부시게 성장한다. 그런데, 잘 생각해보면 강백호의 학습 환경은 환상적이다. 백호가 거친 플레이를 하면 심판이 피드백을 주고 수비에 실패하면 상대편 공격수는 강백호만 노려서 공격한다. 백호가 슛 성공률이 낮으니까 쉬운 슛 찬스를 그냥 내준다. 최종 성과는 팀의 승패로 다가온다. 훌륭한 피드백 환경이다. 강백호의 강한 승부욕은 피드백에 더 민감하게 만든다. 그리고 그런 피드백을 받을 때마다 스스로 고민하기도 하지만 옆에서 코치해줄 안선생님과 채치수, 한나가 있다. 롤모델 서태웅도 있다. 이런 환경에서 성장을 못한다면 그게 더 이상할 것이다.

프로그래머도 좋은 피드백만으로 전문가가 되는 것은 아닐 것이다. 본인의 성장 의지도 필요하고 피드백에서 알아낸 상관 관계에서 인과 관계를 분석해 줄 수 있는 코치(혹은 본인의 분석력)도 필요하다. 피드백은 전문가로 가는 길의 첫걸음 정도로 생각하면 될 것이다.


 

블로그 / 소프트웨어 개발

Youngrok Pak , 10 years, 8 months ago

 


Comments




Wiki at WikiNamu