시작하며







요즘 이른 아침 자리에 앉아 프리코스 미션을 진행하며, 앉은 자리에서 식사를 하고 미션에 다시금 몰입하다 보면 어느새 창밖이 어두워져 있는 걸 보고 늘 신기하다는 생각을 한다 !
정말 신기하게 매 주차 미션을 진행하며 더욱 밀도 높은 몰입을 경험하며 가장 폭발적인 성장을 경험한다.
그 이유로서 미션을 진행하며 그저 "어떻게 구현하지"라기보다는 여러 가지 구현 방법 중 "아.. 이 방법은 이런 부분이 약간 아쉽지만 이런 장점이 있네. 그래, 난 지금 이런 이점이 더 크게 느껴져!"라며 나만의 근거를 토대로 생각하며 미션을 구현하고 있음을 느꼈기 때문이다.
객체지향 설계 및 테스트 코드 작성 방법에 너무 많은 방법이 있고, 문맥에 따라 어떤 걸 챙겨야 하는지 저울질해보며 저만의 생각을 코드에 녹여내는 과정이 너무나도 즐거웠다 !
분명 작년에도 경험했던 로또 미션이었지만, 한번 경험한 문제여서 수월하기보다 더 많은 시야와 설계 과정들을 고려하느라 오히려 더욱 많은 시간을 쏟아부었다. 더 좋은 방향성에 대해 고민하고 적용하는 과정에서 알고 있다고 생각했던 개념들에 대해 깊게 고민해보면 늘 제가 놓친 부분들이 있어서 너무 흥미진진했다 !
3주차는 '제거하는 리팩토링'과 '개념의 본질'을 이해하며 "이게 정말 필요한가?", "왜 이렇게 설계했는가?", "진짜 불변인가?"라는 근본적인 질문들과 마주하며 하루 평균 10시간씩, 7일간 몰입했다.
해당 3주차 로또 미션을 진행하며 다양한 고민을 했었고, 각각의 구현 방법만의 장단점이 있었고 현재 나의 생각과 주관을 토대로 더 큰 이점을 가지고 있다고 판단한 방법으로 구현을 마쳤으며, 이러한 판단 기준과 근거는 이후 미션을 진행하거나 학습을 하며 분명 변화할 수 있다고 생각되지만 나만의 근거와 주관을 가질 수 있어 뿌듯했다 !
특히 1주차와 2주차의 코드리뷰를 통해 주고 받은 의견과 피드백 사항들을 적용해보기 위해 블로그에 정리하며 이해를 바탕으로 나만의 근거를 토대로 정리하며 제 것으로 만들기 위해 노력했다.
고민하며 배우고 적용한 점
"검증의 책임 톺아보기"
관련 포스팅 : https://softmoca.tistory.com/527
가장 먼저 마주한 고민은 2주차 코드 리뷰에서 받았던 "검증의 책임"에 대한 피드백을 실제로 적용하는 것이었다.
3주차에서는 이를 개선하기 위해 도메인 객체가 스스로 검증하도록 설계하기 위해 노력했고, 이 과정에서 가장 중요하게 깨달은 것은 검증을 두 가지로 구분해야 한다는 점이었다.
시스템적 검증은 사용자 입력이 올바른 형식인지 확인하는 것으로, InputHandler에서 재입력 기회를 제공하며 처리했다.
도메인 규칙 검증은 비즈니스 규칙을 만족하는지 확인하는 것으로, 각 도메인 객체의 생성자에서 자동으로 수행되도록 했다.
특히 "객체는 생성이 성공한 시점부터 스스로 유효성을 유지해야 한다"는 불변성의 본질을 깨달았고, 덕분에 무효한 객체를 만드는 것이 불가능하며, Controller는 도메인 규칙을 전혀 몰라도 되는 구조가 되었다 !
2주차의 나는 "검증이 필요하니까 Validator를 만들자"고 생각했지만 3주차를 거치며 올바른 접근 순서를 정립하게 되었다.
먼저 객체를 만들고 생성자에서 자체 검증하게 하고, 검증 로직이 정말 복잡해지면 그때 Validator로 분리하는 것이다 !
이렇게 하면 도메인 규칙이 도메인 객체에 캡슐화되고, 객체가 스스로 유효성을 보장하는 구조가 된다는 걸 몸소 경험했다.
"책임을 바라보는 관점 - 정보 전문가 vs 단일 책임 원칙"
관련 포스팅 :https://softmoca.tistory.com/528
기본 기능 구현을 마친 후, 리팩토링 과정에서 가장 오래 고민했던 부분은 "책임의 경계"였다.
처음에는 통계에서 "결과"라는 개념을 명시적으로 표현하고 수익률 계산의 책임을 분리하면 좋겠다고 생각했다. 하지만 막상 코드를 작성하고 보니, 결과 클래스는 하는 일이 거의 없고 그저 거쳐가는 계층이라고 느껴졌다.그리고 이틀 동안 세 가지 방안을 비교했보았다.
결과 클래스를 유지하면 불필요한 래퍼가 되고, 컨트롤러가 직접 계산하면 도메인 로직이 누수되며, 통계 클래스가 위임받으면 정보 전문가 원칙과 묻지 말고 시켜라 원칙을 모두 준수할 수 있었다.
처음에는 "수익률 계산"이 통계 클래스의 책임이 아닌 것 같았고, 단일 책임 원칙을 위반하는 것 아닌가 고민했다. 하지만 깊이 생각해보니, 통계 클래스는 통계 데이터와 모든 계산 로직을 이미 알고 있었다."책임"에 대한 이해가 잘못되어 있었다.
"메서드 하나가 곧 책임 하나"라고 생각했지만, 여러 메서드가 서로 관련된 하나의 목적이나 데이터를 중심으로 동작한다면 그것은 여전히 하나의 책임이었다!
결국 결과 클래스를 과감히 제거하고 통계 클래스에게 수익률 계산 책임을 주었고, 불필요한 중간 계층이 제거되어 코드가 더 간결하고 명확해졌습니다. 이 경험을 통해 무언가를 제거하는 것이 추가하는 것보다 훨씬 어렵다는 것을 배우며 리팩토링의 본질에 한 발 더 가까워졌다고 생각하며 제거할 줄 아는 용기를 얻게 되었다 !
"ErrorMessage Enum 관리 및 간소화 시도"
관련 포스팅 : https://softmoca.tistory.com/523
ErrorMessage Enum을 도입한 후, 코드가 너무 길어 가독성이 떨어진다는 점이 아쉬웠다.
먼저 Static Import를 적용해 클래스명을 생략할 수 있어 코드가 간결해졌고, IDE의 자동 완성 지원으로 어느 클래스의 상수인지 바로 알 수 없다는 단점도 거의 체감되지 않았다.
더 간소화하고 싶어 toString 메서드를 오버라이드하여 문자열 상수처럼 사용하고 싶었다. 하지만 IntelliJ는 명시성을 중요하게 여겨 이를 막았고, 결국 메서드명만 달라졌을 뿐 코드가 길어지는 것은 변함없었다.
다음으로 헬퍼 메서드를 추가해보았고 코드가 짧고 깔끔했다 !
하지만 곧 의문이 들었다. 원래 책임은 에러 메시지 관리인데 예외 객체 생성 책임까지 가지면 단일 책임 원칙을 위반하는 것은 아닐까? 단순히 코드 몇 자 줄이려고 메서드를 추가하는 것은 과도한 설계가 아닐까?? 나중에 다른 예외 타입이 필요하면 또 메서드를 추가해야 하고, 결국 간소화를 위해 오히려 복잡해지고 범용성이 떨어질 것 같았다.
헬퍼 메서드는 실용적이지만 추가 책임을 가지게 되어 과도한 설계라고 생각해서 많은 시간을 투자했지만 결국 Static Import만으로 마무리했다. 덕분에 때로는 가장 단순한 해법이 최선의 선택이 될 수 있다는 것을 배웠다 !
이 과정에서 트레이드오프와 잘못된 몰입 방향성에 대해 깊이 생각해볼 수 있었고, 단 하나의 목적만을 위해 다른 원칙들을 고려하지 못한 제나자신을 돌아볼 수 있었고, 실패했지만 좋은 경험이었다 !
"Service 계층의 탄생과 제거"
관련 포스팅 : https://softmoca.tistory.com/529
1, 2주차에 비해 요구사항이 많아지자, 웹 애플리케이션 개발 경험을 떠올리며 서비스 계층이 필요할 것 같다는 생각이 들었다. 도메인 객체들은 보이는데 협력 관계가 어려웠고, 우선 돌아가는 코드를 만들기 위해 도메인 객체를 조율하는 계층을 구성했다.
하지만 리팩토링을 시작하며 여러 도메인들을 풍부하게 만들고 메시지를 통해 협력하게 하니 점차 의미가 명확해지고 협력 관계가 잘 보이기 시작했다. 여러 책임들이 서비스에서 각각의 도메인으로 이동하니 점차 서비스 존재 자체가 의미가 없어지고 오히려 혼란만 가져왔다.
미션 가이드를 반복해서 읽던 중 "발매기"라는 단어가 머리에 박혔다 ! 지금까지 컨트롤러 자체가 발매기 역할을 한다고만 생각했던 것이 문제였다.
발매기라는 도메인 객체를 추가했고, 실제 로또 발매기처럼 돈을 넣으면 로또를 발행하고 당첨 번호를 입력하면 확인해주는 존재가 되었고 모든 것이 맞아떨어졌다 ! 로또는 스스로 매칭할 수 있고, 당첨 번호는 스스로 등수를 판정할 수 있으며, 발매기는 스스로 발행하고 확인할 수 있게 되어 서비스 계층은 완전히 필요 없어졌다!
도메인이 빈약했을 때는 서비스가 필요했지만, 도메인이 풍부하게 성장하며 서비스가 "불필요"해졌다. 서비스 계층을 도입했다가 결국 제거하게 되었지만, 이 과정이 없었다면 빈약한 도메인과 서비스 관계에 대해 생각해보지 못했을 것이다.
덕분에 좋은 코드는 불필요한 것을 제거하는 것 또한 중요하다는 것을 배웠다 !
지난 코드 리뷰를 통해 개선 한 점
검증 로직의 위치와 책임




