알고리즘 문제를 잘 풀면 뛰어난 개발자일까?

뛰어난 개발자는 문제도 잘 푼다

결론부터 말하자면, “알고리즘 문제를 잘 풀면 뛰어난 개발자일까?”의 답은 “아니오.”입니다. 하지만 뛰어난 개발자는 당연히 알고리즘 문제도 잘 풉니다. 오잉?

같은 이야기를 조금 더 자극적으로 표현해보겠습니다.

  • 문제풀이를 잘 하지 못하면 뛰어난 개발자가 될 수 없다.
  • 뛰어난 개발자 중에 문제풀이를 잘 못하는 사람은 없다.

이게 무슨 말인지에 대해서 아래 순서대로 차근차근 설명합니다.

  1. “문제풀이 실력 vs 개발자 업무 능력” 논쟁이 생기는 이유?
  2. 논쟁에 대한 글쓴이의 생각
  3. 문제풀이 능력이 뛰어난 개발자의 미덕인 이유?
  4. 올바른 알고리즘 문제풀이 공부 방법
  5. 구글의 Back-of-the-envelope calculations

글 전체 내용을 요약하는 당연한 내용의 그림으로 시작하겠습니다.

삼국지 게임을 떠올리면… 무력이냐 지력이냐? 둘 다 높은게 최고지!

1. “문제풀이 실력 vs 개발자 업무 능력” 논쟁의 원인

논쟁의 원인은, 의심의 여지없이 국내외 IT 기업들의 변화 때문입니다.

IT 기업들에게 인재 채용은 언제나 아주 중요하고 어려운 문제입니다. 그런데 구글, 페이스북 등의 해외 유명 기업들이 IT 인재 채용의 기준으로 Problem Solving(PS) 즉, 알고리즘 문제풀이 실력을 중요한 기준으로 세우기 시작하면서 국내 기업들도 영향을 받게 되었습니다. 카카오, 네이버같은 대기업은 물론 다른 IT 기업들도 “코딩 테스트”라는 이름으로 알고리즘 문제풀이를 채용 프로세스에 포함하고 있습니다. 심지어 삼성이나 LG같은 제조업 중심의 대기업 그룹도 IT 관련 부서에는 코딩 테스트를 도입하고 있죠.

IT 기업들은 여기서 끝내지 않고, 이미 재직중인 직원들에게도 연봉 상승/평가 반영 등을 내세우며 사내 코딩 테스트를 도입하기 시작합니다. 그러면 직원들의 반응은 두 가지로 갈리죠. “좋은 기회다!” 혹은, “일만 잘하면 됐지, 내가 왜 시험을 봐?”. 대부분의 직원들은 후자의 반응이겠죠. ^^;

IT 기업들의 이런 움직임 때문에 직장을 구하는 취업준비생들에게도, 직장을 다니고 있는 현직 개발자들에게도 “알고리즘 문제풀이 실력이 실제로 업무 능력이 뛰어난 인재를 가려내는데 효과가 있느냐?”라는 주제는 뜨거운 논쟁거리가 되었습니다.

2. 논쟁에 대한 글쓴이의 생각

이런 논쟁에 대해 인재 채용의 관점, 직원 평가의 관점, 그리고 개인 능력과 자기계발의 관점 총 세가지 관점에서 바라본 제 생각을 적어보겠습니다.

저는 인재 채용의 관점에서는 위 질문에 대해 거침없이 “YES” 라고 주장합니다. 알고리즘 문제풀이는 개발자의 능력을 평가하는 여러 가지 방법들 중에서도, 가장 간단하고 객관적인 방법이기 때문입니다.

예를 들면 개발자의 능력을 평가하는 가장 확실한 방법은 같이 프로젝트를 진행하면서 일해보는 것인데, 수 많은 지원자들 모두에게 이런 기회를 주는 것은 현실적이지 못하죠. 하지만 알고리즘 문제풀이는 지원자가 수천 명이든 수만 명이든 훌륭한 문제들을 골라서 동일하게 제공하는 것 만으로 공정한 평가가 가능합니다. 그리고 이 평가 결과는 기업 입장에서 “어느 정도 괜찮은 인재”를 필터링하는데 편리하죠.

반면 현직 개발자들의 업무 능력을 판단한다는 관점에서는 “글쎄요…” 라고 이야기하고 싶습니다. 입사 지원자들과 비교했을 때 현직 개발자들의 업무 능력은 오랜 기간 여러 가지 방법을 사용해 다방면으로 평가가 가능하기 때문입니다. 알고리즘 문제풀이를 통한 평가는 언급했듯이 간단하고 객관적이기 때문에, 이게 오히려 기업이 뛰어난 인재를 놓치는 원인을 제공할 수도 있습니다. 업무 능력도 출중하고, 커뮤니케이션 능력도 뛰어난 개발자가 단지 문제풀이 점수가 낮다는 이유로 진급이 누락되거나 안좋은 평가를 받게 되는 것은 말도 안되는 일이죠.

