[마지막까지 긴장의 끈 놓지 않기 🔥]

매주 미션을 수행하면서 코드에 애정을 가지고 최선을 다해 몰입하여 열심히 했기 때문인지, 코드가 정말 만족스러웠고 더 수정할 곳이 없어보였다. 하지만 항상 한 곳 정도는 문제가 발생해 급하게 수정하는 경험을 했었다.

때문에 마지막 주차인 4주차는 더욱 조심스럽게, 마지막까지 긴장의 끈을 놓지 않으면서 코드를 작성했다.
그러다보니 자연스레 이전 미션들보다 더 많은 테스트를 작성하고, 더 많이 실행시켜보았던 것 같다.

특히 정말 조금의 잘못된 결과도 만들어내지 않기 위해 엣지 케이스는 없을 지, 실행 결과는 내가 예측하는 방향으로 정상적으로 출력이 되는 지, 각 메서드는 정상적인 결과를 내놓는 지 등 정말 생각할게 많았고 이러한 깊은 생각은 더욱 개발에 집중할 수 있는 깊은 몰입으로 이어졌다.

실제로 엣지 케이스를 생각하고 이를 테스트하면서 잘못 작성되었던 로직을 몇 가지 발견할 수 있었다.

예를 들어 할인 전 결제 금액이 120,000원 이상부터 증정 이벤트가 적용되어야 했는데,
테스트 코드에서 할인 전 결제 금액을 120,000원으로 설정했음에도 불구하고 증정 이벤트 적용이 되지 않아 확인해보니, 120,000원 이상이 아닌 120,000원 초과로 조건을 잘못주고 있었다.

만약 이번 미션의 요구사항이 실무에서 요구 받은 내용이었고 위와 같은 실수를 저질렀다면 혜택을 받아야했던 고객들이 혜택을 받지 못하는 최악의 상황으로 이어질 수 있던 실수였지만,
테스트 코드 작성을 통해 이러한 상황을 캐치하고 해결하는 경험을 통해 테스트의 중요성을 깊이있게 이해할 수 있었다.

때문에 제출 직전까지 가능한 많고 다양한 상황의 테스트 코드를 작성하였고,
인텔리제이의 기능을 활용해 코드 커버리지를 검사해가며 실수의 발생을 최대한 줄이고자 하였다.
인텔리제이 코드 커버리지 측정법 포스팅

또한 이메일 형식으로 주어진 이번 미션은 이전 미션들보다 분석 과정이 조금 힘들었지만, 실수의 발생 확률을 최대한 줄여보고자 몇 번이고 읽으며 기능구현 문서를 정리했었다.

프리코스에서 미션들을 수행하며 실수는 항상 방심할 때 벌어지며 절대로 완벽한 코드는 없다는 생각을 가지고 철저히 테스트를 통해 검증해나가야 함을 배울 수 있었다.

어찌보면 개발자로 살아가며 가장 배워야할 부분 중 하나라고 생각이 드는데,
4주라는 기간만에 이를 몸으로 느끼며 배울 수 있었음에 정말 감사함을 느꼈다.



[상수는 책임을 가진 객체에 선언하자 📝]

이전 미션까지는 코드를 작성하면서, 애플리케이션에서 사용되는 상수는 모두 Constant 객체를 생성하여 그곳에서 관리하도록 개발하였다. 일반적인 게임을 생각했을 때, Setting이라는 페이지에 접속하여 설정 값을 변경하는 것이 익숙한 일이었기 때문에 미션도 “설정값을 한 곳에서 변경할 수 있다면 좋지 않을까?” 라는 생각이 있었고, 객체에서 관리하는 상수가 많아지면 코드도 길어져 코드를 읽는 것을 방해한다는 생각이 있었기 때문이었다.

하지만 이는 그닥 좋은 설계는 아님을 4주차에 와서야 느낄 수 있었다.
4주차 미션은 여태까지 해왔던 미션 중에 가장 클래스를 많이 생성하게 되었는데, 클래스가 많아지니 설정 값을 바꾸거나 확인하기 위해 Constant 클래스를 오가며 개발하는 것이 상당히 피로했다.
작은 단위의 개발에서는 굉장히 효율적이고 효과적이라는 생각이 들었으나, 프로그램의 사이즈가 조금만 더 커지니 바로 한계점이 드러났다.