2주차 미션의 구조에서는 "검증을 깜빡하면 무효한 객체가 생성될 수 있다"는 근본적인 문제가 있었다.
또한 Validator를 분리하는 기준도 "검증이 필요해서"가 아니라 "검증이 너무 많고 복잡해서 객체가 감당하기 힘들 때"라는 점 너무 와닿았다 ! 나는 "검증이 필요하니까 Validator를 만들어야지"라고 생각했는데, 접근순서가 잘못 되었던것 같다 !
객체는 생성이 성공한 시점부터 스스로 유효성을 유지해야 하는데, 나는 Car가 아니라 Controller가 검증을 책임지게 만들었었던것이 문제이다 ! 생각해보니 Validator를 분리한다는 것과 "객체가 스스로를 검증한다"는 것은 모순이 아니라 함께 갈 수 있는 개념이었다 !


그래서 3주차에는 위와 같이 도메인과 VO가 생성이 성공한 시점부터 스스로 유효성을 유지해도록 했다 !
이를 통해 확실히 객체 생성 시점에 항상 유효성이 보장과 캡슐화와 불변성을 강화할수 있어 어디서 생성하든 검증을 깜빡할 수 없는 구조가 되었다 !
또한 이 객체는 이런 값들이 오면 안돼 ! 라는거 바로 이해할 수 있었고, 이러한 검증이 너무 많아질 경우 그때서야 검증 클래스를 분리하면 되겠구나 ! 라는 깨달음을 얻었다 ! 하지만 다소 아쉬운 점은 VO 활용을 많이 해서 그런지 크게 중복이 너무 무겁게 느껴지는 부분이 없어 따로 빼지는 못한점이 약간은 아쉬운 경험이다 !
stateless한 파싱과 검증을 위한 유틸객체


