2022년 10월 26일 수요일 15시, 우테코 프리코스 과정이 본격적으로 시작됐다.
이번 우테코는 코딩테스트 과정을 없애고 누구나 프리코스 과정을 밟아볼 수 있도록 바뀌었기 때문에, 지금까지의 기수보다는 경쟁률이 좀 더 올라갈 것이라 생각했다. 3 ~ 4기가 대략 1400명 정도가 백엔드 과정을 지원했는데, 이번엔 코테라는 1차 관문이 없어졌으니 아마도 2000명정도가 백엔드를 지원할 거라고 어림짐작을 했다..나같은 경우는 프리코스를 경험하고자 지원한게 아니라 우테코 본 과정에 합격해 성장하고 싶은 마음에 지원한 것이기 때문에, 더 높아지게 될 경쟁률이 신경쓰일 수밖에 없었다..
그러나 이번에 서류를 준비하는 과정에서 이전 기수 합격자분들이 포스팅한 글들을 보며 나름의 팁들을 모으던 중, 공통적으로 내가 보던 말은 "프리코스 과정을 통해서도 성장했다"라는 말이었다. 그래 어차피 경쟁률이 어떻든 상관없이 4주동안 영혼 갈아서 하면 붙을 거다. 라는 생각을 가지고, 프리코스 과정을 통해서도 뭔가 배우고 느끼는 것이 있을 것이니 거기에 초점을 맞추자. 분명히 그 시간들을 견디면 성장해있을 거니까.. 라는 생각을 하며 15시가 되길 기다렸다.
15시가 되고 문제가 공개됐는데, 심히 당황스러웠다. 이전 기수들의 1주차 미션은 야구게임만들기 같은 학교에서 나오는 과제 느낌의 미션이 나올 줄 알았는데 형식이 코딩테스트할 때 보는 알고리즘 문제들과 똑같았다. 5기부터는 미션 형식도 바뀌는건가? 싶은 찰나에 메일로 온 미션 안내문을 읽고 1주차 미션의 목적을 알 수 있었다.
개발 환경 세팅 및 Git, 사용할 언어, 앞으로의 미션은 이렇게 진행된다 등을 체험하는 일종의 튜토리얼!
음 그러면 이거는 원래 코테로 보던 거를 1주차로 옮기던 건가..라는 생각도 들었다. 그리고 각 문제별로 주어지는 요구사항들을 토대로 기능목록을 만든 다음 기능별로 커밋하라는 요청도 있었다. 프론트를 공부할 때 Udemy에서 우아한형제들에 계신 임동준 님의 강의를 들을 때 기능목록을 만든 뒤 기능들을 하나하나 구현하는 경험을 해본 적이 있어 어떻게 하란 건지 조금은 감을 잡을 수 있었다. Git자체도 원래 기능단위로 변할 때마다 commit을 한다고 공부했었다. 그러나 돌이켜보면 기능목록을 만든 후 목록에 있는 기능단위로 구현하고 커밋해본 적은 없었다. 그래서 이 미션을 통해 기능목록을 만들고 그 기능 단위로 커밋해보는 경험을 해볼 수 있고, 이를 통해 더 나은 개발자로 성장할 수 있겠다는 생각이 들었다.
이번 미션을 통해 나는 어떤 성장을 하고 싶을까란 생각을 했다. 일단 자바를 거의 처음 접하는 만큼 자바랑 친해져야겠지..라는 생각을 하고, 내가 우테코에 지원한 이유가 읽기 좋고 재사용성이 좋은 실전적인 코드를 짜는 실력을 키우고 싶어서인 만큼 그 부분을 계속해서 키워봐야겠다는 생각을 했다. 그래서 이번 1주차 미션에선 다음과 같은 목표들을 세웠다.
- 일단 무엇보다도 자바에 익숙해지기
- 미션에서 요구하는 사항들 일단 모두 구현하기
- 깃허브 컨벤션에 맞춰 커밋메시지 작성하기
- 변수/메소드 이름 최대한 그 의미 알아볼 수 있게 작성하기
- 2를 하고 리팩토링할 때 자바 컨벤션을 지키려고 노력하기
일단 1, 2가 가장 중요하다고 생각했다. 따라서 일단 문제에서 요구하는 것들이 다 돌아가도록 코드를 짠 다음, 리팩토링을 진행하는 방식으로 미션을 수행했다.
기능 목록 정의
총 7개의 문제가 제시됐는데, 문제 자체는 가벼운 난이도가 맞았다. 이걸 어떻게 구현해야 하지? 라는 과정에서 엄청난 고민이 들지는 않았다. 시간복잡도의 문제는 나중 문제고 일단 구현 자체는 그리 어려운 난이도가 아닌 문제들이라고 판단했다. 일단 문제에서 요구하는 내용들(요구사항)을 나만의 언어로 다시 정리한 다음, 머릿속에 떠오른 풀이과정을 기능 단위로 풀어서 목록으로 만들었다. 예를 들어 "포비의 왼쪽 페이지에서 나온 점수와 오른쪽 페이지에서 나온 점수 중 가장 큰 점수 구하기"는
- 왼쪽 페이지의 점수 구하기
- 오른쪽 페이지의 점수 구하기
- 그 중 가장 큰 값 구하기
이런 식으로 풀어서 목록화했다. 목록화한 내용은 별도의 문서로 만들까 고민했지만, 전체적인 관점에서 각 문제들이 엄청나게 많은 기능들을 요구하는 게 아니었기 때문에 그냥 각 문제파일들의 하단에 주석으로 달아주고 미션을 진행했다.
간만의 새로운 친구 자바와 친해지기
이제 기능 목록으로 정의한 내용들을 코드로 옮길 차례다. 문제는..
"내가 자바를 다뤄본 적이 별로 없다!"
난 프론트를 공부하다가 우테코를 지원하기 전 백엔드로 진로를 바꿨기 때문에, 지금까지 리액트, 자바스크립트 등의 프론트 관련 라이브러리와 언어만 학습해왔다. 또한 간간히 하던 알고리즘 공부는 파이썬으로 했었다. 자바 자체는 이번 학기 학교 수업을 통해 가볍게 접한 게 다였다..뭐 새로운 언어 학습에 대한 거부감이 없기는 하지만 처음 레포지토리를 클론받고 java로 작성된 파일들을 볼 땐 살짝 정신이 아득해졌다. 가만히 생각해보니, 내가 자바나 c++같은 컴파일 언어를 다뤄본지가 꽤 오래 됐다.. 알고리즘 문제같은 경우는 파이썬에서 편하게 풀곤 했는데, 첫인상이 부드러워서 맘에 들던 파이썬과는 달리 굉장히 딱딱해보이는 자바로 내가 이 문제들을 제때 할 수 있을까? 라는 생각이 들었다.
근데 뭐 지금까지 공부하면서 나름 느낀 건, 직접 부딪혀보며 배우는 게 학습에 훨씬 좋다는 것.자바를 잘 모르는 상태긴 해도 문제들을 풀면서 그때그때 모르는 부분을 찾으며 공부하자고 생각하고 미션을 수행했다. List는 뭐지..문자열 인덱싱은 어떻게 하지..자바에서 형변환은 어떻게 하지..대문자 판별은 어떻게 하지..얘도 메소드가 따로 있나..자바도 파이썬 directory비스무리한게 있나..HashMap이란 게 있구나...등등.. 하나하나 모르는게 생길 때마다 구글링을 하고, 자바의 정석 책을 뒤지며 공부해나갔다. 그리고 실시간으로 궁금한 게 생기면 직접 코드를 짜서 돌려보며 "이 땐 이렇게 되는군!"하고 공부해갔다.
리팩토링을 하며..
1번 ~ 7번까지의 문제들을 일단 다 풀긴 했다. 문제들을 푸는 과정에서는 내 생각을 자바 코드로 어떻게 옮길 수 있지?를 고민했다면, 이제는 좀 더 잘 읽히고 재사용성도 좋도록 코드를 다듬을 차례다.
메소드의 장점이 코드의 재사용이기 때문에 반복적으로 사용되는 코드들을 메소드로 묶는 것부터 시작했다. 그리고 기능 목록에서 정의했던 각 기능들을 추출해 메서드로 만드는 것과 한 메서드에서는 하나의 들여쓰기만 하도록 하는 것, 그리고 메서드 작성시 파라미터를 3개까지만 받게 하는 것, 그리고 자바 컨벤션을 최대한 지키는 것을 중점으로 리팩토링을 해나갔다.
꽤 쉬울 거라 생각했다. 왜냐하면 이미 내가 기능 목록 만들었으니까! 그거 보고 그 기능에 해당하는 코드만 쏙 뽑아서 메서드화하면 되니까!
근데 예상보다 훨씬 더 많은 시간이 걸렸다..
제일 많은 고민을 한 것 = 한 메서드에서 하나의 들여쓰기만 쓰기
예를 들어 다음과 같은 코드가 있다고 하자..
for (암튼 반복문) {
if (특정 조건문)
continue;
이하 코드들..
}
여기서 한 메서드에서 하나의 들여쓰기만 가능케하기 위해, for 문 안에서 if문으로 들어가는 부분을 메서드로 바꿔줘야 했다.
근데 문제는, if문부터를 메서드로 만들어야 하는데 그러면 continue를 그대로 쓸 수가 없다!
처음엔 if문부터를 메서드로 뽑아낸다음 if조건문을 만족하면 return;을 하면 된다고 생각했지만, 문제는 그러면 for문에서 if문 아래에 있는 "이하 코드들"에 해당하는 부분들은 언제나 실행된다. 이를 방지하기 위해선
- "이하 코드들"에 해당하는 부분도 if문과 함께 메서드 안으로 집어넣기
- 플래그 변수 만들어서 if조건문이 만족되면 플래그 변수에 변화를 준 다음, 플래그 변수에 변화가 없을 때만 "이하 코드들"이 실행되게 하기 (물론 이 경우 이하 코드들에 해당하는 부분도 메서드화해야 함)
라는 2개의 방법이 있다고 생각했다. "if문을 통해 특정 조건을 체크하는 것"과 "문제없으면 이하 코드들을 수행하는 것"은 다른 기능이라고 생각했기 때문에 2번 방법으로 하려고 했으나, for문에서 수행하고자 하는 것이 결국은 "이하 코드들"에 해당하는 부분이기 때문에 1번으로 해도 괜찮다는 생각이 들었다. 근데 그러면서도 "아 그래도 조건 체크랑 코드 수행은 다른 기능으로 봐야할 것 같은데.."라는 생각이 계속 들어 고민에 고민을 거듭했다. 결국 이런 코드들은 대부분 1번으로 하긴 했지만, 뭔가 더 좋은 방법이 있을 것 같다는 생각이 든다..
그리고 충격적이었던 것 = 자바는 call by reference가 없다
리팩토링 과정에서 가장 충격적이었던 건, 자바는 Call by reference가 안 된다는 것이었다!!
파이썬에서는 for-else라는 문법이 있어 for문이 정상적으로 수행된 경우(break안 걸리고)에 else문 안의 코드를 실행하게 함으로써 for문의 정상동작여부를 확인할 수 있다. 그러나 자바는 for-else에 해당하는 문법이 없어, 이를 구현하려면 플래그 변수를 둬서 for문에서 특정 조건을 판단하고 break를 걸 땐 그 플래그 변수의 값을 변화시켜야 한다. 그러면 for문 밖에서 플래그 변수의 값이 변했는지를 판단하면 되니까.
굳이 for-else가 아니더라도, 특정 조건을 만족하면 파라미터로 받은 변수의 값을 변화해주는 메소드를 만들고 싶었다. 아니 근데..알고보니 자바 이 친구는 call by value만 되는 언어라고 한다. 즉 내가 생각했던 방식이 안 되는 거다. 객체를 인자로 주고 객체의 속성을 바꾸는 식의 코드는 원본 객체의 속성도 바뀌긴 하지만, 그렇다고 플래그 변수로 쓸 녀석을 객체로 래핑해서 인자로 주긴 너무 번거롭고 읽기 힘들어진다고 생각했다.
뭔가 다른 방법이 있을 거야..하다가, 우선은
플래그변수 = 어떤메소드(플래그변수);
이런 식으로 코드를 작성해 리턴값을 담는 식으로 코드에 변화를 주었다. 이 방법이 최선인지는 잘 모르겠다..
전체적인 1주차 후기
앞서 말했듯, 내가 우테코에 지원한 이유는 읽기 좋고 재사용성이 좋은 실전적인 코드를 짜는 개발자가 되고 싶었기 때문이다. 평소에 원하는 기능을 구현하도록 코드를 짤 순 있어도, 읽기 좋은 코드 혹은 재사용성이 좋은 코드를 짠다고는 생각하지 않았다. 그리고 이번 1주차 미션을 통해, 내가 확실히 이 부분이 많이 부족하다는 걸 느꼈다. 내 코드가 읽기 좋고 재사용성이 좋은 코드였다면 리팩토링 과정에서 이렇게까지 많은 시간이 걸리진 않았을 거라고 생각하기 때문이다. 재사용성이 좋은 코드였다면 각 기능을 추출해서 메서드화하는게 쉽게쉽게 진행됐겠지만, 전혀 그러지 않았다. 오히려 와 이걸 어떻게 뽑아내야 하지..어떻게 바꿔야 하지..등등의 고민을 엄청 했던 것 같다.
그러면서 느끼게 된 것은, 기능 목록을 의미있는 기능 단위로 작성하는 것이 더 좋을 것 같다는 것이었다. 나름대로 기능 목록을 잘 만들었다고 생각했고 그에 맞춰 1차 구현을 완료했다고 생각했지만, 리팩토링 과정에서 기능 목록에 작성했던 각각의 기능별로 메서드화하거나 별도의 코드로 분리하는게 쉽지 않았다. 내가 기능 목록을 투머치하다 싶을 정도로 세밀하게 하려고 했던 것도 한 몫 한 것 같고, 내가 만든 기능 목록의 기능들이 서로 깔끔하게 분리된 기능들이 아니었던 것도 한 몫 한 것 같다..
또한 자바 컨벤션과 깃허브 컨벤션도 나름 잘 지키려고 노력했지만 부족함이 있음을 느꼈다. 제출 과정에서 다른 친구들이 올린 걸 보는데 와우..이게 맞다 싶을 정도로 한눈에 딱 들어오는 커밋메시지를 작성하는 친구들이 좀 보였다. 확실히 이런 부분은 이렇게 작성하는 게 좋겠군! 이란 배움을 얻을 수도 있었다..
2주차 목표
이번 1주차 때 내가 확실히 코드를 더럽게 짜는 편이구나..를 느꼈다. 그러나, 기능 목록을 좀 더 의미있는 기능 단위, 깔끔하게 분리되는 기능 단위로 작성한다면 코드도 좀 더 깔끔하게 짤 수 있고 메서드 분리도 좀 더 깔끔하게 할 수 있을 거란 생각이 든다. 따라서 이번 2주차에서는 기능 목록을 의미있는 기능 단위로 작성하여 메서드별로 깔끔하게 분리되는 코드의 작성을 목표로 할 것이다.
의미있는 기능 단위?
구체적으로 예를 들자면, 포비의 왼쪽 페이지 점수를 구하고 오른쪽 페이지 점수를 구해 둘 중 더 큰 점수를 구한다. 라는 요구사항이 있다고 하면
- 왼쪽 페이지 점수를 구한다
- 오른쪽 페이지 점수를 구한다
- 둘 중 더 큰 점수를 구한다.
라는 기능목록을 만들었다. 왼쪽 구하는 과정과 오른쪽을 구하는 과정을 분리한 것이다. 내가 원하는 것은 목록에 작성한 기능별로 그에 대응하는 메서드 또는 코드를 뽑아내는 것이다. 페이지 점수를 구하는 메서드인 getPageScore라는 메서드가 있으면, 이 기능 목록에서는 1번과 2번 모두에 getPageScore가 쓰이므로 내가 원하던 것과 맞지 않는다. 내가 원하던 건 목록에 작성한 하나의 기능이 하나의 메서드에 대응하는 거니까!! 내가 원하는 식으로 할려면 getLeftPageScore, getRightPageScore로 분리해야 하지만 이는 비효율적이다. 따라서, 기능목록 자체를
- 각 페이지의 점수를 구한다
- 구한 점수 중 더 큰 점수를 구한다
이렇게 만든다면 getPageScore가 1번에만 쓰이므로 좀 더 잘 짜여진, 의미있는 기능 단위로 만들어진 기능 목록이 된다.
...
또한, 깃허브 컨벤션과 자바 컨벤션 역시 좀 더 철저히 지키는 것을 목표로 해야 하겠다.
마지막으로..재사용성이 좋은 코드를 작성한다는 것은 객체지향적인 코드를 작성하는 것과 관련이 깊다고 생각한다. 하지만 난 객체지향적인 코드 작성에 매우 취약하다. 이 부분 역시 2주차때부터는 좀 더 객체지향적인 코드를 짜는 것을 목표로 할 것이다.
1주차 때 얻어간 것들이 많다. 더욱 더 빨아서 이번 기회를 통해 좀 더 성장해보자.
'대외활동 > 우테코 5기 프리코스' 카테고리의 다른 글
[우테코 프리코스 5기 백엔드 4주차 회고] 4주간의 여정 마무리. 나는 성장했는가? (0) | 2022.11.22 |
---|---|
[우테코 프리코스 5기 백엔드 3주차 회고] 이 고통이 성장통이었으면 좋겠다 (2) | 2022.11.17 |
[우테코 프리코스 5기 백엔드 2주차 회고] 본격적인 미션의 시작 - 테스트코드? 제가 한 번 먹어보겠습니다 (0) | 2022.11.08 |
테스트 코드 찍먹해보기(feat. Junit, Assertj) (0) | 2022.11.04 |