brunch

You can make anything
by writing

C.S.Lewis

by 백명석 Jul 06. 2024

빠르게 하는 것의 중요성

제대로 문제를 해결하는 방법

0. 빠르게 잘하는 방법

주어진 시간에 문제를 잘 해결하기 위해서는 일단은 문제를 처음부터 끝까지 빠르게 풀어보고 남은 시간에 좋은 답변을 만들기 위해 노력해야 한다.

왜 이렇게 분리해서 진행해야 하는지 이 글에서 설명해 보겠다.


1. 한 번에 잘할 수 있다고 믿는 사람들

문제를 빠르게 잘 풀기 위해서는

 소여물 먹듯이 반복

을 해야만 잘할 수 있다. 

어떤 작곡가도 한 번에 음악을 작곡하지는 않는다. 모두 여러 번 반복해서 다듬으며 명곡을 작곡한다.

좋은 소프트웨어를 개발을 하는 것도 마찬가지이다. 소프트웨어 개발이 아닌 모든 알려진 답안이 없는 문제 풀이가 동일할 것이다.

그런데 왜 한 번에 잘하려고, 좋은 답안을 만들려고 노력하는지 알아보자.

영리함의 오류

영리한 프로그래머,아니 자신이 영리하다고 여기는 프로그래머들은 볼링 게임에서 플레이어가 볼링공을 투구해서 핀을 쓰러뜨리면 호출되는 roll 함수를 구현할 때 인자로 받은 핀의 수만큼 쓰러뜨리는 것 외에 이때 점수를 더하는 일도 같이 한다. 투구할 때마다 함수가 불리고 투구별 점수를 더하기만 하면 됐으므로(할 수 있어서) 덧셈을 여기에 넣어 버렸다. 정말 영리하기 짝이 없다.

하지만 후에 스페어, 스트라이크를 했을 때 점수를 계산하려면 핀이 쓰러졌을 때 계산을 완료할 수 없고, 이후 1~2 프레임의 투구 기록이 필요하다. 투구하는 것과 분리해서 점수 계산은 별도 해야 하는 것이다(로버트 C. 마틴의 소프트웨어 장인 정신 이야기에 나오는 예제. 후에 변경이 필요할 때 너무 견고해서 느려짐)

입사

또 다른 예로 입사가 있다. 학교를 졸업한 학생들은 대기업에 취업하려고 한다. 그런데 대기업들은 경력직만 채용하려고 한다. 신입들은 자신들에게 기회를 주는 곳에서 업무 수행을 통해 지식과 경험을 쌓으며 자신이 원하는 큰 회사에서 요구하는 역량을 맞추는 것이 맞을 것이다. 하지만 어떤 취업 준비생들은 본인이 원하는 회사에 입사하기 위해 재수(?)도 불사한다.

전문가들의 문제 접근 방법은 마법사 같은 힘을 사용하지 않는다.

Mastering Programming - by Kent Beck에 다음과 같은 내용이 있다.

4~5년 차 훌륭한 개발자들

- 문제를 열심히 푼다.

- 주니어 개발자는 복잡성을 다루는 방법을 모른다

- 트릭, 기술을 배우면서 조금씩 복잡성을 다루게 된다.

- 이런 사이클을 4~5년 하는 것은 좋다.

- 점점 스킬을 얻어서 점점 복잡한 것을 다루는 뇌가 포화되면 학습 전략이 바뀐다.

반면에 전문가들

- 문제 접근 방법은 마법사 같은 힘을 사용하지 않는다.

- 문제를 작은 문제로 분리해서 일반적인 수준의 기술로 처리할 수 있도록 한다.

- 이런 분해는 많은 창의력과 기술을 요한다.

- 행위와 구조 분리도 좋은 예이다.

- TDD도 복잡성 분리 전략이다(complexity partitioning strategy). 어떻게 구현할지 모른다면 테스트를 먼저 추가한다. 적합한 테스트 추가에 비해 구현은 쉽다. 하지만 함께 하면 힘들다make it run, make it right 해야 한다. 한 번에 하나씩 하면 뇌가 감당 가능하지만, 함께 하면 과부하가 걸린다.


주니어들은 복잡한 문제를 복잡한 상태에서 복잡한 기술을 도입해서 어렵게 해결하려는 모습을 종종 보인다. 이런 경우 느리고, 초기에 의도한 대로 좋은 품질을 보이지 못한다.

