우아한테크코스 5기 최종합격 회고 (3)

yoondgu·2022년 12월 30일
0
post-thumbnail

최종 코딩테스트

제출 PR 링크
시험 이후 리팩토링한 브랜치

예상과 달랐던 점

1. 소프트웨어는 작동해야 한다, 돌아가는 쓰레기일지라도

완성하지 못하더라도, 일부분이라도 잘 구현하고자 마음을 먹었던 나는
최종 코딩테스트 미션 메일에서 아래와 같은 내용을 읽고 아차 싶었다.

나의 짧은 개발 공부 경험 중 그 어느 때보다 극단적인 조건 속에서 이상과 현실 사이를 고민할 수 있는 시간이었다.

2. 이전 기수 미션에 비해 쉽게 느껴지는 요구사항
기능 요구사항을 분석하고, 어떻게 구현할지 클래스 구조를 정리하면서
어, 생각보다 할 만 하겠는데..? 라는 생각이 먼저 들었다.
하지만 이렇게 난이도를 조절한 이유가 있을테니
얼른 구현을 마치고 테스트 코드 작성, 리팩토링까지 해야겠다는 생각에 더 마음이 조급해졌다.
그래서 조급한 마음을 컨트롤하지 못한 탓에, 오히려 더 꼼꼼하지 못했고 공부할 때는 내가 할 거라 생각지 못한 실수까지 더 많이 하게 되었던 것 같다.

잘한 점

그럼에도 이렇게 하길 잘했다, 고 생각하는 것은
1. 구현하기 전에 주어진 ApplicationTest의 코드를 먼저 파악

  • 실제 기능이 돌아가더라도 테스트를 통과하지 않으면 0점이기 때문에, 우선은 올바른 셔플 사용법, 입출력 방식 등 테스트 통과에 문제가 없는지 확인하며 코드를 작성하고자 했다. 덕분에 테스트 코드 실행 관련 문제로 헤매는 시간은 줄일 수 있었던 것 같다.

2. view 로직은 간단하게 먼저 구현

  • 공부할 때에는 view 로직에서 상수 처리나, 포맷 관련 리팩토링을 하는 데 생각보다 많은 시간을 할애했다. 하지만 핵심 기능은 도메인 로직에 있다고 생각하여 view는 최대한 간단하게 먼저 구현해두고, 모든 구현을 완료한 뒤 리팩토링하고자 했다. (시간 상 하지 못했지만)

3. 리팩토링하기 전에 단위 테스트 코드를 작성

  • (실제로는 실수가 많은 상태였지만) 기능 구현을 완료한 시점에서, 리팩토링 하기 전에 단위 테스트 코드를 먼저 작성하고자 했다. 리팩토링 하는 과정에서 잘못된 코딩으로 인해 기능에 문제가 생기면 바로 알아차리도록 하고 싶었기 때문이다.
  • 하지만 리팩토링 함으로써 단위 테스트 코드도 모두 수정해야 하는 상황이 생겨서 일부는 모두 주석처리해버리기도 했다.. 그리고 활용할 만큼 테스트 코드를 제대로 작성하지 못했으며, 긴장한 탓에 충분히 이를 활용하지 못하고 디버깅에 어려움을 겪었다. 그래도 이런 의도와 방향성 자체는 좋은 판단이라고 생각한다.

부족한 점

이 외에도 부족한 점이 많겠지만 크리티컬했다고 생각하는 실수들이 있다.
사실 이렇게 적기에 부끄러운 실수들인데, 그런 만큼 잊지 않기 위해 적어본다.

1. 기능 요구사항에 대한 부정확한 구현

  • 추천 메뉴에 대한 같은 카테고리의 개수는 2개까지는 허용이 되었는데, 이를 미션 명세서에도 작성해놓고서는 1개의 중복도 허용하지 않도록 구현해버렸다..