2주차에서 단순히 파싱과 검증의 책임을 위임하기 위해 하나의 클래스로 그 책임을 분리했었다. 하지만 여러 검증 혹은 객체에서 파싱을 재사용할 수 있다는 점은 미처 캐치하지 못했다 !
무엇보다 당시 리팩토링 과정에서 단순히 검증 로직이 필요하니까 객체만들어서 써야지 하며 어떤 특성을 가진 객체인지, 어떻게 사용되어야 하는지 깊은 고민없이 그냥 바로 썼고 import가 필요하니 바로 new로 생성해서 사용해 버렸다 !
그로 인해 inputView가 inputValidator를 내부에서 직접 생성하고 있어, static의 간편함도 아니고, DI 방식의 테스트 용이성도 없지 못한채 강하게 결합된 형태였다 !


그래서 3주차에서는 파싱의 책임을 하는 InputParser, 검증을 책임하는 InputValidator로 각각 분리해 중복을 방지해 보았고, 둘 모두 stateless한 객체로서 모든 메소드를 static으로 만들어 객체 생성없이 바로 사용가능하도록 구성하였다.
이를 통해 확실히 inputValiator를 사용한 입력 검증 테스트가 용이해졌다 !
다만, 리팩토링을 하는 과정에서 시간이 부족하여 DI 방식을 통해 더욱 테스트 용이성을 올려보는 시도를 해보지 못한점이 다소 아쉬웠다 !
Stream API와 캡슐화 균형