그렇다면 마지막으로 개인 능력, 자기계발의 관점에서는 어떨까요? 묻지도 따지지도 않고 “YES” 입니다. 저는 알고리즘 문제풀이 능력이 뛰어난 개발자의 미덕이라고 생각합니다. 또, 올바른 방식의 알고리즘 문제풀이 공부는 평범한 개발자가 뛰어난 개발자처럼 사고할 수 있도록 만들어주는 가장 빠르고 쉬운 방법이라고 생각합니다.

3. 문제풀이 능력이 뛰어난 개발자의 미덕인 이유?

뛰어난 개발자가 되기 위해 필요한 능력은 크게 두 줄기가 있다고 생각합니다. 한 가지는 단순하면서도 실용적이고, 또 아름다운 구조를 만들어내는 건축학적인 능력입니다. 또 다른 한 가지는 주어진 문제를 빠르고 효율적으로 풀어내는 수학적인 능력입니다.

건축학적인 능력에는 절차지향, 객체지향, 함수형 프로그래밍과 같은 개발방법론에 대한 이해나 디자인 패턴, TDD, DDD, 코드 가독성 추구 등과 같은 주제들이 연관되어 있겠죠.

그리고 수학적인 능력은 실제 수학 지식, 문제 해결에 접근하는 방법, 시간복잡도, 공간복잡도에 대한 이해, 컴퓨터와 운영체제 구조에 대한 이해같은 주제들이 연관되어 있을 것입니다.

간단하고 아름다운 코드를 작성할 줄 알지만, 어렵고 복잡한 문제를 풀어내지 못하는 개발자와, 빛처럼 빠르고 효율적이지만 이해하기도 어렵고 유지보수하기 힘든 코드를 만들어내는 개발자가 있다면 뛰어난 개발자라고 부르기는 어렵겠죠. 두 가지 능력을 균형있게 갖춘 사람이라야 뛰어난 개발자라고 인정받을 수 있을 겁니다.

이 때 알고리즘 문제풀이 실력이 개발자의 수학적 능력을 어느정도 대변하는 수단이 될 수 있습니다. 또, 알고리즘 문제풀이에 대해 공부하고 연습하는 것으로 수학적 능력을 기르고 뛰어난 개발자들이 사고하는 방식에 대한 통찰을 얻을 수 있습니다.

4. 올바른 알고리즘 문제풀이 공부 방법

그런데 많은 개발자들이 알고리즘 문제풀이 공부에 대해 오해하는 것이 있습니다. “알고리즘 문제풀이를 공부하는 것은 수학 공식을 외우듯 여러 가지 풀이법을 달달 외우는 것이다. 그리고 그렇게 달달 외우다보면 어떤 문제든 공식에 숫자를 넣듯이 간단히 풀어낼 수 있다.” 라는 것입니다.

절대 그렇지 않습니다.

아마도 알고리즘 문제풀이와 관련된 이야기를 할 때 사용하는 백트래킹, DFS, BFS, DP 등의 기술 이름같은 용어들과 다익스트라, 크루스칼, 아호-코라식 등 학자들의 이름을 딴 수학공식같은 명칭들이 오해를 불러일으키는 듯 합니다.

물론 실제로도 위에서 언급된 기법들을 공식처럼 외우는 공부법을 사용하는 사람들이 많고, 암기를 통해서도 문제풀이 성적을 올리거나 코딩 테스트에 통과하는 것이 충분히 가능합니다. 그러나 이런 방법은 말그대로 문제를 풀기위한 방법이지, 뛰어난 개발자가 되기 위한 방법이 아니라고 생각합니다.

뛰어난 개발자가 되기 위해서는 문제를 푸는 것에 집중하기보다는 문제 해결에 접근하는 방식과, 효율적인 사고 체계를 세우는 것에 집중해야 한다고 생각합니다.

예를 들어 설명해보겠습니다.

알고리즘 공부를 시작할 때 흔히 접하는 주제는 정렬 문제입니다. 버블 정렬, 선택 정렬, 삽입 정렬, 병합 정렬, 퀵 정렬, 힙 정렬 등 많은 종류의 정렬 알고리즘을 접하게 됩니다. 대부분의 사람들은 각 정렬 알고리즘 코드를 한 번씩 따라서 작성해보고, 어차피 병합 정렬이나 퀵 정렬이 가장 빠르고 코딩 테스트에서는 라이브러리에서 제공하는 정렬 함수를 사용하면 된다고 하니 그래프나 DP 문제로 넘어가게 됩니다.

