Search
Duplicate

2021년 11월 2주차 회고록

오랜만에 올리는 이번 주에 꽂혀 계속 듣는 노래입니다.
딱히 요즘 랩이나 힙합에 빠진건 아니지만, 우연이 보게 된 마미손이 수장으로 있는 뷰티플 노이즈 레이블에 소속되어 있는 Zior Park이라는 뮤지션인데, 독특한 음색에 작사,작곡, 영상제작까지 직접 다 한다고 해서 더 빠져있네요. 출근, 퇴근, 업무 모든시간에 듣고 있습니다.
음색이 독특하기에 호불호가 있을 수 있는데, 그 만큼 취향에 맞는 사람은 더욱이 빠질 수 밖에 없는 것 같습니다.

1. 공부의 도 하지 않은 일주일

이번 주 나는 평일이고 주말이고 따로 인강을 보거나 책을 보거나 포스팅을 하지 않았다.
오로지 회사 업무와 코드 리뷰만 하면서 시간을 보낸 것 같다.
지난 주 회고에서 강의도 보고 공부도 하겠다는 다짐을 전혀 지키지 못했다.
근데, 생각보다 현재 스트레스가 있지는 않다. 어째서 그럴까?

1.1 NextStep - Code Review

이제 리뷰어 활동을 시작한지 2주라는 시간이 흘렀다.
첫 시작할 당시만해도, 내가 리뷰할게 없으면 어쩌지, 수강생이 리뷰어보다 잘하면 어쩌지, 내가 모르는걸 질문하면 어쩌지, 등등 많은 고민이 있었다. 이런 고민은 원체 걱정이 많은 내게는 늘상 있는 평범한 고민이였고, 조심스럽게 시작을 하고 2주가 지난 뒤 심적으로 많이 안정을 가지게 되었다.
내가 리뷰할 꺼리가 많다는 점과 도움을 많이 줄 수 있다는 점에서 늘 약간 로망처럼 생각하던 선한 영향력을 끼칠 수 있다는 점에서 만족감을 가질 수 있었다.
또한, 개인적으로도 내가 알고 있던 지식들을 말로 풀고 수강생마다 수준에 맞춰서 리뷰를 작성하면서 혹은, DM으로 온 질문에 대해 토론을 하면서, 내가 아는걸 알려주기만 하는게 아니라 수강생분들의 관점과 생각들을 들으면서 서로 발전해나갈 수 있는 시간이였다.
그 동안 생각만 하던, 2회차 복습을 의도치 않게 리뷰활동을 하면서 하게 된 것이다.
공부하고 그냥 넘어갔던 많은 이론들, 디자인 패턴, 이펙티브 자바의 여러 아이템들, 객체지향의 SOLID, 블랙박스 화이트박스 테스트의 여러가지 기법들에 대해 내가 정리하고 포스팅한 내용들을 공유하고 나도 설명하기위해 다시 리마인드하면서 나도 공부가 되었고, 토론을 하면서 그냥 아는 지식을 나열하는게 아니라 상대방을 설득하려고 하고 수강생의 새로운 시점에서 이슈를 제공하면 나는 그 부분들을 놓치고있거나 새로운 시각을 알 수 있어서 확실히 도움이 많이 되었다.
또한, 나보다 잘하고 못하고를 떠나서 주니어 분들의 코드를 리뷰하기 위해 수십분에서 수시간을 동일한 요구사항에 각기 다른 구현 방식을 보고 코드를 분석하다보니 자연스럽게 코드를 이해하는 시야가 넓어지는 기회이기도 했다.
뭔가 새로운 공부를 하거나 책상에 앉아서 책을 보거나 암기를 하면서 공부를 한 것은 아니지만, 이런 활동들이 많은 도움이 되었다.
또한, 내가 제작년 이 과정을 진행할 때는 조급함은 크고 자신감은 없기에 매일 매일 무조건 PR을 제출하려 했고, 모르는게 생기면 무조건 바로 DM을 보내고 리뷰가 24시간내로 안오면 바로 DM으로 독촉도하면서 진행을 했던게 그 당시에는 다 이정도는 할꺼라 생각하고 별 생각을 안했었는데, 내가 리뷰어가 되 보니 내가 정말 열심히 했다는 평가를 할 수 있게되면서 뭔가 조급함이 조금 가라앉는 느낌이 오기에 지난 한 주간 공부를 따로 하지 않았음에도 덜 불안할 수 있었던게 아닐까? 추측한다.

