회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
개발자 취업을 준비하는 유남주 님과 함께하는 세 번째 취업 멘토링입니다. 지난 이력서 멘토링, 포트폴리오 멘토링에 이어 오늘은 ‘포트폴리오를 준비하기 위한 계획’을 세우기로 했죠. 그러나 포트폴리오를 준비하는 계획이란 무엇인지, 그 말 자체를 유남주 님이 제대로 이해하지 못해 고민하더군요. 다른 의도 없이 문장 그대로 받아들이면 되는 말인데요. 질문을 바꿔보겠습니다.
한날 “여기 있는 유남주님 포트폴리오에서 말 그대로 포트폴리오를 만들기 위해 작업한 건 무엇인가요? 미리 만든 작업물을 포트폴리오에 넣기로 선택한 것, 포트폴리오로 만들려고 작업한 것을 구분해 줄래요?”
유남주 개발자는 따로 답하지 않았습니다. 하지만 바뀐 표정을 보니 어떤 대답을 할지 알겠습니다.
한날 “알겠어요. 모두 기존에 만든 것을 포트폴리오로 골라 담은 거군요. 어떻게 보면 잘됐네요. 이참에 새로운 포트폴리오를 염두에 두고 만들어 보죠. 근데 제가 제안할 포트폴리오 제작법은 꽤 힘들고 어려워요. 애초에 포트폴리오 제작용으로 고안한 방법이 아니거든요. 좀 험난하겠지만, 한 번 고생해서 제대로 만든다는 마음이라면 해볼 만 할 거예요. 시작해 봅시다.”
먼저 정해야 할 건 이력서의 주제가 아닌, 프로젝트의 주제입니다. 주제가 있어야 포트폴리오 완성의 기준을 세울 수 있습니다. 물론 프로젝트의 주제는 이력서의 주제를 잘 받쳐줘야 합니다.
개발자가 제출하는 포트폴리오의 프로젝트 대부분은 ‘제작 그 자체’를 목표로 삼고 만들어진 것입니다. 스터디하며 만들든, 토이 프로젝트로 만들든, 프로젝트를 시작해 만들고 끝맺는 데 의의를 두다 보니 대체로 결과물도 비슷합니다. 클론 코딩류 프로젝트나 개발 교육을 받으며 만든 프로젝트죠. 이런 프로젝트는 작업자가 활용할 수 있는 역량과 시간, 자원의 한계가 명확합니다. 그래서 일반적인 기능 몇 가지를 구현한 것이 전부고 구현하는 데 작성한 코드도 특출나기 어렵습니다. 그렇다 보니 신입 개발자가 제출하는 포트폴리오는 변별력이 부족하기 일쑤입니다.
프로젝트의 주제는 작업자의 문제 정의를 따라야 합니다. 여기서 문제 정의란, 내 프로젝트의 고객이 누구이며, 그들의 어떤 문제를 풀 것인지 정의하는 것이죠. 이때 구체적으로 문제를 정의해야 합니다. 이렇게 정의한 문제일수록 그 문제에 자기의 특징이 투영됩니다. 사람마다 현상이나 상황을 대하는 관점과 반응이 다르거든요.
예를 들어 노트 앱을 만든다고 해볼게요. 이때 “노트 작성을 독려하는 앱”이라고 문제를 정의하면 이는 막연하고 모호합니다. 반면 “ADHD를 앓고 있는 사람이 노트를 더 잘 작성하도록 돕는 앱”은 어떤가요? 더 구체화할 수도 있습니다. “ADHD를 앓고 있는 사람이 하루에 한 번, 한 문장이라도 작성하도록 떠미는 노트 앱”이란 정의는 상당히 구체적으로 보입니다. 하필 ADHD를 앓고 있는 사람인 이유, 그들이 노트를 작성하도록 도우려는 연원은 문제를 정의한 사람으로부터 시작할 테고요.
포트폴리오 프로젝트 완성 기준의 또 다른 핵심 요소는 일정입니다. 기획해 보니, 또는 개발해 보니 3개월짜리인 프로젝트를 만드는 게 아닙니다. 먼저 프로젝트 기간을 정하고, 그에 맞춰 기획하는 것이 좋습니다. 기간 산정의 기준이자 목표는 ‘출시’입니다.
출시에 목표를 둔다면 6개월은 상당히 짧은 기간입니다. “출시한다”는 결정만으로도 해야 할 일이 여러 가지 생기거든요. 하지만 프로젝트를 규모가 아닌 출시 주제에 집중해서 개발한다면 상당히 긴 기간이기도 합니다. 그래서 저는 6개월을 두고 두 개에서 세 개 정도 프로젝트를 만들 것을 제안합니다.
- 프로젝트 두 개 제작: 2개월, 3개월 ; 전체 5개월
- 프로젝트 세 개 제작: 1개월, 2개월, 3개월 ; 전체 6개월
유남주 개발자 “둘의 차이는 1개월짜리 프로젝트의 유무뿐인데, 어떤 의도와 목적이 있는 건가요?”
한날 “의도와 목표는 동일해요. 오롯이 6개월을 들일 수 있는 사람이 있는가 하면, 아르바이트를 병행해야 하는 사람도 있잖아요. 그런 환경 요소를 고려한 거예요.”
유남주 개발자 “그럼 저는 프로젝트를 세 개 만들래요!”
프로젝트를 시작하고 첫 1개월은 상당히 촉박한 기간입니다. 만약 팀 프로젝트라면 소통과 협업이 필요하기 때문에 더 촉박하고요. 더욱이 출시를 목표로 잡았기 때문에 ‘배포’라는 과정도 필요합니다. 로컬 호스트에서 띄워보는 것과 전혀 다르죠. 배포 경험이 없는 경우에는 배포 환경을 구성하는 데에만 일주일을 쓰기도 합니다. ‘localhost:8810’을 ‘puddingcamp.com’로 띄워 누구나 사용할 수 있게 만들 뿐인데 생각지도 못한 변수가 몇 날 며칠을 괴롭힐 수 있습니다.
그래도 첫 프로젝트에서는 프로젝트의 주제, 즉 핵심에 집중해야 합니다. 이때는 내가 정의한 문제를 푸는 데 필요한 것만 만들어야 합니다. 기능이나 편의성이 부족해 불편하긴 하지만 고객의 문제를 해결해 주기 때문에 계속 사용하게끔 만들어야 합니다.
다시 한번 강조하지만, 반드시 출시해야 합니다. 그리고 실제 사용자, 즉 고객을 한 명이라도 더 만들기 위해 노력하세요. 한 번 들어와서 클릭 몇 번 하고 이탈하는 게 아닌 프로젝트가 해결하려는 문제에 동의하고 실제 자신의 문제가 해결되는 걸 경험하는 고객을 만드는 겁니다. 이들이 어떻게 내 제품을 사용하는지 관찰하고 개선사항에 대한 피드백을 요청하세요.
버그가 아닌 이상 리팩토링이나 기능의 변경과 추가를 하지 않습니다. 프로젝트의 주제에만 집중해야 하거든요. 사실 고객을 창출하고, 그들에게 피드백을 받고, 이에 반응하기 위해 노력하다 보면 바빠서 추가할 짬도 안 날 겁니다. 또 그래야 하고요.
첫 1개월짜리 프로젝트에서 가장 중요한 경험은 “실제로 출시하여 고객을 만나는 것”입니다.
두 번째 프로젝트는 앞서 1개월짜리 프로젝트를 그대로 사용해도 되고, 경험하고 얻은 교훈을 바탕으로 새로 시작해도 괜찮습니다. 고객을 관찰하고 그들에게 피드백을 받아 빠르게 대응하는 데 필요한 운영 환경을 구축하는 것, 이것이 이번 프로젝트의 핵심입니다.
우선 배포를 어느 주기로 할 것인지 정책을 정합니다. 이를 정하면 버그나 개선점을 처리하는 데 들어가는 시간, 구현하는 시간, 피드백을 수렴하는 시간을 배분할 때 유용합니다. 또 데이터베이스에 직접 접속해 SQL 질의문으로 데이터를 조작하다가는 사고가 날 지 모르니 데이터를 조작하는 운영자 도구가 필요할 수도 있습니다.
출시한 프로젝트가 성장하는지, 고객 특성은 어떠한지 파악하기 위해 데이터 분석 도구를 적용하고 관찰하면 더 좋습니다. 피드백을 주는 단 한 명의 고객은 A 기능을 추가해달라 하는데, 실제 지표에서는 B 기능을 개선하는 것이 더 중요하다는 맥락이 보이기도 합니다. 그렇다면 B 기능 개선의 우선순위를 높이는 결정을 할 수 있습니다. 이렇게 엔지니어링 의사 결정의 근거를 만들어 개발 공정(production)에 반영하는 거죠.
참고 글: 3달 만든 코드를 모두 엎고 배운 것
동작하는 결과물을 만드는 경험과 고객이 이용하는 결과물을 실제로 운영하는 경험 사이에는 큰 차이가 있습니다. 그 차이는 실제로 고객을 만나고 운영해야 알 수 있죠. 따라서 2개월짜리 프로젝트를 확장할 때, 결정의 기준은 아래 두 가지로 제한하는 게 좋습니다.
- 개발자 주도 확장: 운영 환경을 개선하거나 보수
- 고객 주도 확장: 고객의 피드백을 근거로 기능을 추가하거나 변경
이 두 가지 방향으로 확장하는 목적과 목표는 고객을 오래 머물게 하거나(Session length), 단골로 만들거나(Retention), 고객 수를 늘리는 것입니다. 리팩토링이나 기술적인 개선과 보완은 진행하지 않습니다.
2개월짜리 프로젝트에서 가장 중요한 경험은 “고객과 상호작용을 하며 프로젝트를 성장시키는 것”입니다.
마지막 3개월짜리 프로젝트도 마찬가지로 기존 프로젝트로 해도 되고 새로운 프로젝트를 시작해도 됩니다. 하지만 되도록 2개월짜리 프로젝트를 활용하는 게 좋습니다. 학습을 병행하며 기술적인 성장에 집중해야 하므로 프로젝트를 새로 시작하는 건 효율이 떨어지거든요.
이번 프로젝트에서는 하드 스킬을 키웁니다. 1개월, 2개월짜리 프로젝트를 개발하고 운영하면서 생긴 기술적인 고민, 의사 결정이 필요한 상황이 있을 겁니다. 몇 가지 예를 들게요.
- 코드 리팩토링
- 테스트 코드 작성
- 더 나은 자료구조나 알고리즘 적용
- 설계, 구조 개선
- 엔지니어링 측면에서 더 나은 도구 사용
- 개발 경험 환경(DX) 개선
- 성능 개선
- 사용자 경험을 개선하는 구현 탐색과 적용
- 배포와 배치 효율화
- 버전 관리 체계 수립
- 서비스 모니터링, 장애 대응, 롤백 체계 구축
- 서비스 운영 비용 최적화
3개월짜리 프로젝트를 진행하며 이를 개선해 보고, 모든 활동은 전(before)과 후(after)를 기록하여 비교 자료로 축적해 보세요.
개발자로서 메타 인지를 하려는 노력이 필요합니다. 프로젝트에 활용한 하드 스킬의 수준을 의심하고 더 나은 엔지니어링을 위한 방법을 찾아야 합니다. 이때 더 나은 엔지니어링의 근거는 자기 자신이어야 합니다. 다른 사람에게 도움을 받지 말라는 뜻이 아니에요. 누군가 A라는 도구가 문제 해결에 더 나은 방법이라고 알려준다면, 프로젝트의 상황에 맞춰 정말 그러한지, 왜 그러한지 고민해야 합니다. 또 A 도구를 적용하기 전 상태와 적용한 후 상태를 비교할 수 있는 자료를 제시할 수 있게 기록하고 보관합시다.
즉, 엔지니어링에 있어 정답을 맞히는 것이 아니라 “나는 왜 문제를 이렇게 정의했고, 그 문제를 해결하는 방법의 근거는 무엇인지” 이해해야 합니다. 팀 프로젝트에서 동료와 의견이 갈린다면 토론으로 설득해야 하며 그 과정 역시 기록할 수 있죠.
3개월짜리 프로젝트에서 가장 중요한 경험은 “개발자로서 하드 스킬과 소프트 스킬이 성장하는 것”입니다. 이 성장 과정을 나이테처럼 켜켜이 자료로 쌓는 것도 중요합니다.
이렇게 세 가지 프로젝트는 연속적이지만, 각각 별도 프로젝트로 구분하는 게 좋습니다. 각 프로젝트를 진행하면서 성장하는 모습이 대비되어 잘 드러나기도 하고 단계마다 프로젝트 주제가 다르기 때문이죠.
유남주 개발자 “그런데 멘토님, 신입이나 주니어 개발자가 결과물 위주로 포트폴리오를 만들면 작업물이 비슷하다고 하셨잖아요. 실제로도 제가 짠 코드와 다른 사람이 짠 코드가 그리 다르지 않고, 구현하는 기능도 비슷할 듯해요. 이런 작업물이 개발자로서 일하는 제 사고 체계, 그리고 성장 정도를 다른 사람과 구분될 만큼 보여줄 수 있을까요? 채용담당자가 보는 건 결국 저나 다른 주니어 개발자가 짠 고만고만한 코드잖아요.”
좋은 질문입니다. 포트폴리오를 만들며 성장했더라도, 그 성장을 제3자가 인식할 만한 작업물을 보여주지 못하면 포트폴리오가 제 역할을 못 하는 겁니다. 그래서 효과적으로 설득할 수단과 방법을 고민해야 하죠. 이때 창의성을 발휘하여 색다른 관점과 아이디어를 만들어 내면 좋습니다.
제가 제안하는 방법 중 하나는 ‘커밋(Commit) 이력’을 활용하는 겁니다. 개인 프로젝트나 토이 프로젝트를 할 때, 커밋 메시지를 대충 작성하는 사람이 많습니다. 팀 프로젝트인 경우엔 좀 낫지만, “FIX trivial changes” 수준에 머무르는 건 그리 다르지 않고요. 커밋 메시지를 포트폴리오로 활용할 생각을 미처 하지 못했기 때문입니다.
실제 코드는 작업자에 대해서는 매우 한정된 정보만을 보여줍니다. 그러니 실제 사용할 코드를 작성하는 과정을 보여주는 건 어떨까요? 커밋으로요. 아래 예시를 만들어 봤습니다.
첫 번째 커밋: 의사 코드로 먼저 작성해 본다
def two_sum(numbers, target):
# 맨 앞부터 numbers 마지막 위치까지 순회하며 위치값을 i에 담는다.
# numbers를 맨 앞부터 끝까지 순회하며 위치값을 j에 담되, i와 j는 같으면 안 된다
# if numbers[i] + numbers[j] == target
# return i, j
pass
두 번째 커밋: 실제 코드로 구현한다
def two_sum(numbers, target):
for i, val1 in enumerate(numbers):
for j, val2 in enumerate(numbers):
if i == j:
continue
if val1 + val2 == target:
return i, j
세 번째 커밋: 개선할 점이 있다면 주석으로 기록하며 코드를 작성한다
def two_sum(numbers, target):
for i, val1 in enumerate(numbers):
# 같은 숫자는 존재하지 않으므로 안쪽 for loop는 처음부터 loop를 돌 필요가 없다.
for j, val2 in enumerate(numbers[i+1:]):
if val1 + val2 == target:
return i, j
네 번째 커밋: 좀 더 나은 구현이 떠오르면, 이를 다시 의사 코드로 작성해 본다
def two_sum(numbers, target):
# 같은 숫자가 존재하지 않고, 숫자 개수가 아주 많지 않다면
# target 에서 순회한 값을 빼서 캐쉬해놓으면 순회를 한 번만 돌 수 있지 않을까?
# Python의 dict의 키 접근은 시간복잡도 O(1)이므로 매우 빠르다
for i, val1 in enumerate(numbers):
for j, val2 in enumerate(numbers[i+1:]):
if val1 + val2 == target:
return i, j
다섯 번째 커밋: 의사 코드를 실제 코드로 구현한다 (1)
def two_sum(numbers, target):
# 같은 숫자가 존재하지 않고, 숫자 개수가 아주 많지 않다면
# target 에서 순회한 값을 빼서 캐쉬해놓으면 순회를 한 번만 돌 수 있지 않을까?
# Python의 dict의 키 접근은 시간복잡도 O(1)이므로 매우 빠르다
# 키는 target 에서 순회 시 값을 뺀 값이며, 밸류는 해당 값이 있는 위치이다.
table = {}
for i, val1 in enumerate(numbers):
complement = target - val1
# target에서 val1 을 뺀 값이 테이블에 있는지 검사한다.
if complement in table:
return
# 테이블에 없다면 테이블에 값과 인덱스를 캐쉬한다.
table[val1] = i
여섯 번째 커밋: 의사 코드를 실제 코드로 구현한다 (2)
def two_sum(numbers, target):
# 같은 숫자가 존재하지 않고, 숫자 개수가 아주 많지 않다면
# target 에서 순회한 값을 빼서 캐쉬해놓으면 순회를 한 번만 돌 수 있지 않을까?
# Python의 dict의 키 접근은 시간복잡도 O(1)이므로 매우 빠르다
# 키는 target 에서 순회 시 값을 뺀 값이며, 밸류는 해당 값이 있는 위치이다.
table = {}
for i, val1 in enumerate(numbers):
complement = target - val1
# target에서 val1 을 뺀 값이 테이블에 있는지 검사한다.
if complement in table:
return i, table[complement]
# 테이블에 없다면 테이블에 값과 인덱스를 캐쉬한다.
table[val1] = i
일곱 번째 커밋: 코드를 정리한다
def two_sum(numbers, target):
table = {}
for i, val in enumerate(numbers):
complement = target - val
if complement in table:
return i, table[complement]
table[val] = i
유남주 개발자 “제가 문제를 정의하고 해결해 가는 과정을 발자국 남기듯이 커밋하는 거군요! 코드에 불필요한 주석을 남기지 말라는 조언, 그리고 커밋을 깔끔하게 남기라는 조언에 갇혀서 이렇게 해볼 생각은 못 했어요, 멘토님.”
한날 “포트폴리오용 프로젝트니까요. 커밋도 작정하고 나를 드러내는 수단으로 써야죠.”
유남주 개발자 “그런데 채용담당자가 단계별로 커밋을 따라가며 코드를 볼까요?”
한날 “단계별로 보도록 도슨트처럼 돕고 이끌어야 해요. README.md에서 어필할 부분을 설명하고, 이 부분에 관련된 커밋 단계들을 링크로 걸 수 있겠죠.”
포트폴리오를 염두에 둔 프로젝트를 할 때는 기존의 제약에서 벗어나 작정하고 포트폴리오의 정보 전달력을 높이는 데 집중하세요. 포트폴리오란 아트북을 만드는데 소설책의 형식을 따르느라 스스로를 제약하지 마세요. 자신을 설명하고 드러낼 다른 수단과 방법도 찾아보세요. 스스로를 가장 잘 표현할 방법은 아마도 자기 자신이 가장 잘 알 겁니다.
유남주 개발자 “감사합니다. 그런데 처음에는 실천할 구체적인 방법을 설명해 주셔서 구현도 쉬울 거라 생각했는데, 가만히 생각해 보니 전혀 그렇지 않겠어요. 물론 쉽다고 말하신 적은 없지만요.”
역시 눈치가 빠른 개발자입니다. 제가 여태껏 소개한 방법들은 메타 인지, 즉 자기 인식에서 시작합니다. 또 과정 내내 자기 인식을 유지해야 해서 꽤 어렵고 힘듭니다. 옆에서 누군가 자신을 관찰하며 코치해 주면 좋겠지만, 현실에서는 스스로를 자기 언어로 표현하기 보다 남이 원하는 유형에 나를 맞추고 남의 언어로 설명하느라 고군분투해야 할 때가 많습니다.
무엇보다 안타까운 점은 많은 신입, 주니어 개발자가 자신의 취약성을 외면하거나 부정한다는 점입니다. 자기 자신을 인식하려면 어떠한 가치 판단 없이 있는 그대로를 마주하고 포용해야 합니다. 다시 말하면 자기의 취약한 점도 스스로의 일부로 포용하여 자신을 온전히 인식해야 합니다. 자신의 취약성을 포용했을 때 비로소 내가 세상과 어떻게 연결되었는지, 그리고 어떻게 연결될 것인지 알게 됩니다. 그리고 그제서야 다른 사람을 설득할 수 있습니다.
참고 글: 우리의 취약성은 서로를 연결하고 강하게 만들어 줍니다
쉽지 않습니다. 그 쉽지 않은 일을 이제 갓 개발자 세계로 발을 들이는 신입에게, 발을 들인 주니어에게 요구하는 게 미안하기도 합니다. 그렇지만 어쩔 수 없는 것도 현실입니다. 기왕 하는 것, 좋은 기회라 생각하는 건 어떨까요? 이참에, 그러니까 이력서를 쓰는 김에 자기 인식에 투자해 보세요. 자기 인식은 업무 성과와 자기 발전에 도움이 되거든요.
여러분이 학습하고 성장하는 걸 돕고자 제 여정을 시작해 3달 만든 코드를 모두 엎기도 하며, 다양한 사람을 만나 이야기 나누고 나아가는 중입니다. 지금까지 이력서와 포트폴리오 작성에 관한 제 관점과 생각을 여러분에게 들려드렸습니다. 유익하고 도움이 되었기를 바랍니다.
화면 너머의 수많은 유남주 개발자님, 곧 업계에서 동료로 만나 인사 나눌 그날을 기대하며 기다리겠습니다.
한날 작가의 ‘뽑히는 개발자’ 시리즈
③ 뽑히는 개발자는 어떤 프로젝트를 하나요?
[자기 인식을 위한 참고 자료]
1. 메타인지가 문제 해결과 학습 성과를 향상시킨다는 주장도 있습니다. 이는 업무 환경에서도 적용될 수 있는 개념입니다.
2. 자기조절학습 모델이 메타인지가 목표 설정, 전략 선택, 자기 평가 등의 과정에 중요한 역할을 한다는 것을 보여줍니다.
3. 메타인지 훈련이 복잡한 문제 해결 능력을 향상시킨다는 것을 실험을 통해 입증한 결과도 있습니다.
4. 기업가 맥락에서 메타인지의 역할을 연구한 결과, 메타인지 능력이 높은 기업가들이 더 나은 의사결정을 내린다는 것을 발견했습니다.
5. 팀 수준에서의 메타인지가 팀 성과에 긍정적인 영향을 미친다는 것을 보여주었습니다.
요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.