개발자처럼 생각하는 방법 - 문제 해결의 교훈(How to think like a programmer — lessons in problem solving)

개발에 관심이 있다면 아마 이런 글을 본적이 있을 것이다:
"이 나라의 모든 사람들은 프로그래밍을 배워야합니다. 왜냐하면 생각하는 법을 가르쳐주기 때문이죠."- 스티브 잡스(Steve Jobs)
개발자처럼 생각하는 것이란게 정확히 무슨 의미이고, 어떻게 할 수 있는 것일까?
본질적으로, 이것은 어떻게하면 문제를 더 효과적인 방법으로 해결 할 수 있을까에 대한 것이다.
이 글은 바로 이것을 알려주기 위한 것이다.
이 글의 마지막 쯤에 당신은 더 나은 "문제 해결사"가 되기 위해 정확히 어떤 단계를 거쳐야 하는지 알 수 있을 것이다.

왜 이것이 중요한가?

문제 해결은 메타 기술(meta-skill)이다.
우리는 모두 크던 작던 어떤 문제(problem)를 가지고 있다. 우리가 이런 문제에 대처하는 것은 가끔은, 음.. 꽤 임의(random) 적이다.
당신만의 시스템이 없는 한, 아마도 문제를 "해결" 하는 방법은 이럴 것이다:
  1. 해결책을 시도.
  2. 해결 되지 않으면 다른 방법을 시도
  3. 그래도 문제가 해결되지 않으면 2단계 반복
뭐, 가끔 운이 좋을 때도 있다. 하지만 이것은 문제를 해결하는 최악의 방법이다! 이것은 엄청난 시간 낭비다.
가장 좋은 방법은 a) 프레임워크를 만들고 b)그것을 연습하는 것이다.
"거의 모든 고용주들은 문제 해결(problem-solving) 능력을 우선시합니다. 문제 해결 능력은 거의 만장 일치로 고용주들이 언어 프로그래밍 능력, 디버깅, 시스템 설계보다 더 중요하다고 생각합니다. 컴퓨팅 사고(computational thinking)나 크고 복잡한 문제를 나누는 능력은 실무에 필요한 기본적인 기술 능력(어쩌면)보다 더 가치가 있습니다."— Hacker Rank (2018 Developer Skills Report)

프레임워크를 만들자

