2020년 12월 15일 화요일을 기준으로 우아한 테크코스 3기 프리코스가 종료되었다.

프리코스 마지막 테스트를 준비하는 겸 1~3주차 미션들을 처음부터 다시 진행해봤다. 미션들을 모두 새로 완성하고 나니, 프리코스 이후 내가 무엇이 달라졌는지 보이기 시작했다. 많은 것들이 바꼈지만 당장 한 눈에 보이는 달라진 점들을 기록하고 자극제로 사용할 생각이다.



👨‍💻 패키지 구조를 나누기 시작했다.

숫자 야구 게임 패키지 구조

image

가장 장족의 발전을 이룬 미션이다. 아래에서 이야기하겠지만 확장성은 전혀 고려하지 않은 클래스메서드(static)로 범벅되어 있는 전체 코드와, 패키지 구조…

무엇이 domain 이고 무엇이 controller 인지 구분도 할 줄 모르는 사람의 답답한 패키지 구조. 프리코스가 끝난 후에야 Model(domain) - View - Controller 를 조금이나마 이해하기 시작했다.


자동차 경주 게임 패키지 구조

image

Service 라는 클래스를 추가 개설하여 Collection 클래스의 부담을 줄일 줄 알게 되었다.

Cars, CarRepository 모두 CarCollection을 갖고 있는 클래스들이다. Cars 를 사용할 당시엔 CollectionCars 하나였기 때문에 부담이 많지 않아 분배할 필요가 없었다. 그러나 3주차 지하철 노선도 미션을 진행하면서 Station, Line, SectionCollection 클래스가 많아지고, Collection 끼리의 교환이 일어나기 시작할 경우 Collection 클래스가 갖는 부담이 기하급수적으로 커진다는 걸 깨닫게 되었다.

또한 부담이 줄을수록 일급컬렉션의 모습을 갖추기 쉬워진다는 큰 장점이 있다!


지하철 노선도 미션 패키지 구조

image

프리코스 이후 확장성을 고려하면서 작은 값 하나라도 객체화(Wrapping) 시키기 위해 고민을 하기 시작했다.

사실 작은 값 하나라도 Wrapping을 해야한다는 규칙은 알고 있었지만, ‘왜 해야하는가?’ 가 부족했다. 프리코스 진행 중엔 생각나면 하고, 안나면 마는 존재였다. 그러나 지하철 노선도 미션을 다시 진행하면서 구간 삽입(insert Station in Section)을 구현하는 과정에서 문뜩 든 생각이 깨달음을 주었다.

‘삽입순서(insert Order)가 미리 검증된 채로 들어오면 얼마나 깔끔할까?’

검증을 미리 완료한 채로 메서드에 전달되면 안전하고 깔끔하다. 상수 값을 객체로 만들면 생성자에서 검증이 가능하므로 합리적인 단계에서 검증이 진행되므로 이해하기도 쉽고, 믿음직스럽다. 단순한 상수가 기특한 녀석으로 변한다.

패키지를 나누는 것은 시간을 많이 잡아먹는 일이다. 그러나 나눠 두어야 훗날 다시 코드를 읽고 전체 구조를 이해하기 쉬워진다. 상호간의 예의이자, 미래의 나를 위한 투자다. 다른 사람이 아닌 나를 위한 투자인데 마다할 이유가 없다.


👨‍💻 검증을 어디서 할지 감을 잡기 시작했다.

image

image

프리코스 진행 중엔 검증을 뷰(View)에서 모두 진행한 후 값을 넘겨줬다. 입력 즉시 완벽하게 검증을 완료하고 마음 편하게 로직을 옮겨 다니는 데이터를 기대했기 때문이다. 그러나 프리코스를 진행하면서 문자열을 잘못 넘겼던 경험 덕분에 로직을 옮겨다니는 데이터가 변질 될 수 있다는 사실을 깨닫게 되었다.

이후 모든 검증을 도메인 최하단에서 진행했다. 사용자로부터 입력된 데이터가 객체로 변하는 곳이 도메인이기 때문에 검증은 무조건 도메인에서 하는게 가장 안전하고 좋다는 고정관념이 자리잡기 시작했다.

