중요한 것을 잘해야 한다.
중요한 것을 잘하기 위해서는 열심히 하는 것 외에 올바른 방향으로 해야 하는 것도 포함된다. 속도(Velocity)는 속력(Speed)과 같은 크기와 방향을 함께 포함하는 물리량이다. 열심히 해서 속력을 최대로 올릴 수는 있지만 방향이 잘못된다면 나쁜 방향으로 엄청난 속력으로 달려서 크게 망할 것이다. 따라서 속력만큼 방향도 잘 정해서 속도를 제대로 내야 한다.
하지만 VUCA로 대변되는 4차 산업 혁명의 시대가 한참 지난 지금과 같이 변동성이 높은 시대에 어떻게 중요한 일을 잘할 수 있을까?
잘하기 위한 방법은 2가지가 있는 것 같다.
1. 어제보다 잘해야 하지만 절대 실패를 허용하지 않는 방법
- 실패를 하지 않고 잘하기 위해서는 어제까지 하던 방법대로 더 열심히 하는 방법 외에는 없는 것 같다. 실패가 허용되지 않는다면 말이다.
- 이 방법은 어제보다 나빠지지는 않을 것이다. 하지만 개선되는 비율도 매우 미미할 것이다.
- 우리나라의 국민 소득이 3만 달러를 넘어선 지가 꽤 된 것으로 안다. 이 방법으로는 증가하는 인건비도 충당하기 어려울 수 있다.
2. 실패를 허용하지만 큰 성과를 거두는 혁신적인 시도를 하는 방법
- 이러한 혁신적인 시도는 500% 이상의 성과를 거둘 수도 있다고 한다
- 하지만 이러한 혁신적인 시도의 90%는 실패한다고 한다.
내가 생각하는 결론은
중요한 일을 혁신적으로 하되 실패로 인한 손해를 최소화해야 한다.
는 것이다.
- 기대되는 신규 입사자가 입사했을 때 우리의 가장 중요한 과제를 해결해 주거나, 그가 스스로 우리의 가장 중요한 과제를 찾아서 제안해 주길 기대한다.
- 기대되는 인재를 멘토링하거나 새로운 조직을 맡아서 구성원들의 역량을 빠르게 성장시키려고 한다.
- 열정이 많거나 의욕이 앞서는 개발자는 중요한 과제를 잘 준비해서 한 번에 멋지게 해결하여 회사에 기여하려고 한다.
이런 기대가 잘 성공할까?
몇 가지 사례를 보자.
신규 입사자가 기존 조직의 중요한 문제를 해결해 주길 바라는 경우가 있다. 몇 가지 사례를 살펴보자.
나는 2006년 3월 Daum에 입사를 했다. 내가 입사했을 때 내가 할 일은 명확하게 정의되지 않았다. 내가 회사를 잘 살피고 중요한 일을 제안해 줬으면 한다는 말을 들었다. 입사 당시 10년 차였던 내게 경력자들이 적었던 Daum에서 내게 취할 수 있는 방법 중 하나였다고 생각된다(사실 이 글의 다른 사례에 나오지만 나도 기대되는 입사자에게 동일한 기대를 하고 유사한 태도를 취하는 실수를 했다).
당시 Daum은 3개월 간의 수습 기간이 있었다. 이때 나는 내가 알고 있는 것, 경험한 것 등을 내부 개발자들에게 공유하는 활동을 많이 했다. 어쩌면 회사에 기여하는 활동이었는지 모르지만 나는 당시 회사를 다니는 것이 너무 힘들다고 생각했다. 내가 있어야 할 이유를 없다고 생각했다. 후에 다시 생각해 보니 기존 인력들과 어울려 무엇인가를 하며 기여한다는 느낌을 받지 못하고, 나 혼자 외로이 뭔가를 하는 경우가 많았고, 실제적인 기여로 발현되지 않아서 자기만족이 안되어서였던 것 같다.
이후 퇴사를 고민하다가 8월부터 제주에서 게시판 개선 프로젝트에 참여면서 6개월 이상을 업무에만 몰두하게 되었다. 나름 기여도 하고, 인정도 조금씩 받기 시작하면서 어느새인가 Daum에 적응되었다. 물론 주변의 훌륭한 선후배 동료분들이 나의 적응을 도와 주워서 가능했다. 육체적으로는 정말 힘들었지만 그전에 정신적 어려움을 겪고 있었기 때문에 육체적 어려움은 크게 느껴지지 않았다.
내가 Daum에서 게시판 개발 팀장이 되었을 때 신규 입사자들의 빠른 적응을 돕는 것이 어려움으로 다가왔다. 이때는 위키를 전달하고 스스로 공부하고 모르는 것은 물어보라고 하는 게 경력직 온보딩의 방식이었다. 그런데 이런 방식에서 빠르게 적용하는 분들은 찾아보기 어려웠다. 그때는
"Daum에 있는 분들이 너무 뛰어나서 새로 입사한 분들이 기존 Daum 직원들과 함께 성과를 내려면 오래 걸리나 보다"
라고 생각을 했었다.
한참 시간이 지난 후에는 신규 입사자들의 역량이 문제가 아니라 우리가 작성한 위키가 부족해서 온보딩이 어려운 것은 아닌가라는 생각까지는 했었다.
이후에 신규 입사자가 입사를 하면 초기 수개월은 많은 대면 협업을 통해 집중적으로 알려줬었다.
내가 할 수 있는 수준으로 빠르게 올라오기를 바라면서...
Unix 환경에서 Client / Server 개발, EJB 개발 등을 하다가 Daum에 입사한 이후 본격적으로 사용한 spring은 테스트 작성이 쉬웠기 때문에 테스트 작성, TDD, 리팩터링, 객체지향 설계 등을 알려주려고 노력했다. 너무 쉽게 그런 원칙들을 실행할 수 있는 환경이라고 생각했기 때문이다.
하지만 아무리 쉬워도 학습과 연습을 통한 역량 향상에는 시간이 걸린다. 그때는 그 부분을 간과했었다. 지식, 경력 등에서 오는 차이를 인정하지 않고 한 번에 높은 수준으로 성장하길 기대하는 실수를 한 것이다.
앞서 언급한 대로 혁신적 시도의 90%는 실패한다고 한다. 하지만 500% 이상의 성과를 거둘 수 있기에 혁신적 시도를 해야만 한다. 복잡하고 어려운 혁신적 시도를 사전에 완벽하게 준비하여 한번에 해결하려고 하는 경우를 본다. 본인은 충분히 준비되어서 주변 사람들의 우려가 발생할 일이 없다고 생각한다.
최근에 그런 경우가 있었는데, 준비해 온 분들이 마음을 상하더라도 진행을 중지하자고 결정을 한 경우가 있다. 반복적, 점진적으로 진행할 수 없고, Big Bang 방식으로 한 번에 변경해야 해서 가역성(Reversible)이 없다면 더 준비해서 반복적, 점진적, 가역적으로 할 수 있을 때 진행하자고 했다. 이번에는 우리 실력이 부족해서 적용하기 어렵고 다음에 실력을 키워서 안전하게 하자고 했다. 구성원들에게는 미안하고, 아쉬운 결정이었지만 나는 이 결정에 후회는 없다.
또 향후 개선이 예상되는 변경을 미리 하자고 했을 때 다소 추가적인 작업이 발생하더라도 개선의 효과를 측정할 수 있을 때 적용하자고 했다. 지금의 성과를 측정할 수 있고, 개선을 적용한 후 성과를 측정하여 비교할 수 있어야 개선을 하기 위해 소요되는 비용을 경영진에 설명할 수 있다고 생각했기 때문이다. 이 부분은 지금도 할 수 있지만 보다 효과적으로 하기 위해 미룬 것이라고 생각한다.
이런 아쉬운 일들이 발생하는 이유를 다음과 같이 3가지 측면에서 생각해 봤다.
- TDD의 3가지 단계 중 "Make it work"에서 왜 빠르게만 만들라고 하는지
- 켄트벡이 말하는 "아기 발걸음(Baby Step)"이 왜 중요한 것인지
- Kent Beck의 Tidy First에서 나오는 할인된 현금 흐름(Discounted Cash Flow)과 옵션(Option)은 어떤 의미인지
TDD에서는 실패하는 테스트를 추가한 후에 최대한 빠르게 동작하도록 만들고, 그다음에 리팩터링을 하라고 한다. 왜 동작하도록 하는 것과 리팩터링을 함께 하지 않을까? 어차피 한 사람이 두 가지 일을 다 하는 경우가 많은데 말이다.
켄트벡은 한 번에 2가지를 잘하기 어려워서 나눠서 해야 한다고 설명한다. 이 말에 공감한다. 내 경우도 뭔가 빠르게 동작하도록 노력할 때 객체지향 원칙, 디자인 패턴 등을 적용해서 좋은 설계를 함께 얻으려고 한 경우가 꽤 많았다. 이 경우 빠르게 동작하도록도 못했고, 좋은 설계를 얻지도 못했다. 그렇다. 빠르게 동작하도록 만든 후 리팩터링을 통해 설계를 개선해야 한다. 테스트가 있기 때문에 설계를 공격적으로 변경할 수도 있다.
2가지를 분리해야 하고 최대한 빠르게 만드는 것이 중요한 또 다른 이유가 있다.
TDD, Where Did It All Go Wrong에서 이안 쿠퍼(Ian Cooper)는 Make it work 단계에서 duct tape programming을 해야 한다고 한다.
위와 생긴 duct tape는 모든 곳에 사용할 수 있는 만능 테이프로 빠르게 문제를 해결할 수 있다. 예를 들어 냄비에 구멍이 났을 때나 난로 연동에 구멍이 났을 때 구멍을 메우기 위해 사용할 수 있다. 많은 경우에 빠른 해결책을 제공한다. 하지만 제대로 된 해결책은 아니다. 임시방편이다. duct tape programming도 마찬가지이다. 빠르게 비즈니스 요구사항을 해결하지만 제대로 된 해결책이 아니어서 기술부채를 유발하거나 다른 문제를 유발한다.
그럼 왜 이안 쿠퍼는 duct tape programming으로 문제를 해결해야 한다고 하는 것일까? 작년 하반기부터 업무를 하면서 느낀 것인데 우리는 문제를 다 풀어보기 전에는 문제를 제대로 이해 못 하는 경우가 많다. 문제를 이해했다손 치더라도 문제를 해결하면서 발생 가능한 이슈를 사전에 알기는 매우 어렵다. 그래서 땡빵을 하더라도 문제를 빨리 풀어보면서 문제를 이해해야 한다는 이안 쿠퍼의 말이 뼈저리게 와닿았다.
이제는 잘할 수 있더라도 동작하도록 할 때는 복붙, 스택오버플로우, GPT 등을 이용해서라도 빠르게 문제를 해결해야 한다는 것을 글을 읽는 분들도 공감하실 것이라 생각된다.
켄트 벡은 큰 일을 잘하려면 잘게 나눠서 아기 발걸음처럼 잘게 나눠서 실행해야 한다고 말하곤 한다. Tidy First에서도 지네의 발 움직임처럼 작게 움직여야 한다 했다.
작은 단계를 엄청나게 빠른 속도로 밟아나가서 마치 도약하는 것처럼 보일 수도 있다
지네는 많은 발로 매우 조금씩 움직인다. 하지만 전체적으로는 매우 빠르게 움직인다(https://www.youtube.com/watch?v=D44iU1Ak7_o&t=5s 이 영상을 한번 보시라 ^^).
A Daily Practice of Empirical Software Design - Kent Beck - DDD Europe 2023 이 영상에 켄트벡은 이런 이야기를 한다.
4~5년 차 훌륭한 개발자은
- 문제를 열심히 푼다.
- 주니어 개발자는 복잡성을 다루는 방법을 모른다
- 트릭, 기술을 배우면서 조금씩 복잡성을 다루게 된다.
- 이런 사이클을 4~5년 하는 것은 좋다.
하지만 점점 스킬을 얻어서 점점 복잡한 것을 다루는 뇌가 포화되면 학습 전략이 바뀐다.
전문가들의 문제 접근 방법은 마법사 같은 힘을 사용하지 않는다.
전문가들
- 문제를 작은 문제로 분리해서 일반적인 수준의 기술로 처리할 수 있도록 함
- 이런 분해는 많은 창의력과 기술을 요함
- TDD도 복잡성 분리 전략임(complexity partitioning strategy)
- 어떻게 구현할지 모른다면 테스트를 먼저 추가. 이후 구현은 쉽다. 하지만 함께 하면 힘들다
- make it run, make it right
- 한 번에 하나씩 하면 뇌가 감당 가능하다. 하지만 함께 하면 과부하가 걸린다.
즉, 복잡한 일을 복잡하게 처리하는 마법이 아니라 작게 나눠서 빠르게 진행하는 것이 기술인 것이다.
특히 혁신적이거나, 복잡하거나, 처음 시도하는 일을 실패할 확률이 높다. 그러니 작게 나눠서 롤백해도 아깝지 않은 단위로 작게 나눠서 빠르게 진행하자(나는 git reset --hard HEAD를 정말 많이 한다).
다시 말해, 치밀하게 계획을 해서 한 번에 거대한 일을 처리하는 것(예언가의 역량???)이 아니라 빠르게 완료하면서 문제를 이해하고, 이슈를 파악하고, 후에 변경이 요구될 때 안전하고 빠르게 변경하는 것이 개발자에게 필요한 역량이다
Tidy First에서 켄트벡은 지금 정리를 할지? 아님 지금은 비즈니스에 도움이 되는 구현을 먼저 하고 정리는 나중에 할지? 결정하는 것과 관련해서 비즈니스 관점에서 설명하기 위해 할인된 현금 흐름(DCF.
Discounted Cache Flow)과 옵션(선택 가능성)을 언급한다.
내일 돈을 받는 것보다 오늘 돈을 버는 것은
- 당장 쓸 수 있고
- 미래를 위해 오늘 투자를 할 수도 있고
- 내일 못 받을 가능성도 없어서
더 가치가 있다. 이것이 할인된 현금 흐름의 개념이다.
그래서
- 높은 확률로 돈을 벌고(높은 확률로 돈을 버는 쪽을 선택하고), 낮은 확률로 나중에 돈을 써라(미래를 위한 투자라고 생각됨)
- 정리(tidying)를 먼저 하지 말라. 정리를 먼저 하는 것은 돈을 더 일찍 쓰고, 나중에 버는 것이다.
- 나중에는 정리가 필요치 않을 수도 있음
이라고 한다.
이에 반해 옵션은
- 나중에 더 많은 돈을 벌기 위해 설사 정확한 방법을 모르더라도 지금 돈을 쓰라고 함
- 옵션이 생길 일이 명백하면 정리를 먼저 하라
고 한다.
개발자들은 필요, 효능이 예상되는 곳에 미리 뭔가(추상화, 사전 설계 등)를 추가하는 경향이 있다. 나도 구현을 하다 보면 지금 필요한 것 외에 뭔가를 더 할 때가 많다. 구현을 하다 보면 문제를 더 잘 이해하고, 이슈를 발견한다. 그러면서 지금 하고 있는 일에 추가적으로 발견한 뭔가를 더하게 된다. 이럴 때는 그 일을 바로 하기보다 백로그에 저장하고 나중에 우선순위를 정해서 하는 것이 대개는 맞다.
Clean Craftmanship에서 로버트 마틴은 누군가 "뭔가가 필요할 것이다"라고 말한다면 "필요하지 않다면 어떨까?"라고 반문하라고 한다(YAGNI). 나는 이 말에 매우 공감한다. 대개의 경우 필요할 것이라고 예상했던 것이 없더라도 별일이 발생하지 않는 경우가 많았다. 그저 그 당시에 뭔가에 꽂혀서 그게 필요할 것이라는 토끼굴(본래 하려던 것 외에 다른 뭔가에 빠진 경우)에 빠진 경우가 많다.
정리를 해야 한다는 생각이 든다면 지금 정리를 하지 않고 기능 구현을 하면 어떨지 생각해 보는 것이 필요하다.
미리 개선을 하면 후에 효과가 나와도 개선의 효과인지 알기 어렵다. 효과를 측정할 수 있을 때 개선을 하는 것이 좋다. 다시 한번 말하지만 엔지니어에게 필요한 역량은 필요할 때 빠르고 , 안전하게 변경하는 것이지 미리 예측하는 것이 아니라고 생각한다.
온보딩 후, 팀원들이 떠나버렸다 를 보면 스타트업의 대표인 저자는 팀원들이 주어진 일만 하기보다는 함께 숲을 바라보고 필요한 일들을 주도적으로 찾아나가길 바랐다고 한다.
"당장 나무부터 베려고 하지 말고, 숲을 보고 이해하라"
라고 신규 입사자들에게 요구했었다고 한다. 그랬더니 입사 후 시간이 어느 정도 흐른 후에
"나보다 더 적합한 사람이 있을 것 같다"
며 퇴사를 하더라고 한다. 그들은 기여하지 못하고 있다는 느낌을 가진 것 같더라고 한다. 인간의 제대로 쓰임 받고자 하는 욕구’, ‘인정받고 싶은 욕구’가 충족되는 게 얼마나 중요한지 깨닫게 되었던 순간이었다고 한다(이게 내가 Daum에 입사하고 수습기간이 끝났을 때 회사를 그만두고 싶었던 마음인 것 같다).
이후 저자는 합류와 동시에 구체적인 업무와 기대하는 점을 말씀드리고, 빠른 시일 내에 팀에 기여하는 결과물을 만들어낼 수 있도록 최선을 다해 도왔다고 한다. 그랬더니 회사의 성장에 다시 가속도가 붙었을 뿐만 아니라 신규 입사자들이 회사를 이해하는 속도가 훨씬 더 빨라지기 시작했다고 한다.
나도 지금 회사에서 오픈마켓 상품개발팀 팀장 출신의 개발자가 입사했을 때 가장 중요한 일을 맡겼는데 그때 서로 어려웠었다. 이후 CS, 작은 변경 등을 맡겼는데 이때부터 성과가 나고 중요하고 거대한 일도 도움이 되기 시작했다.
위키를 던져주고 알아서 적응하라고 하면 지금 일을 잘하는 분들에게 중요한 일을 할 시간을 많이 확보할 수 있다. 하지만 신규 입사자들과 역량이 부족한 분들은 계속 생산성을 높일 수가 없다.
우리 팀의 에이스의 시간이 들더라도 사소한 것이라도 바로 기여할 수 있도록 도와주는 것이 팀을 위해서 중요하다.
몹프로그래밍, 짝프로그래밍 등을 통해 같이 해 보면서 배우는 게 시간이 걸리는 것 같지만 사실은 가장 빠르고 효과적인 방법인 것 같다. 처음 난 이런 방식들에 부정적인 감정을 가지고 있었다. 우리 팀 에이스가 자신의 일에 시간을 들이지 못하고 스스로 배워야 할 부분을 알려주는 것 같은 느낌이 들었다. 하지만 이런 경험이 쌓이니 팀 전체의 생산성과 역량이 높아지는 것을 목격하게 되었고 이젠 온보딩, 지식 전달 등에 몹/짝프로그래밍이 효과적이라고 생각한다.
Emily Bache의 강연을 좋아한다. 그중 How SOLID & TDD Paved the Way to Success at Ferrari를 보면
교육이나 강의로 배울 수 있는 것과 그럴 수 없는 것
에 대한 내용이 있다.
Scala는 나름 배우기 어려운 언어라고 생각한다. 에밀리의 팀은 Scala를 다 함께 강사에게 배우고, 팀으로 돌아와서 이미 좀 익숙한 팀원의 도움을 받아 팀에 안착시킨 경험이 있었다고 한다. 강사에게 배운 것이 효과가 있었다고 한다.
그런데 페라리팀은 SOLID, 객체지향설계, TDD 등을 배웠지만 효과가 없었고, 코치(TDD 등을 함께 하는)들과 수년 동안 짝프로그래밍 등을 통해 팀과 같이 일하면서 팀원들은 SOLID, 객체지향설계, TDD 등에 대해 배웠다고 한다.
이 경험에 나는 매우 공감한다. TDD, 리팩터링 등은 책을 보고 배우기엔 과정, 절차가 안 보이고, 강사에게 배우기엔 예제가 실제 개발자들이 다루는 코드와 거리가 멀어서 효과적이지 않다. 팀원과 같이 앉아서 짝프로그래밍을 하거나, 팀 내에서 다양한 경우에 대한 공유를 하는 것이 훨씬 효과적이다.
온보딩, 중요한 일을 잘하는 방법 등도 마찬가지인 것 같다. 같이 일하는 동료를 통해서 배우는 것이 가장 효과적이다. 일을 하면서 배우는 것이 효과적이다.
Tidy First에 이런 내용이 있다
가장 좋은 추상화는 대개 실행 중인 코드에서 발견된다. 추측(Speculation)으로는 절대 추상화를 만들 수 없다.
이 문구도 우리가 책이나 강의를 통해서 공부해야겠지만 현업에서 실천적으로 일하며 설계하고 배워야 하는 중요한 근거라고 생각된다.
너무 큰 일을 먼저 하려고 하지 말고, 바로 성과가 나는 일을 먼저 하면서 정리(?)를 하면 큰 일로 기여할 수 있게 되는 것 같다. 큰 일을 할 때는 복잡하고 어려운 기술이 아니라 일상적인 수준의 기술로 무난히 해결할 수 있는 수준으로 잘게 나눠서 빠르게 진행을 하자.
계획이 없는 것도 안 좋지만, 너무 이르고, 구체적이고, 고정된 계획에 사로 잡히는 것도 안 좋은 것 같다. 특히 지금과 같은 변동성이 높은 시대에는 말이다. 방향에 대한 계획은 반드시 필요하다. 매일 수정을 하더라도 말이다. 하지만 지금 비가 오는지를 알기 위해 창문 밖으로 손을 내밀어 보면 되는데, 일기 예보를 기다리는 계획을 세우는 것은 어리석다. 계획을 세워 의도한 대로 살자. 하지만 예측하기 어려운 미래에 대해 너무 많은 추측으로 구체화된 계획을 세우기보다는 작고, 빠르게 실행해 보며 피드백을 기반으로 실행해 나가자.
거대 사전 설계(Big Upfront Design)가 통하던 세상이 아니다. Agile(민첩)하게 동작하도록 만들면서 문제를 정확히 이해하고, 이슈를 파악하고, 필요한 개선을 필요한 때에 안전하고 빠르게 할 수 있는 역량이 필요한 세상이다.