이에 반해 역량이 뛰어난 개발자들 중에는 복잡한 문제를 잘게 나눠서 일정 추정도 쉽고, 실패했을 때 롤백하기 쉽고, 빠르게 구현 가능하는 모습을 보여준다.

작게 움직이지만 작은 움직임을 매우 빠르게 하는 지네처럼 움직여야 하는 것이다.

이상한 나라의 수학자

이 영화에서 어떤 사람이 수학을 잘하느냐고 학생이 천재 수학자에게 묻는다.

똑똑한 사람이냐고 물으니, 그들이 제일 먼저 자빠진다고 한다.

그럼 열심히 하는 사람이냐고 물으나, 그들이 두 번째로 먼저 나자빠진다고 한다.

그럼 어떤 사람들이 수학을 잘하느냐고 물으니 어려운 문제를 만나서 못 풀면, 

요 놈 봐라. 어려운데... 내일 다시 해 봐야지

이런 자세를 갖는 사람들이 수학을 잘한다고 한다.

그렇다 똑똑하고, 열심하는 것만으로는 부족한 것이다. 앞서의 예들과는 다르지만 꾸준함을 잃지 않고 여러 번 시도하는 사람이 잘하는 것 같다. 크게 한 번에 양으로 승부하지 말고, 작더라도 자주 빈도로 승부해야 하는 것 같다.

익히기 어려운 기술을 익힐 때도 마찬가지이다. 어려운 문제이니 한 번에 잘하지 못할 것이라고 생각하자. 한 번에 잘할 수 있다면 아마 그리 어려운 기술이 아닐 것이다.

내 경우도 한 번에 잘 안 되는 것들이 많았다. 하지만 시간 차를 두고 여러 차례 시도하니 점점 나아지는 경우가 많았다.

2. 빠르게 잘하는 방법

시간 내에 잘하는 것이 내 실력이다. 1시간짜리 시험을 치르는데 시간이 부족하다고 2시간을 써서 100점을 받았다고 100점은 아닌 것이다.

먼저 제한 시간을 준수하는 것이 우선이다. 아니면 낙제다.

개발자들이 기능 구현을 하는 것도 마찬가지이다. 일정을 확보하는 것도 중요하지만 일정을 준수해서 비즈니스에 기여하는 것도 중요하다.

정해진 시간 내에 빨리 끝까지 해보고, 남은 시간에 잘하기

가 필요하다.

왜 먼저 끝까지 해 봐야 할까?

처음부터 끝까지 기능을 구현해 봐야 

- 요구사항/문제를 정확히 이해할 수 있고

- 문제 해결 시 발생 가능한 이슈를 명확히 알게 된다(예측으로는 부족함)

동작하도록 만든 후에 좋은 구조를 갖도록 설계를 개선할 때 내 생각에는 

100% 말고 60% 정도만 개선

하는 것이 좋다.

문제에 대한 치열하게 고민하고 있는 지금 나의 맥락을 가지고 내가 할 수 있는 100%까지 개선하면 동료들이 알아보지 못한다. 우리는 함께 해야 한다. 미래의 나도 남이다.

정말 잘해야 한다면 후에 다시 고칠 기회가 있을 것이다.

할 수 있지만 지금 당장 필요치 않다면 나중을 위해 참을 수 있는 능력이 전문가에게 필요한 역량 중에 하나인 것 같다. 지금 충분한 수준으로만 개선하는 것이 경제적이기도 하고, 실제로도 더 좋다.

시간이 흐른 후에 다시 그 코드를 본다면 웃음이 날 수도 있다. 왜 그렇게 했을까? 더 좋은 방법이 있는데라는 생각이 들 수도 있다. 나중에 더 필요해서 더 많은 개선을 한다면 그때는

나의 실력이 더 좋아졌을 수도 있고,

나의 도메인 지식이 더 많아졌을 수도 있고,

개선 대상이 개선이 용이하도록 환경이 변했을 수도 있다.

duct tape programming으로 빠르게 풀고, 다음 문제를 시작하기 전에 설계 개선

하는 것이 중요하다. 

핵심가치(끝까지 빨리 풀고 잘하기)에 집중하고 토끼굴에 빠지지 말아야 한다.