2. 엉뚱한 코딩 실수

  • 최대한 단순하게 기능을 구현한 뒤, 서비스 클래스에서 직접 로직을 수행하는 내용을 줄이고 관련 정보 별로 로직을 수행하도록 하기 위한 리팩토링을 진행했다.
  • 이 과정에서 못 먹는 메뉴 또한 DislikeMenus 클래스로 관리하도록 변경했는데, 생성자에서 menus라는 변수명으로 받은 인자값을 멤버변수에 저장해야 하는데 자기 자신의 변수명을 적어버렸다.
        public DislikeMenus(List<String> menus) {
            validateMenus(menus);
            this.dislikeMenu = dislikeMenu;
        }
    평소 과제를 진행하듯이 코딩했다면 전혀 상상도 못할 실수라서 어떻게 이런 짓을 했는지 충격을 받았다..
    하지만 평소에는 시간 제한 없이 여유롭게 코딩했기 때문에, 잠깐 실수를 했더라도 이를 바로 잡을 기회가 충분했을 뿐이다.
    긴장한 것도 문제겠지만, 이렇게 menus, dislikeMenu와 같이 헷갈리는 변수명을 혼용해서 사용해 스스로 실수를 유발했다는 점에 주목해야 할 것 같다.

3. 디버깅은 차분하고 정확하게

  • 사실 2번 실수는 오류 메시지만 잘 읽어도 바로 수정할 수 있는 문제였다.
    dislikeMenu를 초기화하지 않은 멤버변수로 둔 상태에서 위와 같은 생성자 메소드가 실행됐고, 이에 따라 DislikeMenus 객체를 생성할 때 NullpointerException이 발생했기 때문이다.
  • 그런데 제출 시간이 얼마 남지 않은 시점이었고, 순간 너무 당황해 멤버변수에 new ArrayList<>()를 초기화시키는 엉뚱한 방식으로 오류만 발생하지 않게 수정해버렸다. 오류는 발생하지 않지만 전달받은 menus는 사용하지 않고 dislikeMenu 변수에는 항상 빈 리스트가 저장되어 있도록 수정해버린 것이다.
    IDE에서도 이와 같은 엉뚱한 코드에 대한 경고 메시지를 보여주었을 것 같은데, 조급한 마음에 그런 건 생각할 겨를도 없이 테스트가 잘 통과하는지만 확인했다.
    (그리고 오류를 간신히 잘 해결했다고 생각했다.....)
  • 게다가 못 먹는 메뉴 정보를 저장하는 테스트 코드를 별도로 작성했다면 긴장한 상황에서도 문제를 금방 알아차릴 수 있었을텐데 아쉽다.

4. 기계적으로 코딩하지 말기

  • 시간 단축을 위해 IDE에서 몇 가지 단축키를 설정해 빠르게 코드를 입력하도록 설정해두었다. pf -> private final, ps -> public static, ...
  • 그 중 psfpublic static final의 단축키였고,
    시험 외의 코딩에서 나는 주로 상수값들을 ErrorMessage, InputMessage와 같은 별도 클래스에 정의해서 사용했기 때문에 그 때 많이 활용하는 것이었다.
    하지만 최종 시험에서는 더 빠른 구현과 관리의 용이성 등의 이유로 클래스 내에 상수들을 정의했다. 때문에 해당 상수들에는 접근제어자로 public 대신 private을 쓰는 것이 적절했다.
    그런데 기계적으로 psf 단축키를 사용해 상수를 정의하던 습관 탓에,
    해당 클래스 내부에서만 사용하는 상수인데도 모두 접근제어자를 public으로 선언했다는 사실을 뒤늦게 발견했다..
    기능 작동에는 문제가 없는 실수였지만, 시험이 아니었다면 넘어갔을 안좋은 습관을 깨달을 수 있었다.

시험을 마친 뒤 마음가짐, 그리고 합격

시험을 마치고 나올 때는, 웃기게도 나쁘지 않았다며 자만에 빠질 뻔했다. 하지만 나의 코드에서 각종 실수를 발견하고 다른 분들의 잘 구현된 코드를 보면서 정신이 확 들었다. 역시 실전은 다르구나 생각했다. 실전이라는 리트머스지를 통해 또다시 새로운 부족한 점들을 발견할 수 있었던 것 같다.