1.2 충실한 회사 업무(?)

좋게 생각해야할지 나쁘게 생각해야할지 모르겠지만, 9월 말 퇴사를 얘기하고 어느덧 한달 반정도가 지났다. 이상하게도 퇴사얘기가 나오고 내가 할 업무가 정말 많아졌는데, 한달 반동안 내가 회사에서 맡은 업무를 대충 나열해도 다음과 같다.
1.
노인복지 화상통화 웹앱 유지보수 및 고객응대
2.
노인복지 화상통화 솔루션 인수인계
3.
은행관련 Server API 추가기능 구현 및 SMTP 인증 시스템이 Keycloak으로 변경되는것에 따른 새로운 모듈 개발
4.
고객사 제품 홍보(CES) 홈페이지 개발 투입
5.
(오늘 추가) 크롤러로 해외 사이트 Carousel 에서 제품 정보를 찾는 표준 라이브러리 개발 기술검토
6.
(오늘 추가) Spring REST Docs + asciidoctor 가이드 문서 제작 및 교육
오히려 나보다 다른 직원들이 더 어이없어 하는 상황인데, 어찌되었든 내일 모레 유지보수로 출장까지 가야하니 참 골때리는 상황이 아니라 할 수 없다.
근데 이게 왜 내게 스트레스를 주는게 아니라 스트레스를 주지 않도록 하는걸까?
우선, 해당 업무 대부분은 클리어를 한 상황이다. 응대도 대부분 다 끝내놨고 인수인계도 최대한 문서까지 다 전달한 상황이고, 은행관련 추가개발역시 개발은 끝내놨고, README로 문서화도 거의 다 마춰놓은 상태이다. 이렇게 결국 대부분 과제를 다 일정보다 더 빠르게 끝내버렸고, 이런 상황이 될수록, 퇴사를 하는것에 대한 부담감등등이 사라지고, 내가 그래도 마지막까지 도와줄 것은 다 도와주고 떠날 수 있다는 부분에서 이유모를 죄책감과 여러 복잡한 감정들이 정리되는 시간이기도 했기 때문인 것 같다.

1.3 충분한 휴식과 수면

백신 2차를 맞고 너무 안좋아진 몸상태를 걱정하면서, 먹는것도 그냥 먹고싶은대로 먹고(야식은 빼고), 잠도 충분히 자거나 계속 휴식을 취하니까, 컨디션도 이제 완전히 회복이 된 것 같다.
그리고 이게 결정적인 것 같다. 원체 체력이 약한상태에서 공부한다 뭐한다 하면서 새벽1~3시에 잠들었는데, 한 주간 대부분 11시~12시에 잠들고 식사도 충분하게 하니까, 컨디션이 회복되고 건강한 신체에 건강한 정신이 깃든 것 같다.

그래서...

비록 기존에 하던대로 공부를 하지는 못 했지만, 무가치한 시간은 아니였던 것 같다.
조급함을 조금 덜어냈다는 것 만으로도, 충분히 가치있었던 한 주였다.
그게..인생이니까 (끄덕)

2. 객체지향 패러다임에 대한 고민