2주차에서는 getter와 스트림 그리고 VO에 대해 잘못된 개념을 가지고 있어 Tell, Don't Ask 원칙을 잘못 해석하고 사용을 했다 !
그리고 아래 사항들을 깨달으며 객체에게 더욱 충분한 행동을 부여해야한다는걸 깨달았다 !
Position의 getValue()는 getter가 아니라 언박싱이라는 점 !
Wrapper의 본질적 목적이 원시값에 의미와 행동을 부여하는 것인데, 값을 꺼내는 건 자연스러운 일이라는 점 !
객체가 스스로 비교하도록 메시지를 구성하면 getter 없이 스트림으로 충분히 기능 구현이 가능한 점 !



3주차에서는 로또 자체에 포함 행위를 가지도록하고, Rank 자체에 Comparable개념을 적용해서 스스로 비교할수 있도록 하여 외부에서 if 분기로 등수 판정을 하지 않고, Rank 스스로 판단할수 있도록 구성해 보았다 !
확실히 객체에 충분한 행동을 부여하니 스트림을 사용하면서도 getter없이 원활히 캡술화를 챙기며 기능을 구현할수 있었다 !
게터(Getter) 테스트의 필요성 및 assertThat 과 assertAll


2주차에서는 객체가 할 수 있는 모든 것을 테스트해야 한다고 생각해서 getter도 테스트를 했다.
하지만 게터 테스트는 내부 구현에 의존하기 때문에 필드 구조가 바뀌면 실제 동작에는 영향이 없어도 테스트가 쉽게 깨질 수 있는 문제가 있었다 !

또한 assertThat을 여러 번 호출하면 첫 번째 검증이 실패하는 순간 테스트가 중단되어서, 나머지 검증 결과를 확인하려면 테스트를 여러 번 돌려야 하는 비효율이 있었다 !


그래서 3주차에는 게터 테스트는 하지 않고 동작을 테스트해서 상위 레벨 테스트를 할때 자연스럽게 검증이 되도록 테스트를 구성해 보았다 ! 확실히 구현세부 사항에 대한 테스트를 안하게 되니 리팩토링 내성도 전체적으로 강해지는것을 느꼈고, 리팩토링을 진행하며 유지보수상이 줄어드는 것을 느꼈다 !
또한 assertAll()을 사용해 모든 검증을 실행한 후 실패한 항목들을 한번에 보여주도록 해서 테스트 피드백이 훨씬 명확하고 빠르게 진행되도록 개선해 보았다 !
에러메시지 Enum