합격이 간절했던 만큼 나의 부족함이 계속 발견되는 일은 유쾌하지 않았지만
돌이켜보면 그만큼 더 배울 수 있는 시간이었다.

그럼에도 처음 우테코에 지원할 때와 지금 나 자신을 비교하면 정말 많이 성장했다는 것, 그리고 최선을 다했다는 것만큼은 확신할 수 있다. 그래서 너무 아쉬웠지만 후회는 없었다. 이런 나의 성장과 간절함이 평가에 좋게 작용하기만을 바라며 발표일을 기다렸다.

이전에는 안하던 실수를 했다 하더라도, 억울해할 일이 아니라 이 역시 지금 나의 역량을 보여주는 지표 중 하나라고 생각했다. 그래서 만약 떨어진다면 그건 그거대로 겸허하게 받아들이자고 열심히 마음 속으로 되새겼다. 그러고 나니 차분한 마음으로 다시 지난 코드를 꺼내보고 리팩토링을 해볼 수 있었다.

다들 그러했겠지만 이렇게 하루에도 몇 번씩 기대와 해탈을 반복하다가...

너무나 감사하게도 합격 메일을 받아보게 되었다. 😇

전체 회고

자체 평가를 해보자..

사실 합격하고 너무 너무 기쁜 것과는 별개로 왜 내가 합격했을까..? 하는 의문이 상당히 많이 들었다.
그래서 생각해보다보니 합격 기준을 추측하기보다 나 스스로 무엇은 잘했고 무엇이 아쉬웠는지 정리해보고 싶어졌다. (물론 어디까지나 스스로의 생각이기 때문에 잘못된 평가일 수는 있다.)

  • 잘한 점
    • 소감문을 자세하게 작성했고, 소감문의 가독성 등 면에서도 성장하려고 노력했다.
    • 사소한 것이라도 메모하며 미션을 진행해서 소감문 작성 및 회고에 도움이 많이 되었다.
    • 학습 과정, 몰입 경험 등 기존에도 기록하는 습관을 가지고 있었다.
    • 자바의 API 중 몰랐던 것들을 적극적으로 배우고 사용해보려고 했다.
    • 커밋 메시지부터 기능 목록, 메소드 분리, 예외 처리까지 나만의 기준/규칙을 확실히 정리하려고 노력했다.
    • 최종 코딩테스트 소감문에서도 학습 과정을 드러내고 싶었다. 하지만 시험 중에는 시간을 내어 소감문을 쓰기 어려울 것이라 생각했다. 그래서 프리코스 종료 이후 학습 과정과 시험에 대한 각오 등에 대해 미리 적어둔 글을 함께 제출했다.
  • 보완할 점
    • 빠르게 문제 해결 방법을 떠올리는 역량을 키우자.
    • 머리가 아닌 손으로 개발하는 것을 경계하자. 의식적으로 하자.
    • 시간이 부족하더라도 정확하게 구현할 수 있도록 노력하자. (여러 실수를 체크할 만큼 여유롭지 않은 상황도 있음을 고려하자)
    • 마찬가지로 디버깅 또한 시간 제한 같은 외부적 요인이 있더라도 당황하지 않고 침착하게 해보자.
    • 소감문 정리를 열심히 하긴 했지만, 명확하고 좋은 글을 쓰려면 더 노력해야 할 것 같다. (시간도 오래 걸린다.)
    • 이전에 배우거나 접한 적은 있지만 기억이 흐릿하거나 잘못 이해하고 있는 개념들이 많다. 그럴 때마다 정확히 알고 넘어가도록 노력하자.
    • 몰랐던 기술이나 새로운 구현방식이라고 해서 무조건 남용하지는 말자.

본 교육 전까지의 계획

  • 충전을 위한 휴식과 운동
  • 문제 해결 역량을 위한 PS 풀이 다시 시작
  • 프리코스 및 프리코스 이전에 배운 것들 리마인드
  • 바빠지기 전에 이력서 템플릿 미리 정리해두기
  • 깃허브 정리
  • 2023년 구체적인 목표 설정

0개의 댓글