개발자로써 발을 내딛은 개발자라면 1년차부터 수년차까지 맨날 접하고 듣고 말하는게 바로 이 객체지향 즉 OOP(Object-Oriented Programming)이다.
위키의 내용만 가져다 보면 이렇게 설명하고 있다.
객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.
즉, 비슷한 속성들을 하나의 개념으로 묶어서 객체로써 정의하고 이렇게 묶여진 군집간에 메세지만을 전달하도록 한다는 것인데, 나를 포함한 많은 주니어 개발자들은 이러한 객체지향 패러다임을 정말 제대로 이해하고 있을까?
얼마전까지의 나는 이제 객체지향을 좀 알고있다고 생각을 했었다.
20대때부터 열심히했건 안했건 꾸준히 했고 어느덧 30대가 되었는데, 이쯤되면 어느정도 난 아는편 아닐까? 생각을 했었다.(오만했다.)
그런데 참 하면 할수록 쉽지않다는걸 계속 느낀다. 객체간에 상태가 아닌 메세지를 보내야 한다지만, 무의식중에 사용하는 getter와 메세지가 아닌 상태를 보내고 있는 코드를 보게된다.
리뷰를 위해 내가 예전에 수강생일때 만들었던 프로젝트를 보니 그 당시에는 최선이였다고 생각했던게 얼마나 어리숙한 코드인지만 알게 되었다.
수강생분들의 코드를 보면 그래도 몇몇분들은 객체자체는 잘 만든다. 하지만 이런 분들의 코드 역시
getter를 통해 상태를 꺼내 이를 연산에 사용하는 경우들이 있다.
가령 예를들어 다음과 같은 자동차(Car)객체가 있다고 하자.
public class Car { private final Name name; private final Position position; //... getter, setter, etc... public Position getPosition() { return position; } } public class RacingService { //... public GameResult race(Cars cars, Round round) { while(round.hasNext(){ cars.notify(Car::move); } Position maxPosition = cars.getMaxPosition(); List<Car> winners = cars.filter(car -> car.getPosition().getPosition() == maxPosition.getPosition()) .collect(toList()); return GameResult.from(winners); } }
Java
복사
이 코드를 보면 자동차 경주를 진행하고 우승자를 조회해서 반환하는 비즈니스 로직이다.
내부 구현부만 문제없으면 잘 동작할 것이다. 하지만, 이는 객체지향적으로 문제가 있는 코드이다.
어디가 문제일까? 바로 이 코드이다.
car.getPosition().getPosition() == maxPosition.getPosition()
자동차 객체의 속성 중 위치정보를 포장하는 일급 객체인 Position을 getter를 통해 가져온 뒤
이 일급 객체의 내부 원시값을 조회해서 이를 최대 이동거리와 비교하고 있다.
위에서 언급했던 객체에 메세지를 보내 결과를 반환받는다. 라는 말과 전혀 일치하지 않는 행위이다.
Service Layer에서 메세지를 전달하는게 아닌 상태를 가져와서 직접 비교하고 있다.
정말 많은 분들이 이런식으로 상태를 가져와서 직접 로직을 수행하는데 사용하고 있다.
(물론, 나도 꽤 자주 이런 실수를 저지른다. )
이를 메세지를 보내는 방식으로 바꾸면 어떻게 될까? 이렇게 표현해볼 수 있지 않을까?
public class Car { private final Name name; private final Position position; //... getter, setter, etc... public boolean equalPosition(Position position) { //Position Wrapper class에 equals and hashCode가 재정의 되있다고 가정한다. return this.position.equals(position); } } public class RacingService { //... public GameResult race(Cars cars, Round round) { while(round.hasNext(){ cars.notify(Car::move); } Position maxPosition = cars.getMaxPosition(); List<Car> winners = cars.filter(car -> car.equalPosition(maxPosition)) .collect(toList()); return GameResult.from(winners); } }
Java
복사
이제 자동차의 위치가 내가 원하는 위치와 동일한지 비교하는 책임은 위치라는 객체 그 자체가 책임질 일이고 나머지는 그 메세지를 전달하고 응답결과만 가지고 로직을 수행하면 된다.
이처럼 다 보고나면, 별거 아닌 것 같지만 나를 포함해서 많은 주니어 개발자가 실수하는 부분이기도 하다. 이렇게 말 나온김에 생각외로 많은 주니어분들이 고민하는 하나의 이슈를 더 얘기해보자.

getter를 사용하지 않으면 진행을 할 수 없는데 어떻게 하죠?

결론부터 얘기하자면 getter를 지양하라는 것이지 금지하라는 것이 아니다.
단순 데이터 전달을 목적으로 하는 getter의 사용은 사용해도 괜찮다는게 내 의견이다.
그냥 책에서 혹은 미션에서 setter, getter를 지양하세요! 라고 말했다고 쓰지말아야 하는게아니라 어째서 쓰지 말아야 하는지 생각해보자.
회고록이기에 너무 깊게 들어가긴 그렇지만, setter는 더 말할것도 없이 객체의 불변성을 깨트리고 내가 의도하지 않은 Layer의 의도하지 않은 메소드에서 해당 객체의 내용을 쉽게 바꿀수 있기 때문에 프로젝트 자체에 대한 신뢰도가 떨어질 수 밖에 없다.
그럼 getter는 어째서 지양해야 하는 것일까?
setter/getter는 객체 내부의 필드에 접근할 수 있게 해주는 접근자(accessor)라고도 불린다.
이런 접근자가 존재하면 기껏 private 필드로 만들었음에도 접근이 가능하게 되면서 public 필드를 만든것과 동일한 문제가 생기기 때문에 위험하다.
외부에서 내부의 구현으로 접근할 수 있게 해주는 문제가 가장 큰 문제다. 그렇기에 setter도 getter도 없을수록 좋다. 하지만 setter와 다르게 getter는 아예 금지하라는 말은 하지 않는다. 연산에 사용할 목적이 없고, 단순한 계층간 데이터 전달 목적으로는 사용할 수 있다고 생각한다.
그리고 몇 가지 생각을 더 꺼내자면, 이런 접근자 메서드를 없애고자 하는 이유는 결국 객체의 캡슐화를 유지하고 내부 구현을 노출시키지 않으려함과, 불변성을 확보하기 위함이다.
내가 만든 객체의 필드값이 일급 객체로 포장되어 있고, 또한 불변성을 가지도록 했다면, getter를 사용해서 필드를 꺼낸다 하여 객체의 불변성이 사라지지 않을 것이다.
즉, 객체 내부의 조작할 수 있는 방법은 오로지 공개된 API를 통해서만 되야지 접근자를 통해 조작이 되서는 안된다. 없을수록 좋지만 있다고하여 그걸 사용해서 내부 값을 위/변조 할 수 있다면 애초에 좋은 설계가 아닌 것이다.

3. Next Plan

아내 가게의 바나나 귀신..!
1.
코드리뷰를 하며 얻은 인사이트 및 키워드를 주제로 포스팅 및 학습
: 이건 방급 회고를 쓰며 급하게 떠오른 생각인데, 객체지향에 대해 작성을 하다보니 나도 생각이 많이 정리되는게 효과가 급진적인걸 보니 이걸 하나의 컨텐츠로 포스팅을 해보면 좋을 것 가탇.
2.
미리 다음 미션들 구현해보기
: 사다리타기, 볼링 등 구현한지 너무 오래되어 기억이 가물가물하기에, 리마인드삼아 구현을 해 볼 필요를 느꼈다. 좀 더 양질의 리뷰를 하기위해 복습을 주중에 진행해봐야겠다.
3.
알고리즘 강의 사놓은거 보기
: 요즘 개인공부안하면서 유일하게 걱정인게 바로 이 알고리즘......경력코테 통과할정도만 실력을 쌓아야하는데 그조차 쉽지가 않다...