그렇지 않으면 중요치 않거나 할 필요가 없는 일에 시간을 낭비하게 된다.

반드시 다음 문제를 시작하기 전에는 필요한 만큼 개선을 해야 한다. 그렇지 않으면 기술부채가 생겨 점차 느려져서 경쟁에서 뒤처지게 된다.

3. 빠르게 하는 것의 가치

실패하지 않기 위해 계획, 예측을 많이 하면

- 느려진다

- 아무리 예측을 잘하고 준비해도 예상치 않은 문제가 발생한다

- 사전에 예측을 하다 보면 디테일에 몰입해 토끼굴에 빠지는 경우가 많다

지금과 같이 속도가 중요한 시대에서는 빠르게 전체를 동작하도록 만들고 각 부분의 정확성을 높이는 전략이 효과적이다. 

일을 빠르게 하는 것 자체가 목적은 아니다.

주어진 시간 안에 동작하는 온전한 해결책을 빠르게 만들고, 필요한 만큼 개선을 하기 위한 시간을 확보하는 것이 궁극적인 목적이다.

할 수 있다고 필요 이상의 개선을 하는 것의 문제

지금 할 수 있다고 끝까지 하지 말자. 너무 견고해져서 나중에 변경하기 어려워질 수 있다. 필요한 만큼만 개선하고 빠르게 진도를 나가자. 로버트 C. 마틴의 소프트웨어 장인 정신 이야기에서

규칙 3. 최상의 결과를 추구하지 말라

라고 말한다. 왜 최상의 결과를 추구하지 않았을까? 

최상의 결과를 너무 일찍 추구하면 주변의 세부사항을 죄다 놓치기 쉬워서다

재작업의 가치

Present Factory Chapter: The Incentive Paradox in Software Design 에서 켄트 벡은 테스트가 성공한 후에 리팩터링을 하는 재작업에 대해 다음과 같이 말한다.

- 리팩터링은 재작업하는 것처럼 느껴질 수 있고, 설계를 다듬는다는 것은 과거의 오류를 바로잡는 것처럼 느껴질 수 있지만, 이러한 재작업은 과소평가된 설계의 가치이다

- 왜 처음부터 제대로 설계하지 않았을까?

- 이전 구조는 실수가 아니었다

- 시스템을 살아있게 했고, 시스템의 맥락(탐색 또는 확장)에서의 필요를 반영한 것이었습니다

- 이제 그 맥락이 바뀌었을 뿐이다.


TDD 사이클 중 Green에 해당하는 make it work 단계에서는 빠르게 동작하도록 하라고 한다.

Ron Jeffries는 “clean code that works”가 중요하다고 했는데, 켄트 벡은 이걸 한 번에 할 수 없다고 한다. 인간은 한 번에 2가지를 동시에 잘 못한다고…

특히 빠르게 성공시키는 것과 좋은 설계는 대립 관계이다.                


한 번에 잘하려고 철저히 예측하고 계획을 세우려고 하는 분들과 초반에 빈틈이 있더라도 끝까지 동작하게 한 후에 문제를 해결해 나가며 개선을 하는 분들을 보며 느낀 점을 정리해 봤다.

나는 동작한 후에 개선하는 방향을 취한다. 그래서 사전에 설계를 시작할 수 있는 수준만 하고, 동작하도록 테스트 코드에 대충 작성한 후에 리팩터링을 통해 좋은 구조를 갖도록 한다. 사전 설계가 종이나 화이트보드에 온갖 예측을 가지고, 머리를 무겁게 하며 설계를 하는 것이라면 리팩터링동작하는 코드를 가지고 빠르게, 자주 피드백을 받으며 하는 설계라고 생각한다. 후자가 머리를 가볍게 하고, 빠르게 구현하고, 언제든지 실행을 통해 피드백을 받아볼 수 있는 방법이라고 생각한다.

현재는 숲에서 길을 잃기 쉬워서 과도하더라도 철저한 사전 설계를 통해 현재 위치와 앞으로 갈 방향을 알아야 하는 시대가 아니다. 지금은 목적지를 입력하고 대략의 경로를 확인하여 가벼운 계획을 세운 후 내비게이션(IDE 같은 도구)에 의지하며 빠르게 목적지로 갈 수 있다. 혹여 경로가 틀렸더라도 작은 변경을 통해 본래의 경로로 돌아갈 수 있다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari