프로그래머스의 윈터코딩에 참여하다
프로그래머스의 윈터코딩에 참여하다
나는 평소처럼 넋놓고 학교 게시판을 보고 있던 와중, 눈길을 끄는 어떤 포스터를 보게 되었다. 스타트업 겨울 인턴십 공고 포스터였다. 역시나 작년에 봤던 것처럼 프로그래머스를 통한 인턴십 채용과 관련된 공고 포스터겠구나
하는 생각이 들었는데, 참여 기업 명단에 지그재그의 Croquis
, 코인원
이 내 눈을 이끌었다. 스타트업을 가게 된다면 이 회사에서 일해보고 싶은 생각이 들었던 회사였는데, 이 때가 아니면 언제 여기서 일해볼 수 있을까라는 생각이 들어 망설일 틈이 없이 바로 지원을 하게 되었다. 굳이 인턴이 아니더라도, 혹시나 계속해서 일하게 된다면 졸업을 앞두고 휴학을 길게 잡을 생각할 정도로 간절했다.
지원서를 쓰기 전에 앞서, 윈터코딩 일정을 자세히 알아보았는데 윈터코딩은 크게 다음과 같이 일정이 되어있는 모양이었다.
- 1차 선발 코딩테스트 : 흔히 말하는 알고리즘 문제를 빠른 시간안에 풀어야 하는 테스트
- 2차 선발 개발과제 : 요구사항을 주면, 그 요구사항에 맞게 각자 원하는 프레임워크, 각자 원하는 방식대로 구현해서 코드를 제출하는 것
- 스타트업 인터뷰 : 스타트업 돌아다니면서 인터뷰를 하는 것 같다. 개인적으로는 원하는 회사 찾아가서 인터뷰하고 싶은 생각이 들기도 하는데, 다양한 경험도 나쁘지는 않다.
- 교육 프로그램 : 12월 초부터 12일 정도 기간 잡고 빡세게 OJT 하는 모양이다. 근데 기말고사 기간이다(….)
- 인턴 근무 : 12월 중순부터 실무에 투입하는 것 같다. 사실 이게 제일 기대된다.
이렇게 부푼 기대를 가슴에 안고 이력서를 쓰게 되었는데, 음…. 정말 적을 게 없었다. 이력서 양식에는 회사에 속해서 개발자로서 얼마나/어떻게 일했는지를 적는 직무경험
을 적는 란이 있고, 개인적으로 만들어본 토이 프로젝트
를 적는 란이 있었지만, 번역을 했던 경험이라던가 학술동아리에서 활동한 경험을 적을 수 있는 란도 없었고, 오로지 개발 경험만
적어야 했다. 사실 프로젝트 엄청 옛날에 몇개 깔짝깔짝 만들어본 적이 있긴 했지만, 굳이 이런걸 써야하나?
혹은 이런걸 써도 되나?
싶은 생각이 드는 프로젝트가 많았어서 일부러 이력서에 적지 않았다. 오로지, 학력 기재사항에만 밑에 짤막하게 알고리즘 학회 창설멤버 및 학회장, 학회 위키 구축 및 운영 경험, 1년 반에 걸친 알고리즘 교육 경험
정도만 적었다. 이런걸 예상하고는 있었지만, 스스로를 돌 볼 시간이 없었다는 점에 회의감이 들기도 했다.
지금까지의 인생을 되돌아보면, 개발경험이라기보다는 커뮤니티 활동 경험만 많은 편이었다. 2016년에 제대하자마자 Elixir School 이라는 Elixir 튜토리얼 문서를 번역하면서 함수뽕이 차오르기도 했고, 번역하다보니 재밌어서 7~8월 쯤에 ROR 커뮤니티에서 주관하는 레일스 워크숍을 하면서 프로젝트 결과물을 뽑으면서도 레일스 공식 문서 번역을 리뷰하기도 했었다. 군인이라는 신분 때문에 참여하고 싶어도 참여하지 못했던 Lisp 세미나를 가게 되면서부터 시작된 인연으로 그 다음해 3월에 Clojure Bridge 워크숍에서 코치로 활동하기도 했다. 2017년도 하반기부터는 알고리즘 동아리 회장을 자진해서 맡고 학부연구생으로 들어가면서부터 외부와의 연락을 거의 단절하면서 살아왔다. 학교라는 제한된 범위에서 활동하다보니 학교 밖에서 놀던 자유롭던 시절이 그립기도 했고 답답한 1년을 보내왔다. 그렇게 1년의 공백기간을 살다가, 2018년 7월에 열린 Django Girls 워크숍에서 코치로 활동하게 되었고, Django Grils에서의 인연으로 원래 단골로 갔던 정기 꾸준 코딩 모임 PyJog
를 공동 운영하게 되면서 밖으로 나갈 준비를 하고 있는 상황이다. 이런 자잘한 TMI를 얘기하는 걸 좋아하는데, 이력서에는 그런 얘기를 적기에는 양식이 모자란 느낌이 없지 않았다. 그런데 어떻게 생각해보면, 실력으로 승부해야한다면 이런 양식을 쓰는게 오히려 맞을 수도 있긴 할 것 같다. 내가 스스로 생각하기에도 밖으로 나가기에는 그 동안 준비가 너무 소홀하기도 했기 때문이다.
경력이라 할 것도 없으니, 정말로 내가 가진 실력으로만 승부해야겠다는 생각이 들었다. 결국 이력서에는 학력사항만 기재하고, 알고리즘 학회의 학회장이었다는 사실만 짤막하게 적었다.
코딩 테스트
코딩 테스트는 중간고사가 끝난 직후에 시작되었는데, 코딩 테스트는 그냥 간단하게 언급만 하려고 한다. 코딩 테스트에는 꼭 합격하기 위해서 최근 2년 간의 기출문제를 쉬지않고 풀었다. 단순히 코딩테스트가 어느 정도 난이도인지 가늠하기 위해서였다. 문제 세트가 대부분 한 문제 빼고는 쉽게 풀 수 있는 수준이었다. 내가 풀지 못했던 그 한 문제는 다이나믹 프로그래밍 유형의 문제였기 때문에, 이번 코딩 테스트에는 DP 안 나오게 해주세요
하고 속으로 빌었다.
그리고, 10월 27일 온라인 코딩테스트를 2시간 동안 치게 되었는데, 2시간에 3문제 정도 밖에 안 주길래 속으로 띠용
하는 생각이 머릿속을 스쳤다. 처음 2문제는 BOJ의 구현
카테고리 문제만 풀 줄 알면 어느 정도 풀 수 있는 수준의 난이도였고, 마지막 문제는 이분탐색으로 슥삭할 수 있는 문제였다. 머리가 좀 빠릿빠릿하게 돌아갔으면, 40분 안에는 풀 수 있었을 것 같기도 한데, 엉뚱하게 접근한 것도 있었고 이상한 삽질을 많이 하다보니 1시간이 지나서야 겨우 올솔브했다. 난이도가 너무 낮아서 타임어택으로 떨어지는게 아닌가하고 속으로 걱정하기도 했고, 코딩 테스트 합격하더라도 최종 합격 여부는 개발 과제에서 결정나겠구나
라는 생각이 들기도 했다.
이렇게 2일 동안 이런저런 생각을 하던 사이, 10월 29일 프로그래머스에서 윈터코딩 코딩테스트 합격 통보 메일을 받았다.
개발 과제
코딩테스트 합격 통보 메일을 받으면서, 한편으로는 흐뭇한 생각이 들기도 했지만, 역시나 본 게임은 여기서 시작이었다. 메일에는 코딩테스트 합격 결과와 함께 웹/모바일/머신러닝 분야별로 과제가 주어졌고, 나는 그나마 자신이 있는 웹 분야 과제를 하기로 했다. 웹 분야의 과제는 다음과 같이 요구사항이 주어져 있었다.
- 새로운 TODO(제목 + 내용)를 작성한다
- 사용자의 선택에 의해 TODO에는 마감 기한을 넣을 수 있다.
- 우선순위를 조절할 수 있다.
- 완료 처리를 할 수 있다.
- 마감기한이 지난 TODO에 대해 알림을 노출한다.
- TODO 목록을 볼 수 있다.
- TODO 내용을 수정할 수 있다.
- TODO 항목을 삭제할 수 있다.
요구사항은 그렇게 어렵지는 않아 보였다. 전형적인 Todo 앱이었다. 어느 정도 개발에 기본기가 충분한 사람이라면 빠르게 만들 수도 있을 것이다. 나는 개발에 그렇게 능숙한 사람도 아니기 때문에, 설계는 둘째치더라도 구현을 오래할 것 같은 예감이 들었다. 주 개발스택을 Ruby/Rails에서 Python/Django로 갈아타는데서 진통을 겪고 있는 입장이기도 했고, 학회 홈페이지를 Django 기반으로 구축하겠다고 해놓고, 사용자 인증에서 매번 막히고, Redux도 제대로 익히지 못할 정도로 상당히 미숙했기 때문이었다. 교양 레포트 과제 제출 마감기한도 끼어있었는데, 나한테는 개발과제가 더 중요했기 때문에 어쩔 수 없이 교양은 드랍하고 개발과제에 몰빵하기로 했다.
그래도 이왕이면 오랜만에 실서비스를 가정하고 개발하는 것이기 때문에, 쓰고 싶은 스택대로 시도해보면서, 지금까지 해본 적도 없는 모험적인 방법으로 구현을 해보기로 했다. 어쨌거나 구현해야하는 결과물은 Todo List 어플리케이션이기 때문에, 평소에 자주 사용하고 있는 Todoist를 참고하면서 개발하기로 했다. 왠만하면 RESTful API 서버를 개발하는 쪽으로 가는게 트렌드이기 때문에, Django REST Framework를 이용하여 RESTful API 서버를 개발하는 방향으로 가면서도, 프론트엔드가 없으면 아주 아주 섭하기 때문에 프론트엔드는 잠깐잠깐 깔짝거리던 React를 쓰는 방향으로 가게 되었다.
개발과제를 하면서 알게된 자잘한 것들
내가 가진 모든 시간을 개발과제에 투자했다. 어쩌다 엄청난 우연으로 진지한 만남을 고려하게 된 사람이 있게 되긴 했지만, 양해를 구하고 오로지 개발과제에만 투자했다. 오랜만에 하는 웹개발인 만큼, 최대한 퀄리티를 높여서 개발하는 방식으로 진지하게 개발에 임했다. 프론트엔드는 내가 주력으로 하고자 하는 분야가 아니다보니 React 코드가 들어간 부분은 연구실에서 프로젝트할때 썼던 코드 일부를 재활용하긴 했지만, 백엔드에 들어가는 코드는 왠만하면 예전 코드 재탕없이 레퍼런스 문서를 참고하면서 작성했다. Todoist를 참고하면서 개발했기 때문에, UI로 얼추 흉내낼 수 있는 수준으로 코드를 짰다.
파이썬으로 실서비스로 웹개발을 해본 것은 Flask로 해본 게 처음이었고, Django를 이용해서 직접 개발에 투입해본 적은 거의 없다시피 했는데, 한번 집중해서 개발해보니 이만큼 좋은 것은 없겠다는 생각이 들기도 했다. 책보며 독학하는 것보다는 요구사항이 명확하게 주어진 상황에서 이를 구현하기 위해 발악하는 과정 자체가 정말 나에게 큰 도움이 되었다. 개발을 하게 되면서 Django에 애정을 가지는 수준까지 가게 되어버렸다. Django를 이용해서 개발하면서 어떤 점에서 애정을 가지게 되었는지 몇가지만 찝어서 얘기해보고자 한다.
Django에 내장된 DB 모듈의 기능
Django에는 모델을 다루는데 굉장히 쓸만한 여러가지 유틸리티 함수, 클래스가 내장되어 있었다. Django에는 자체적으로 ORM이 내장되어 있으며, ORM에는 데이터베이스에 있는 여러개의 레코드를 다루기 위한 QuerySet
이라는 클래스가 있다. 데이터베이스의 TodoEntry
테이블에 있는 모든 레코드를 불러오고 싶다면 TodoEntry.objects.all()
코드를 실행하여 TodoEntry
테이블의 모든 레코드의 정보를 담고있는 QuerySet
인스턴스를 얻을 수 있다.
앞에서 Todo 앱을 구현할 때, Todoist를 많이 참고했다고 언급했었다. Todoist의 홈 화면에는 기한이 지난 할 일 목록과 앞으로 처리해야할 할 일 목록을 따로 보여주는 방식으로 구현이 되어 있었는데, 이를 구현하려면 당연히 두 개의 리스트로 따로 나눠서 구현해 한다. 두 개의 리스트를 이용해서 React 같은 걸로 동적으로 렌더링해야할 것이다. 각 할일마다 마감기한이 있을 수도 있고, 마감기한이 없을 수도 있기 때문에(NULL을 허용하는 방식으로 구현할 수 있다) 다소 복잡한 로직이 들어갈 수도 있을 것이다. 마감기한은 기한이 지났는지 여부는 매시간마다 태스크를 수행하는 방식으로 구현하거나 칼럼을 따로 추가하는 방식으로 구현하기에는 너무 비효율적이라는 판단이 들었기 때문에, SQL 문을 실행하듯이 레코드의 모든 정보를 긁어오면서도 출력된 결과물의 각 레코드마다 추가적인 칼럼을 추가하는 방식으로 구현하기로 했다.
하지만, 한 가지 의문점이 있었다. 홈 화면을 불러올때 실행되는 View의 코드에서 매번 복잡하게 쿼리를 수행해야 하는가? 쿼리를 좀 더 깔끔하게 수행하기 위해서 모델 수준에서 해결할 수 있는 방법은 없는 것일까? 그렇게 Django 공식 문서를 찾아보다가 Manager
클래스라는 것을 알게 되었다. TodoEntry.objects.all()
에서 objects
는 사실 Manager
클래스의 인스턴스였고, 모델 클래스에서 다른 Manager
클래스의 인스턴스인 멤버변수를 정의하면 내가 원하는 QuerySet
을 반환하는 쪽으로 구현이 가능할 것만 같았다. objects
가 QuerySet
을 반환하는 방식을 유지하면서도, 내가 원하는 QuerySet
을 가져올 수 있도록 RemainingTodoManager
클래스를 정의했다. 기존의 쿼리셋은 완료한 작업에 대한 레코드도 같이 가져오는 반면, 내가 정의한 방식대로 가져오게 되는 쿼리셋은 완료하지 않은 작업에 대한 레코드 만을 가져오면서도 기한이 지났는지 여부를 추가적인 칼럼을 붙이는 방식으로 구현되어야 한다. 마감기한은 현재 시간을 기준으로 대소비교를 할 수도 있지만, 마감기한 칼럼에는 NULL을 허용하도록 조건을 추가했기 때문에 NULL 검사도 따로 해줄 필요가 있었다. 이런 귀찮고 번거로운 작업을 모델에서 질의를 수행하는 시점에서 해결할 수 있도록 하는게 이상적이다.
그래서, 이 문제를 어떻게 해결할 수 있을까하고 공식문서를 찾던 와중 QuerySet
클래스에 annotate
메서드가 있다는 것을 알게 되었다. annotate
의 사전적 의미만 보아도 알 수 있듯이, 주석 달다
라는 뜻이다. 즉, 각 레코드마다 조건 검사를 수행하여, 각 레코드의 조건을 보았더니 이게 어떤 유형의 레코드였더라
하는 정보를 쿼리셋 내부에서 추가적인 칼럼을 만들 수 있다. 조건검사를 어떻게 하고, 칼럼에다가 어떻게 값을 대입하는지 공식문서를 찾아보면서 Q
객체를 알게 되기도 했고, Case
, Value
, When
과 같은 괜찮은 유틸리티 함수를 알게 되었으며, 아래와 같이 코드를 짤 수 있었다.
from django.db import models
from django.db.models import Case, Value, When
from django.db.models.functions import Now
from django.utils.timezone import now
PRIORITIES = (
('1', '긴급'),
('2', '중요한 일'),
('3', '평범한 일'),
('4', '사소한 일'),
)
# 완료한 작업을 제외한 모든 Todo Entry에 대한 질의를 수행
class RemainingTodoManager(models.Manager):
def get_queryset(self):
return super(RemainingTodoManager, self) \
.get_queryset() \
.filter(completed=False) \
.annotate(outdated=Case(
# deadline 필드가 NULL이 아니면서,
# 현재 시간보다 적으면 기한이 지났다고 표시
When(deadline__isnull=False,
deadline__lte=Now(),
then=Value(True)),
default=Value(False),
output_field=models.BooleanField()
) )
# Create your models here.
class TodoEntry(models.Model):
"""
TodoEntry Model
할 일 목록의 각 엔트리가 가지는 속성을 정의한다.
* title : TodoEntry에서 제목을 의미한다.
* description : TodoEntry에서 구체적으로 어떤 일을 할 것인지를 의미한다.
* priority : TodoEntry에서 할 일의 우선순위를 의미한다.
* completed : TodoEntry에서 할 일의 완료 여부를 의미한다.
* deadline : TodoEntry에서 마감기한을 의미한다.
"""
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
completed = models.BooleanField(default=False)
priority = models.CharField(max_length=1, choices=PRIORITIES, default='3')
deadline = models.DateTimeField(null=True, default=None)
created_at = models.DateTimeField(default=now)
updated_at = models.DateTimeField(default=now)
# Query Set 정의
entries = models.Manager()
remaining = RemainingTodoManager()
DB 설정의 간편함
개발과제로 제출한 서비스는 깃헙에 커밋이 올라가자마자 CircleCI를 거쳐서, Heroku 서버로 배포되는 과정을 거친다. Heroku는 DB로 Postgres를 쓰게 되는 경우가 많은데, Django에서 쓰는 Postgres 커넥터 라이브러리인 psycopg가 계속해서 말썽을 부리는 것이다. symbol __res_maybe_init, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference
이런 메시지가 뜨는 에러였는데, 제출 마감기한 4시간을 앞두고 이 에러를 고치느라 사경을 헤메는 것 같은 생각이 들었다. 스택오버플로우를 참고하면서 가능한 온갖 트러블슈팅 방법을 다 시도해보았지만, 이건 Heroku 서버 문제이면서 Postgres에 문제가 있는거구나라는 결론을 내리게 되었다. 그래서, 배포 문제를 어떻게 해결해야하나 고민하던 와중, Heroku에서 MongoDB 애드온을 지원한다는 사실을 알게 되었다.
그래서 코드를 급하게 수정했다. 사용하는 라이브러리만 바꾸었을 뿐인데 성공적이었다.(!!!!) 아래의 코드는 환경설정에 해당되는 settings.py
파일의 소스코드 일부분인데, DB 백엔드를 Postgres에서 MongoDB로만 바꿔서 쓰겠다하고 한줄을 수정했을 뿐이었는데, 그냥 돌아갔다. 모델 부분의 코드를 일괄적으로 뜯어고칠 필요가 없었던 것이다.
DATABASES = {
'default': {
'ENGINE': 'djongo',
'NAME': os.environ['NAME'],
'HOST': os.environ['HOST'],
'USER': os.environ['USER'],
'PASSWORD': os.environ['PASSWORD'],
'PORT': os.environ['PORT']
}
}
내가 왜 이런거에 감동을 느끼게 되었는지에 대해 설명하자면, 과거의 경험을 설명하지 않을 수 없다. Rails로 개발할 당시에는 모델과 관련된 코드를 짤 때 RDBMS 기반으로 코드를 짜느냐, MongoDB 기반으로 코드를 짜느냐에 따라 코드를 짜는 방법이 달랐는데, RDBMS 기반으로 코드를 짜게 되면 모델 클래스가 ActiveRecord 클래스를 상속하는 방식으로 코드를 짜야 했고, MongoDB 기반으로 코드를 짜게 되면 Mongoid
의 Document 모듈을 모델 클래스 안에서 mixin을 해야 했다. 사용하는 DB를 바꾸게 되면, DB 때문에 모든 모델의 코드를 뜯어고쳐야 할 수도 있는 위험성이 보였다. Flask도 역시 예외는 아니었는데, Flask도 어떤 DB를 쓰느냐에 따라 SQLAlchemy 기반으로 코드를 짜야 할 수도 있고, MongoEngine 기반으로 코드를 짜야 할 수도 있다. 그런데 Django는? 그런거 없다. 그냥 DB 백엔드를 뭐로 쓰는지 바꿔주기만 하면 된다. 당연히 엄청 추상화가 잘 되어 있어서 그런 탓도 있겠지만, DB 백엔드 설정만 한 줄 바꿔줬을 뿐인데 삶의 질이 확 올라가는 것이 느껴졌다.
이런건 정말 아쉬웠다
윈터코딩 개발과제까지 하면서 한 편으로는 괜찮게 느껴진 것들이 많았지만, 다른 한 편으로는 아쉽게 느껴진 것들이 많았다. 시스템에 아쉽게 느껴진 것이라기보다는 스스로에게 아쉽게 느껴진 것들이라 할 수 있을 것이다.
첫번째로는 TDD에 너무 미숙했다는 점이다. 가산점을 얻기 위해 어떻게든 TDD를 끼얹어보려고 노력하긴 했으나, 연습장처럼 쓸 목적으로 TDD 쓰기만 하다보니 Unit Test, Integration Test를 고려하면서 TDD 코드를 제대로 작성해본 적이 거의 없었고, 심지어 RESTful API 서버를 개발하면서 TDD 코드를 작성해본 적도 없다. 언젠가는 하겠지, 언젠가는 하겠지하고 미루고 미루다보니, 막상 때가 다가오니 아무 손도 쓰지 못하게 되었다는 점에서 보면 너무 아쉽게 느껴진다.
두번째로는 사용자 인증 기능을 구현하지 못했다는 점이다. 개발 과제에서의 요구사항은 실 서비스에서 사용할 수 있는 수준의 퀄리티를 원하는 것일텐데, 사용자 인증은 Rails를 이용해서 웹서비스를 개발했을때도 라이브러리를 그냥 갖다쓰기만 해서 개발해오기만 했지 혼자 힘으로 구현을 못하는 경우가 대부분이었다. 심지어, RESTful API 서버를 개발할때는 더 막막했다. 주워들은 바로는 JWT(Json Web Token)을 이용한 사용자 인증이 있는 모양이다. 하지만, 아직까지 그럴만한 역량이 충분하지 못했다는 것이 너무 아쉬웠다.
세번째로는 나는 아직도 상태관리 라이브러리에 익숙하지 못했다는 점이다. 연구실 관련 일때문에 자진해서 React 중심으로 만져오긴 했었지만, 상태관리 라이브러리를 다루는데 그렇게 익숙하지 못했다. 연구실을 도중에 나오기 전까지도 나는 여전히 Redux가 있다는 것만 알고 있지, Redux를 제대로 쓸 줄 몰랐으며 지금도 제자리 걸음이다. 주변에서는 MobX를 쓰는게 어떠냐는 권유를 하긴 했지만, Redux도 이해를 제대로 못하고 있는데, MobX는 그 나름대로 난해하게 느껴지는 구조였기 때문에 결국 쓰지는 못하고 React + axios만 써서 프론트엔드 작업을 해왔던 것 같다. 물론, 내가 프론트엔드 중심으로 가려는건 아니지만, JWT를 이용한 사용자 인증과 관련해서도 장벽이 느껴지는 부분이었기 때문에 항상 아쉬움이 남아있다.
네번째로는 시간에 쫓겨서 작업하느라 문서화가 미비했던 점이다. 오랜만에 실서비스를 가정한 개발이라는 것에 손을 대었던 만큼, 개발을 하면서도, 배포를 하면서도 흔히 말하는 맞왜틀!!!
, 맞는데 왜 틀리지!!!
를 외치며 분노의 수정작업을 하느라 시간을 엄청 잡아먹게 되었다. 문서화를 하고 나서 코드를 짜자니, 내가 짠 코드도 믿을 수 없는 수준이라서 일단 돌아가는 코드를 짜는데만 집중했다. Django로는 실서비스를 개발한 경험이 많이 없다보니 시행착오를 엄청 많이 겪었고, 그렇게 잘 다루지는 못하는 React로 온갖 런타임에러를 뗌질하는데 대부분의 시간을 보냈다. 마감기한까지 2시간을 앞두고 돌아가는 코드를 제출하기는 했는데, 설치 방법에 대한 문서화, API에 대한 문서화, 웹 UI의 사용법에 대한 문서화를 놓고 보더라도 너무 아쉬운 것들 투성이였다. 이번 개발과제를 통해, 오랜만에 본격적인 개발을 접해보는 것이기도 하고, 이 때가 아니면 언제 온갖 새로운 방법을 다 써먹을 수 있을까 싶은 생각도 들었는데, 마감기한이 지나고나서 생각해보면, RESTful API 서버를 만들었음에도 Swagger API 문서 생성기를 올리지 못한게 너무 아쉽게 느껴졌다.
사실 이것 외에도 아쉬운 점은 정말 많지만, 가장 걱정되는건 너무 최소한으로 구현했던건 아닐까
하는 것이다. 나도 역시 내 딴에는 퀄리티를 높이려고 노력을 했다고 생각하긴 하지만, 결과물만 보면 그렇게 성의가 들어간 작품으로 보이지는 않는다. 오히려 다듬고 더 다듬어야 하는 미완성작에 가깝다. 웹개발 과제로 제출한 코드는 어차피 만들기 시작한거 구데기인 상태로 방치는 할 수 없으니 단계적으로 개선해나갈 생각이다.
마치며
윈터코딩은 어쩌면 올해의 내 운을 건 최후의 도박일지도 모른다. 학점을 챙겼을때 생길 수 있는 이점(졸업을 그나마 일찍하고 탈홍한다), 개발과제에 몰빵했을때 생길 수 있는 이점(인턴을 하게 될 확률이 높아진다)의 선택지 중에서 하나를 포기해야 했고, 나는 개발과제를 충실히 하는 쪽을 선택했다. High Risk, High Return
이라는 말이 있듯이, 졸업도 못하고 인턴도 못하게 되어서 먹고 살기 힘들어지는 최악의 가능성도 생각하지 않을 수는 없다.
레일스로 스택오버플로우 비슷한거 만들어본 적도 있었고, 게임개발동아리 임원이었을 당시 커맨드 패턴을 이용해서 쯔꾸르와 같은 플레이 방식을 구현한 적도 있었고, 라즈베리파이에 Vue.js를 올려보는 이상한 실험을 하긴 했었지만, 나 자신의 역량을 드러내는 프로젝트는 아니라는 생각이 강하게 들었다. 근데, 개발을 너무 쉬었던 탓에 토이프로젝트로 뭔가를 만들었다하면 이런거 밖에 없었다. 어떻게든 합격을 해야겠다는 심정으로, 이런걸 굳이 이력서에 써야하나 싶었던 프로젝트까지도 이력서에 한 3개 정도 적었다. 오히려 감점 요인이 될 수도 있지 않을까 싶어서 불안하기도 하다.
비록 리스크를 감수하고 개발과제에 내가 가진 모든 시간을 쏟아붓긴 했지만, 실패해도 후회는 없을 것 같다. 개발과제를 하면서 조금은 해커톤을 하는 것 같은 느낌이 들기도 했었고, 오랜만에 머리를 쓰면서 개발하는 것 같은 느낌이 들어서 좋았고, 내가 어느 부분에서 한계를 느끼게 되는지 인지하게 되었으며, 앞으로 어떤 부분을 개선해야 할 지 되돌아볼 수 있게 되었다. 개발과제를 하는 것 자체는 정말 좋은 경험이다. 비록, 멘탈이 털릴 수도 있겠지만 그만큼 개발과제에 임하면서 배우게 되는 것들도 많고, 직무를 수행하기 위해서 최소한 어떤 것이 요구되는지 알 수 있고, 모자란 점을 개선하면서 성공에 한발짝 두발짝 다가갈 수 있기 때문이다.
개발과제에 제출한 코드는 여기에 올렸으며, 추후에 포트폴리오에도 써먹을 수 있도록 단계적으로 개선하여 재활용할 계획이다.
이제 11월 8일에 있을 합격자 발표를 기다려야겠다.