추가로 코드 리뷰 시에는 상수가 선언된 곳에 접근하려면 직접 패키지 구조를 살피며 찾아다녀야 했고, static import를 했을 때는 직접 패키지 import 목록에서 상수 클래스를 찾아야 하는 등 읽는 이들에게 번거로움을 선사하는 비효율적인 코드였다.

때문에 상수를 사용하는 객체 내부에 상수를 직접 선언하여 쉽고 빠르게 접근할 수 있도록 코드를 수정하니, 원하는 값을 금방 확인할 수 있어 편리했고 코드 리뷰 시에도 상수가 어떤 값을 가지고 있는지를 조금의 스크롤 움직임으로 파악할 수 있게 되어 리뷰어들의 피로도 덜어줄 수 있게 되었다.



[객체와 메시지를 주고받기 💬]

객체에서 Getter나 Setter를 통해 값에 직접적으로 접근하지 말고 메시지를 주고받으라는 말이 처음엔 이해하기 어려웠다.

Setter는 외부에서 값이 변경되지 못하도록 막기 위해 자제하는 것이 맞지만, Getter를 안쓰면 도대체 값을 어떻게 이용하라는 거지?”
라는 고민이 생겨 이러한 고민을 해결하기 위해 열심히 생각하고 학습하였고,
덕분에 4주차에 와서는 메시지를 주고받는다는 말이 어떤 의미인지 어느정도 파악할 수 있게 되었다.

예를 들어 이번 미션에서 도메인 객체 중 혜택(할인,증정상품)에 대한 정보를 가진 Benefits 객체를 작성하면서
아래와 같은 문제점들을 고려하며 섬세하게 코드를 작성할 수 있었다.



첫번째로 Getter를 통해 할인과 증정 상품에 대한 정보를 '외부'에서 가져가서 사용하게 되면 어떨까?

가져간 메서드는 외부에서 생성한 다른 객체로 초기화되어 사용해도 애플리케이션 자체는 문제없이 작동한다.
즉 변경이 발생해도 알아차릴 수 없다는 것이다.

Optional<GiftMenu> giftmenu = benefits.getGiftMenu();
giftMenu = Optional.empty();

이런식으로 말이다.


프로그램 어딘가에 나도 모르게 위와 같은 코드가 작동하도록 구현해놨다면,
예외가 발생하거나 프로그램이 멈추는 일은 없지만 내가 예상한 결과와는 전혀 다른 결과가 발생할 것이다.
깊이 생각하며 개발한 코드에서 이런 일이 발생할 가능성은 낮지만, 이런 상황이 발생할 경우를 ZERO로 만들어줄 수 있기 때문에 Getter 사용을 지양하는 것이 옳다고 느꼈다.



두번째는 '디미터의 법칙'에 관련된 문제이다.

객체 내부에서 행위를 가지지 않고 외부에서 Getter를 통해 가져오게되면 접근을 위한 dot(.)이 굉장히 많아지고 이는 코드의 가독성을 낮추는 요인이 될 수 있다.

아주 작은 예를 들어 Benefits 객체에서, 필드인 Optional<GiftMenu>를 활용한 메서드를 통해 증정 상품에 대한 가격 정보를 얻어오도록 하지 않고 필드에 대한 Getter만 구현했다고 가정해보자.

benefits.getGiftMenu().get().getTotalPrice();

그럼 증정 상품에 대한 가격정보가 필요할 때,
길이는 길고 가독성은 낮은 위와 같은 코드가 발생하게 되었을 것이다.

이러한 생각과 고민 등을 통해 Getter를 지양해야하는 이유를 이해할 수 있었고,
그럼 어떻게 해야할지를 고민하는 과정에서 자연스레 메시지를 주고받도록 설계하는 방법을 배울 수 있었다.

Getter를 통해 외부로 필드 값을 꺼내가는 것이 아닌,
객체 내부에서 필드값을 통해 필요한 행위를 수행하고 그 결과값을 리턴하도록 구현하면 되었다.