2주차에선은 검증에서 사용하는 상수들을 해당 클래스 외부로 뺴면, 해당 메시지를 확인하기 위해 다른 패키지로 이동을 하는게 피로감이 생겨 따로 뺴지 않았다 ! 하지만 그로인해 몇몇 클래스에서는 저렇게 필요한 부분을 복사 붙여넣기해서 다시금 넣는 작업을 해줬어야 했다 !

그래서 3주차에서는 에러 메시지를 enum으로 만들어 보았다 !
네이밍을 확실하게 하니 매번 메시지를 enum 파일을 통해 확인하지 않아도 되서 생각보다 많이 번거롭지 않았다 !
또한 무엇보다 여러 클래스 특히 테스트 코드에서 에러메시지를 사용하는게 너무 편해졌다 !
코드리뷰를 통한 개선 사항 체크
TDD와 버그 발견

3주차 미션을 진행하며 제출일 전날에서야 기능적인 버그를 발견했다.
3주차에서는 설계 → 구현 → 리팩토링 → 테스트 -> 리팩토링 → 테스트 를 반복하며 미션을 진행했지만 해당 버그를 전혀 인지 하지 못했으며, 실제로 콘솔을 통해 여러 입력값들을 직접 넣어보는 과정을 통해 버그를 발견했다 !
그리고 이후 3주차 미션 소감문과 회고를 작성하며 TDD로 미션을 진행했다면 이런 버그를 발견하지 않을 수 있었을까? 라는 생각이 들어고 PR에 리뷰어들의 의견을 들어 보았다.
그 중 TDD는 '테스트를 먼저 작성하면서 설계와 요구 사항을 더 명확히 다듬는 과정'을 통해 버그를 조기에 발견하거나 아예 만들지 않게 도움을 줄수 있겠다는 의견을 듣게 되었다 !
무엇보다 나의 실수였던 '동작하는 코드' 보다 '의도대로 동작하는 코드'를 빠르게 검증한다는 점이 확실히 이번 문제에 도움이 될것 같다는 의견이 확 ! 와닿았다 !
또한 굳이 TDD가 아니더라도 기능 구현 후, 해당 기능이 의도한대로 잘 동작하는지 테스트를 통해 피드백 받는 과정으로도 이런 문제를 해결하는데 도움이 될것 같다는 의견에도 큰 공감을 했다.
최종적으로 이런 '기능이 의도한대로 잘 동작 하는지 테스트 후 커밋' 하는 과정을 TDD 사이클링이 자체적으로 강제적(?)으로 가져 올수 있다고 생각을 했다 !
의존성 주입과 테스트