적절한 프레임워크를 찾기 위해 나는 팀 페리스(Tim Ferriss)의 “The 4-Hour Chef”라는 책의 조언을 따랐다.
나는 C. Jordan Ball(65,000명 이상의 사용자가 있는 Coderbyte에서 1, 2위에 랭크되어 있는)과 V. Anton Spraul(Think Like a Programmer: An Introduction to Creative Problem Solving"라는 책의 저자)라는 두 명의 인상적인 사람들을 인터뷰했다.
그들에게 똑같은 질문을했는데, 대답은 꽤 비슷했다!
곧, 여러분도 알게 될 것이다.
사이드 노트 (Sidenote): 그렇다고해서 모든 것이 똑같다는 것은 아니다. 모든 사람은 다 다르고, 당신 역시 다르다. 하지만 우리 모두가 좋다고 동의하는 원칙으로 시작한다면 훨씬 더 많이 더 빠르게 발전 할 수 있을 것이다.
"새로운 프로그래머들이 저지르는 가장 큰 실수는 문제를 해결하는 법을 배우는 대신 문법을 배우는 데 치중 한다는 것이다." - V. Anton Spraul
그렇다면, 새로운 문제에 직면했을 때 무엇을 해야 할까?
다음 단계를 따른다:

1. 이해(Understand)

무엇이 문제인지 정확히 알아라. 대부분의 어려운 문제들은 이해가 되지 않기 때문에 어려운 것이다(따라서 이것이 첫 번째 단계인 이유이다).
문제를 이해 했는지 어떻게 알 수 있을까? 글(plain English)로 설명 할 수 있다면 문제를 이해 한것이다.
어떤 문제를 설명하다가 전에는 보지 못했던 로직(logic)의 허점(holes)을 발견하게 된적이 있지 않았는가?
대부분의 개발자들은 이것이 어떤 느낌인지 알 것이다.
그렇기 때문에 문제를 풀기전에 적어보거나 다이어그램을 그려보거나 다른 사람에게 이야기 해야 하는 이유이다 (또는 어떤 사람들은 rubber duck을 사용한다).
"단순한 용어로 설명 할 수 없다면, 이해하지 못한 것이다."- Richard Feynman

2. 계획(Plan)

계획없이 바로 뛰어 들지 말자.(그리고 어떻게든 당신이 그럭저럭 해나갈 수 있기를 바란다.) 솔루션을 계획하자!
문제를 풀 수 있는 정확한 단계를 적을 수 없다면 아무 쓸모가 없는 것이다.
개발에서 이것은 곧바로 문제에 뛰어들지(hacking) 말라는 의미다. 머리로 문제를 분석하고 정보를 처리하기위한 시간을 주자.
좋은 계획을 세우려면 다음 질문에 답해보자:
"주어진 입력 X가 출력 Y를 리턴(return)하는 데 필요한 단계는 무엇일까?"

3. 나누기(Divide)

주의를 기울이자. 이것이 가장 중요한 단계이다.
단번에 큰 문제를 해결하려고하지 말자.
대신 문제를 하위 문제로(sub-problems) 나눈다. 이렇게 문제를 나누면 훨씬 쉽게 해결할 수 있다.
그런 다음 각 하위 문제를 하나씩 해결한다. 가장 간단한 것부터 시작한다. 가장 단순한 것은 답을 이미 알고 있거나 답을 거의 알 수 있다는 거와 같다.
여기서 가장 단순하다는 것은 이 해결된 하위 문제가 다른 하위 문제들에 의존하지 않는다는 것을 의미한다.
모든 하위 문제가 풀렸다면 이제 점을 연결해보자.
모든 "하위 솔루션"을 연결하면 원래의 문제에 대한 솔루션을 얻을 수 있다. 축하한다!
이 테크닉이 문제 해결의 기본이다. 꼭 기억하자 (필요하다면 다시 읽어보자).
"내가 만약에 처음 시작하는 개발자들에게 한가지 문제 해결 방법을 알려 준다면 그건 문제를 줄일 수 있는 방법일 것이다.
예를 들어, 당신이 만약 초급 개발자(new programmer)이고, 10개의 숫자에서 3 번째로 높은 숫자를 찾는 프로그램을 작성해야한다고 가정 해보자. 기본적인 프로그래밍 지식만 있다면 어렵지 않겠지만 당신에겐 까다로운 과제 일 수 있다.
어떤 문제에 막혔다면, 문제를 좀 더 간단하게 줄여야한다. 세 번째로 높은 숫자 대신 가장 높은 수를 찾는 것은 어떤까? 아직도 너무 힘든가? 3개의 숫자 중에 가장 큰 숫자를 찾는 것은 어떤가? 아니면 둘 중 큰 수를 찾는 것은?
문제를 솔루션을 알고있는 지점으로 문제를 줄여나간다. 그런 다음 문제를 조금 확장해서 솔루션을 다시 작성하고 원래의 문제로 돌아올 때까지 계속해나간다. "— V. Anton Spraul

4. 막힘(Stuck?)

당신은 아마 이렇게 질문 할지도 모르겠다. "Hey Richard ... 그 방법이 쿨(cool)하긴 한데, 하위 문제 조차 해결할 수 없다면 어떡하나요?"
먼저 심호흡을 크게 해보자. 누구나 이런 상황에 부딪힐 수 있다.
하지만 걱정은 하지말자.
가장 좋은 개발자/문제 해결사(problem-solvers)가 차이점이 있다면 버그/오류에 대해 짜증을 내기 보다는 더욱 호기심을 갖는다는 것이다.
시도해볼만한 다음과 같은 세 가지 방법이 있다:
  • 디버그: 솔루션을 단계별로 실행하여 잘못된 위치를 찾는다. 개발자들은 이것을 디버깅이라고 한다 (실제로 이게 모두 디버거가 하는 일이다).
"디버깅 기술은 당신 생각이 아닌 실제로 당신이 프로그램에 명령 내린 것을 이해하는 것이다."- Andrew Singer
  • 재평가: 한발 뒤로 물러서보자. 다른 관점에서 문제를 보자. 좀 더 일반적인 접근 방식으로 추상화 될 수 있는 것이 있는가?
"가끔 우리는 문제의 디테일(detail)을 놓치고 좀 더 일반적인 수준에서 문제를 해결할 수 있는 원칙을 간과한다. [...]
이것의 고전적인 예는 물론, 연속하는 정수 1 + 2 + 3 + ... + n의 합계를 구하는 것이다. 가우스(Gauss)가 이 문제를 해결한 간단한 공식: n(n + 1)/2 덕분에 추가적인 계산이 필요하지 않다" — C. Jordan Ball
사이드 노트(Sidenote): 재평가를 위한 또 다른 방법은 새로 시작하는 것이다. 모두 삭제하고 다시 시작하자. 진심이다. 이것이 얼마나 효과적인지를 알면 어처구니가 없을 것이다.
  • 연구: good ol’ Google. 제대로 읽었다. 당신이 가지고있는 문제가 무엇이든 누군가 이미 그것을 풀어봤을 것이다. 그 사람/솔루션을 찾자. 사실, 당신이 문제를 해결했다고 해도 검색을 해보자! (다른 사람들의 솔루션을 통해 많은 것을 배울 수 있으니까).
주의 사항: 큰 문제에 대한 해결책을 찾지는 말자. 하위 문제에 대한 해결책을 찾자. 왜? 고생하지 않으면 (조금이라도), 아무것도 배우는 게 없기 때문이다. 아무것도 배우지 못한다는 것은 시간을 낭비한 것이다.

연습(Practice)

단기간(just one week)에 좋아질 것이라고 기대하지 말자. 좋은 문제 해결사가되고 싶다면 많은 문제를 풀어봐야 한다!
연습만이 살 길이다. "이 문제는 <이곳에 개념을 삽입>하기만 하면 쉽게 해결할 수 있다"라고 알아 차라는 것은 단지 시간 문제 일뿐이다.
어떻게 연습 하냐고? 다양한 방법이 있다!
체스 퍼즐, 수학 문제, 스도쿠, 바둑, 모노폴리, 비디오 게임, 크립토키티,등등.
실제로 성공한 사람들은 "아주 작은(micro) 문제 해결"을 연습하는 습관이 있다. 예를 들어, Peter Thiel은 체스 게임을하고 Elon Musk는 비디오 게임을한다.
Byron Reeves는 "비즈니스 리더십이 3 년에서 5 년 사이에 어떻게 보이는지 알고 싶다면 온라인 게임에서 어떤 일이 일어나는지 살펴보세요. "라고 말했다.
Elon [Musk], Reid [Hoffman], Mark Zuckerberg 등 많은 사람들이 게임 제작이 회사의 성공을위한 기반이되었다고 말합니다.- Mary Meeker (2017 internet trends report)
그렇다고 비디오 게임을 하라는 것은 전혀 아니다.
비디오 게임을 하는 것을 문제를 해결 하는 것으로 생각 하라는 것이다!
그래서, 당신이 정말 해야 하는 것은 연습을 하는 것이다. 무언가 작고 사소하더라도 많은 문제(micro-problems) (이상적으로는 당신이 좋아하는 것)를 해결 해보는 것.
예를 들어, 나는 코딩 첼린지(coding challenges)를 좋아한다. 매일 적어도 한 가지 도전 과제 (보통 Coderbyte)를 풀려고 한다.
내가 말했듯이, 모든 문제는 비슷한 패턴을 가지고 있다.

결론(Conclusion)

이제 끝났다.
자, 개발자처럼 생각하는 것이 어떤 의미인지 이제 더 잘 알 것이다.
또한 문제 해결 능력이 성장에 필요한 놀라운 기술(메타 기술)임을 알게 됐다.
문제 해결 기술을 연습하기 위해 무엇을 해야 하는지도 알게 됐다는 것에 주목하자!
휴.. 정말 멋지지(cool) 않은가?
마지막으로, 많은 문제들을 만나길 바란다.
제대로 읽은게 맞다. 적어도 이제는 어떻게 문제를 해결할 수 있는지 알고 있지 않은가! (또한 문제를 해결함으로써 성장 할 수 있다는 것도.)
"한 장애물을 넘었다고 생각하면 다른 장애물이 나타납니다. 하지만 그게 인생을 흥미롭게하는 이유죠. [...]
인생은 이러한 장애물들을 뚫고 지나가는 과정입니다. 즉, 우리가 반드시 뚫고 지나야 할 일련의 선들입니다.
매번, 당신은 뭔가를 배울 것입니다.
매번, 여러분은 힘, 지혜, 그리고 관점을 만들어 나갈 것입니다.
매번, 경쟁은 조금씩 줄어들 것입니다. 결국 마지막 남는 것은 최고가 된 당신뿐일 겁니다."— Ryan Holiday (The Obstacle is the Way)
자, 이제 문제를 풀어보러 가자!
행운을 빈다 🙂
특히 C. Jordan Ball과 V. Anton Spraul에게 감사한다. 내가 소개한 좋은 충고는 모두 그들에게서 배운 것들이다.
또한 짧은 시간 내에 내가 습득 한 프로그래밍 지식은 모두 Lambda School 없이는 이뤄내지 못했을 것이다. 정말 고맙고, 강력하게 추천한다.
presentation


이 글은 번역글 입니다. 원문은 아래에서 확인 할 수 있습니다. 감사합니다.