그러나 3주차 지하철 노선도 미션을 진행하면서 Collection 끼리 서로 데이터를 주고 받기 시작하자 도메인 단계 검증이 한계에 부딪히기 시작했다. 코드가 지나치게 길고 복잡해지고 있었다. 어떻게 해결해야하나 반나절을 고민하다가, 결국 고집을 꺾고 Service 쪽에 검증 메서드를 추가시켰다. 그러자 눈에 보이는 코드와 메서드 이동이 훨씬 간결해졌다.

이러한 설계 패턴, 코드 구현 규칙을 배우는 이유가 무엇인가?

그제서야 깨닫게 되었다. 프로그래밍에 정해진 답은 없다. 가독성과 생산성을 위해서라면 얼마든지 규칙을 위배할 줄 알아야한다. 프로그래밍에서 설계 패턴과 규칙은 잘 어기기 위해서 배우는 것이다.


👨‍💻 API를 활용하기 시작했다.

image

API를 활용하고 나니 불필요한 변수 선언이 필요없어 졌고, 코드 라인 수도 줄어들었다. 성능도 대단하고 뛰어난 수학자/개발자들이 만든 것이니 이미 검증되어서 어지간하면 직접 구현한 것보다 빠르다. 무엇보다 중요한 것은, 해당 API가 사용된 것 자체로 그 코드 한 줄이 무엇을 의미하는지 곧장 유추할 수 있다 (stream API를 사용하면 Collection을 다룬다는 것을 코드 전체를 읽지 않아도 인지 가능).

학부생 땐 편리하고 뛰어난 기능을 제공해주는 API를 멀리해야했다. API의 강력함과 달콤함에 빠져 직접 구현할 수 있는 능력을 기르기 어렵기 때문이다.

분명 의미가 있는 제한 행동이었다. 그러나 나는 곧 학부생에서 벗어나 가치를 생산하는 개발자가 되어야 한다. 개발자는 본인의 생산성 향상을 위해 끊임없이 API를 공부하고, 습득하고, 적용해야 한다.


👨‍💻 코드의 흐름과 가독성을 신경쓰기 시작했다.

image

굳이 말이 필요한가? 드라마틱 한 변화다.

두 메서드 모두 Line 1개와 Station 2개를 하나로 묶어 Section으로 만든 후 SectionRepository에 저장한다. 프리코스 중 작성한 saveSection 메서드의 경우 메서드 네이밍이 불명확해서 동작 출처를 알기 어렵다는 문제부터 시작된다.

“객체에 메세지를 보내라” - 프리코스 공동 피드백

프리코스 중엔 객체에 메세지를 보내라는 피드백에 갇힌 나머지 어떻게든 객체를 가져오지 않고 메세지를 보내기 위해 기를 썼었다. 그러나 앞서 말했듯, 생산성과 가독성을 위해서라면 객체에 메세지를 보내라는 규칙을 꼭 지킬 필요는 없다. 이를 깨닫고 난 후 작성한 saveByLineService 메서드의 경우 간결하고도 짧다.

객체를 가져오지 말고 객체에 메세지를 보내라는 규칙도 현재 다시 해석해보면 “객체를 반환하는 getter 메서드를 쓰지 마라.” 가 아니라 “객체의 필드멤버(내부 데이터)를 반환하는 getter 메서드를 쓰지마라.” 인 것 같다. Collection 클래스에서 객체를 반환하는 getter 메서드는 어차피 stream API를 활용하기 위해서 사용된다. 규칙을 잘 어기자.



정리하고 보니 참 많은게 남았다. 3주가 지났을 뿐인데 배움을 넘어 몸소 깨달은 내용은 3개월 혹은 그 이상이다. 프리코스 첫주차 미션을 제출 할 때도 이정도로 변화가 생길 줄은 예상 못했다. 정말 시간가는 줄 모르고 빠져들었다.

포스팅하면서 상세하게 비교하고 나니 테크코스가 더더더욱 절실해졌다.
마지막까지 부지런히 움직이자! 🏃‍♂️


댓글남기기