다시 말해, Getter를 통해 외부에서 필드값을 활용하여 어떤 행위를 수행하던 방식이 아닌
객체에게 행위를 요청하고 행위에 대한 결과 값을 요청하는 것이 바로 객체와 메시지를 주고 받는 것이었다.


덕분에 위와 같이 디미터의 법칙을 어기고 get을 허용해서 값의 변경을 열어두었던 코드는

public int getGiftMenuPrice() {
    if (giftMenu.isPresent()) {
        return giftMenu.get().getTotalPrice();    
    }
    return 0;
}

Benefits객체 내에 위와 같이 “증정상품의 금액을 알려줘”라는 메시지를 담은 행위를 둠으로서
위에서 설명한 문제점을 모두 제거할 수 있었다.



[프리코스를 마치며 🏁]

4주간 프리코스에 몰입하고 많은 사람들과 협력하며 단기간에 많은 성장을 이룰 수 있었다.
테스트 코드 작성이 복잡하고 어렵게만 느껴졌던 이전과 다르게 테스트 코드의 중요성을 배우고 엣지 케이스를 찾아나서는 개발자로 성장할 수 있었으며, 객체의 분리 기준인 역할과 책임이 무엇인지 그리고 객체간에 대화하도록 작성하는 것이 무엇인지 등을 배우며 많은 성장을 경험할 수 있었다.

또한 단순 자바만 사용한 프로그래밍 경험을 통해 “백문이 불여일견”이라는 말처럼 글만으로 특정 방법론이나 규칙 등에 대해 이론적으로 학습하는 것이 아니라,
직접 문제를 몸으로 느끼면서 방법론 또는 규칙들이 왜 생겨났는지 이해하며 개발하니 너무나도 큰 도움이 되었던 것 같다.

개발적인 부분 외에도 프리코스를 경험하며 커뮤니티와 코드리뷰를 통해 사람들과 함께 성장하는 경험을 통해 ‘함께’의 의미와 소중함을 4주간 뼛속 깊이 배워갈 수 있었다는 점이 가장 큰 배움 중 하나라고 느꼈다.

특히 커뮤니티 사람들과 스터디를 만들어 미션이 끝날 때마다 옹기종기 모여 각자의 코드를 발표하고 질문에 대답하며 서로의 배운 점을 나누던 시간들은 이렇게나 깊이 몰입하고 즐겼던 적이 있었나 싶을 정도로 너무 유익했고 소중했다.

뿐만 아니라 배운 점들이나 마주한 문제에 대한 해결 과정을 블로그에 정리하며 학습하고 이를 커뮤니티에 공유하였는데,
사람들의 피드백 덕분에 더욱 좋은 문서로 개선해나가고 놓쳤던 부분을 캐치하여 더욱 깊이 있게 학습해나갈 수 있었고 도움이 되었다는 사람들의 코멘트 하나하나가 정말 큰 힘이 되어주었다..

✨ 미션 수행 중, 포스팅 기록


프리코스 미션이 완전히 끝나 여유가 조금 생겼으니, 커뮤니티에서 만나 4주간 함께 도움을 주고받던 사람들과 오프라인으로 모여 얘기도 나누고 서로의 코드도 리뷰해보려한다.

분명 처음에는 내 코드를 모르는 사람에게 보여주는 것이 쑥스럽기도 하고 두렵기도 했는데, 지금은 오프라인으로 만나 함께 서로의 코드에 대해 소통할 정도로 즐거워졌다는 것이 너무 신기한 경험이었다.

결과를 기다리는 동안 여유가 생겼으니 지금까지 해왔던 미션의 코드를 조금 더 개선해보고자 한다. 첫 번째 미션으로 돌아가면 고칠 점들이 굉장히 많을 것 같은데 하나하나 고쳐보며 배운 것을 잊지 않게 노력해보고자 한다.

정말 마지막으로 우테코 6기의 프리코스를 경험할 수 있었음에 감사했고,
그럴 수 있도록 모든 이들에게 기회를 주신 우아한 테크코스의 모든 관계자분들! 정말 감사했습니다!

profile
하나씩 천천히 깊이있게 쌓아가는 백엔드 개발자 최승준입니다.

0개의 댓글