하지만 정렬 문제에는 더 많은 정보와 배울거리가 숨어있습니다.

  • 분할 정복을 이용해 O(nlgn) 알고리즘을 유도해내는 과정
  • 데이터가 적을 때에는 왜 퀵 정렬이나 병합 정렬 대신에 삽입 정렬을 사용하는지
  • 시간복잡도상 힙 정렬이 퀵 정렬보다 빠른데, 왜 런타임에서는 퀵 정렬이 더 빠른지
  • 왜 퀵 정렬은 불안정 정렬, 병합 정렬은 안정 정렬이 되는지
  • 다른 알고리즘들과 다르게 병합 정렬이 기피되는 상황은 언제인지

이런 정보들을 통해 정렬 문제 뿐만 아니라, 실무에서 데이터들을 다룰 때에도 도움이 될만한 통찰을 얻을 수 있습니다.

또 알고리즘 문제풀이에 뛰어난 사람들이 가진 공통적인 사고체계를 배우는 것도 실무의 여러 문제를 접근하는 데 도움이 됩니다. 아래와 같은 것들입니다.

  • 시간 복잡도에 따른 1초당 처리 데이터 근사치
    • O(1), O(logN) 아주 많이
    • O(N) 1억 개
    • O(NlogN) 1천만 개
    • O(N^2) 1만 개
    • O(N^3) 1백 개
    • O(2^N) 20~30개
  • 2중 반복문은 O(N^2), 3중 반복문은 O(N^3)
  • 문제를 나눠 분할 정복으로 접근하면 대부분 O(NlogN)
  • 데이터를 순서대로 접근해 찾으면 O(N)
  • 공간을 희생하는 대신 더 빠르게 찾고싶다면 트리, 해시 테이블
  • 문제는 단순화하고, 해결은 무식한 방법으로 시작해 좁혀가기

그리고 여러 알고리즘을 외우고만 있는 것은 의미가 없겠지만, 알고리즘들의 탄생 배경과 문제를 해결하는 방식에 대해 알고 있는 것은 당연히 도움이 됩니다.

  • 문자열을 찾을 때에는 상황에 따라 KMP, 아호-코라식 등
  • 데이터의 빠른 검색이 중요하면 이분 탐색, B-Tree 등
  • 연결성을 가지는 데이터라면 그래프로 모델링해 관련 알고리즘 활용

“문제 풀이법을 달달 외우고 있는게 업무에 무슨 도움이 돼?” 라는 말은 수긍할 만 하지만, “저런 걸 공부해봤자 업무에 무슨 도움이 돼?” 라고 말하면 반박이 가능할 만한 내용들이죠?

따지자면 문제 풀이법을 달달 외우는 것 마저도 위의 내용에 따르면 간접적으로 도움이 되기 때문에, 어쨌거나 아무 것도 하지 않는 것 보다는 훨씬 낫겠죠.

5. 구글의 Back-of-the-envelope calculations

알고리즘 문제풀이와 직접적인 연관이 있는 것은 아니지만, 구글에서도 Back-of-the-envelope calculations 이라는 일종의 계산법, 사고 체계를 소개하고 있습니다. 정확히는 구글의 위대한 개발자인 Jeff Dean 이 스탠포드 대학교 초청 강의에서 소개했다고 합니다.

간단히 설명하면, mutex 락/언락은 100 ns. 1MB를 데이터를 메모리에서 읽으면 250,000 ns. 네트워크에서 읽으면 10,000,000 ns. 이런 방식으로 어떤 동작에 소요되는 시간 근사치들을 알아두고 실제 시스템을 설계하기 전에 간단히 계산을 해보는 것입니다. 근사치 계산을 통해 어떤 시스템 설계가 요구사항에 적절할 지 판단하는 것이죠.

자세한 내용은 저의 다른 포스트에서 확인해보실 수 있습니다.

마치며

전달을 위해 다소 강한 어조를 사용했는데, 강조하고 싶은게 어떤 것이였는지 잘 전달되었으면 좋겠습니다. 마치 본인이 알고리즘 문제풀이의 대가이며, 뛰어난 개발자로 이름난 사람이여서 세상이 어떻게 돌아가는지 다 이해하고 있는 양 적었지만 아쉽게도 사실은 그렇지 않습니다. ^^; 저도 평범한 개발자이고 뛰어난 개발자를 목표로 개발과 관련된 여러 가지 이론과 견해들을 접하며 공부해나가고 있습니다.

어떤 키워드나 주제에 대해 존재라도 알고 있는것과 전혀 모르고 살아가는 것에는 정말 큰 차이가 있는 것 같다고 느낍니다. 끊임없이 읽고 배워서 뛰어난 개발자가 될 수 있도록 노력해야겠습니다.

긴 글 읽어주셔서 감사합니다!

4.5 2 votes
Article Rating
구독
Notify of
guest
3 Comments
오래된 순
최근 순 좋아요 순
Inline Feedbacks
View all comments
임보탬

감명깊게 읽었습니다.
감사합니다!

dsd

도움이 많이 되는 글이네요 ps 공부를 하면서도 나중에 개발할때 어디에 도움이 되는건가 하는 궁금증이 많았었는데 도움이 됐습니다!