컨트롤러 테스트에 대해서는 고려하지 않아 해당 부분을 고려해 보지 못했었다 !
현재 구조에서는 LottoController가 구체 클래스에 강하게 결합되어 있어, 테스트나 확장 시 제약이 있을 수 있을 것 같다 !
확실히 의존성을 외부에서 주입하게 된다면 테스트시 Mock 객체 주입을 통해 다양한 테스트용 로또 생성 구현체를 사용할수 있고, 이후 다른 다양한 입력으로 변경이 가능해서 훨씬 유연할것 같다 ! 이후에 꼭 적용해 봐야겠다 !
마치며
7일간 하루 평균 10시간, 총 약 70시간을 투자하며 3주차 로또 미션에 몰입했다.
매일 TIL을 작성하고 여러 개의 블로그 포스팅을 하며, 단순히 미션을 완수하는 것이 아니라 매 순간 성장하는 과정 자체가 너무 즐거웠다!
특히 이번 주차는 '제거하는 리팩토링'의 의미를 깊이 체감한 시간이었다.
클래스를 만들었다가 제거하고, Service 계층을 도입했다가 제거하고, Lottos 일급 컬렉션을 만들었다가 제거하며"이게 정말 필요한가?"라는 질문을 끊임없이 던졌다.
무언가를 추가하는 것보다 제거하는 것이 훨씬 어렵다는 것을, 그리고 때로는 제거하는 용기가 더 좋은 설계로 이끈다는 것을 배웠다.
또한 블로그에 학습 내용을 정리하며 '이해했다'와 '설명할 수 있다'의 차이를 더욱 깊이 체감했다.
검증의 책임, Information Expert와 단일 책임 원칙의 균형, ErrorMessage의 간소화 시도 등을 글로 정리하려니 코드로 구현할 때보다 훨씬 더 깊이 생각해야 했고, 그 과정에서 진정한 이해가 생겼다. 특히 블로그 포스팅을 통해 나만의 판단 근거와 트레이드오프를 명확히 정리할 수 있었던 것이 큰 성장이었다.
1주차가 객체지향적 사고의 시작이었고, 2주차가 설계와 테스트의 본질을 탐구하는 시간이었다면, 3주차는 개념의 본질을 이해하고 불필요한 것을 제거하는 시간이었다. 일급 컬렉션, Value Object, Record, Service 계층 등 좋다고 알려진 것들을 무조건 적용하는 것이 아니라, "이 프로젝트에서 진짜 필요한가?"를 고민하며 선택할 수 있게 되었다.
특히 코드 리뷰를 통해 설계는 정답이 아닌 맥락과 상황에 따른 선택임을 더욱 깊이 이해했다.
description을 Rank에 둘지 OutputView에 둘지, 수익률 계산을 WinningStatistics에 맡길지 PurchaseAmount에 맡길지, LottoMachine을 도메인 객체로 만들지 Service로 만들지 등 모든 선택에는 명확한 근거와 트레이드오프가 있었다.
완벽한 설계는 없으며, 각 선택의 장단점을 이해하고 현재 맥락에 가장 적합한 선택을 해야 한다는 것을 몸소 느꼈다.
정확히 1년 전 작년 프리코스에서는 예외 처리와 동작한은 기능 구현을 위해 많은 시간을 투자했다면, 지금의 나는 "왜 이렇게 설계했는가?"를 끊임없이 고민하고 있다. 이 변화가 나에게는 가장 큰 성장의 증거이며, 더욱 우아한테크코스에 합류하고 싶은 동기를 불태우게 만든다!
TDD TDD TDD !!
다음 주차에서는 이번 주 배운 교훈들을 더욱 발전시키기 위해 TDD 테스트 주도 개발을 본격적으로 시도해보고 싶다 !
3주차에서 가장 아쉬웠던 점은 Rank의 보너스 매칭 버그를 제출 전날에야 발견했다는 것이다. requiresBonus == bonus라는 로직은 분명 잘못되었지만, 설계 → 구현 → 리팩토링 → 테스트 순서로 진행하다 보니 테스트 단계에서 Boolean 파라미터의 양쪽 경우(true/false)를 모두 검증하는 케이스를 놓쳤다. 만약 테스트를 먼저 작성했다면 "3개 일치 + 보너스 true일 때도 5등이어야 한다"는 케이스를 구현 전에 명세했을 것이고, 구현 단계에서 바로 버그를 발견할 수 있었을 것이다.
또한 '제거하는 리팩토링'을 경험하며 Result 클래스, Service 계층, Lottos 일급 컬렉션을 만들었다가 제거하는 과정에서 많은 시간을 투자했다. 만약 TDD로 접근했다면 "이 객체가 정말 필요한가?"를 테스트 작성 단계에서 먼저 고민했을 것이다. 테스트를 작성하다가 "이 객체를 테스트하려니 실제로 하는 일이 없네?"라는 것을 조기에 발견하고, 불필요한 추상화를 미리 막을 수 있었을 것 같다 !
특히 검증의 책임에 대한 접근 순서를 확립하는 데도 TDD가 큰 도움이 될 것 같다. 2주차에서는 Validator를 먼저 만들고 나중에 도메인 검증으로 옮기는 우회를 했지만, TDD로 시작하면 "Lotto 객체를 어떻게 생성할 것인가?"를 테스트하면서 자연스럽게 생성자 검증이 먼저 떠오를 것이다. 테스트가 설계를 이끌어주는 경험을 꼭 해보고 싶다 !
코드 리뷰에서 논의한 "description을 어디에 둘 것인가", "수익률 계산 책임은 누구에게 줄 것인가" 같은 설계 결정도, TDD로 접근하면 "이 객체를 어떻게 사용할 것인가"를 먼저 고민하게 되어 더 명확한 판단 근거를 얻을 수 있을 것 같다. 테스트 코드를 작성하며 "이 메서드를 호출하는 클라이언트 입장에서 자연스러운가?"를 먼저 생각하면, Tell Don't Ask나 Information Expert 같은 원칙들이 자연스럽게 녹아들 것 같다.
무엇보다 TDD는 '의도대로 동작하는 코드'를 빠르게 검증하게 해주며, 리팩토링에 대한 두려움을 없애준다는 점에서 더더욱 끌린다 !
이번 주차에서 '동작하는 코드'는 만들었지만 실제로 의도대로 동작하는지 늦게 확인했던 경험 때문에, 다음에는 Red(실패하는 테스트) → Green(통과하는 구현) → Refactor(리팩토링) 사이클을 통해 매 순간 의도를 검증하며 개발이 자연스레 나아가는 경험을 하고 싶다 !
또한 이번 주차에서 "이 객체는 무엇을 위해 존재하지?"라는 생각과 고민을 하며 방향성을 잃어 종종 혼란스러웠다 !그리고 Result 클래스를 제거하고 Service 계층을 제거할 때 "혹시 동작이 깨지지 않을까?" 하는 불안감이 있었다.
하지만 촘촘한 살아있는 테스트가 있다면 테스트가 안전망 역할을 더욱 잘해줄것이기 떄문에 제거하는 용기를 더 쉽게 낼 수 있을 것 같다 !
Lotto, Rank, WinningNumbers 같은 핵심 도메인 객체부터 TDD를 적용해보고 싶다 !
특히 Boolean 파라미터가 있거나, Enum으로 분기 처리를 하거나, 복잡한 계산 로직이 있는 부분에서 TDD가 빛을 발할 것 같다. 점차 범위를 넓혀가며 "테스트가 설계를 이끈다"는 경험을 직접 느끼며 꼭 채득해 한 단계 더 도약하고 싶다 !
실패를 두려워하지 않고, TDD가 주는 피드백을 통해 더 견고하고 명확한 설계를 만들어내는 과정이 너무 기대된다 !
마지막으로 이렇게 좋은 교육 프로그램을 통해 폭발적인 성장을 할 수 있는 기회를 주신 우아한테크코스 운영진분들께 진심으로 감사드린다 🙇🏻♂️ 무료로 이런 퀄리티 높은 경험과 코드 리뷰를 제공받으며 매일 성장할 수 있다는 것이 믿기지 않을 만큼 감사하다!
"정답을 찾는 것이 아니라, 왜 이렇게 설계해야 하는지 고민하는 과정" 자체가 얼마나 즐겁고 의미 있는지 다시 한번 느낀 한 주였다. 남은 프리코스 기간도 이런 자세로 임하며, 매일 성장하는 개발자가 되기 위해 최선을 다하겠다!!
'외부활동 > 우아한테크코스 [프리코스]' 카테고리의 다른 글
| 테스트주도 개발 시작하기 - 챕터 3. 테스트 코드 작성 순서 (0) | 2025.11.04 |
|---|---|
| 테스트주도 개발 시작하기 - 챕터 2. TDD 시작 (0) | 2025.11.04 |
| 도메인의 성장과 Service 계층의 관계 (0) | 2025.11.02 |
| 책임과 무한 리팩토링(정보 전문가 vs 단일책임원칙) (0) | 2025.10.31 |
| 검증의 책임 톺아보기 (0) | 2025.10.31 |