[우아한 테크 코스 8기] 프리코스 3주차

2025. 11. 3. 14:51·우아한 테크 코스 8기

0. 개요

금주 시간이 빠듯해서, 여유있게 프로그래밍을 하지 못해 아쉽다.

그래서 아쉬운 점이 좀 많은 편이다.

이번 주차는 뿌듯한 부분보다는 아쉬운 점이 많은 주차였습니다.

근로, 학부 수업, 동아리 행사 등 여러 일정이 겹치면서, 프로그래밍할 시간이 적었습니다. 그래서 주로 남는 시간에 머리속으로 구상만 하고, 일부러 비워둔 일요일에 프로그래밍을 시작했습니다.

덕분에, 머릿속에서 구상한 것 만큼 나의 코딩이 아름답지 않다는 걸 깨달을 수 있었습니다.

 

1. 오래 고민했던 부분과 시도

객체와 객체가 협력하는 건 무엇일까 고민하고 코드에 녹여내고자 노력했습니다.

카페에서 커피를 주문할 때, 고객과 종업원과의 협력, 종업원과 바리스타의 협력이 존재하듯, 이번 프로그래밍에서도 이러한 협력을 찾아내어, 구현하고자 노력했습니다.

 

1-1. READMD.md살아있는 문서로 관리하기

READMD.md 파일을 주로 초반에 작성하고 마지막에 일부 내용 추가하니, 일기쓰는 느낌이 들었습니다.

개인적으로 구현 기능 목록을 처음 추가한 뒤, 실시간으로 업데이트하며, ‘살아있는 문서’가 되어야한다고 생각했는데, 1주차와 2주차에 그러지 못해 아쉬움이 많았습니다.

피드백에서도 이 부분을 짚어주셔서, 3주차에는 초반부터 완벽한 READMD.md파일 작성을 지양하고, 다양한 변화와 풍파를 맞은 살아있는 문서로 관리하고자 노력했습니다.

그러나, 살아있는 문서를 만들기 위해 노력하는 게 처음이다보니 아쉬운 점도 많았던 거 같습니다.

1-2. 협력 구매자와 로또발매기

로또 발매기에서 로또를 구매한다는 행위가 있고, 로또 발매기는 무엇과 협력하는 걸지 고민해볼 필요가 있다고 생각했습니다.

구매하는 주체가 프로그래밍에 드러나지 않아서, Controller 상에서 List<Lotto>를 관리해도 괜찮았을 것입니다.

그러나 이는 Controller와 로또 발매기의 협력이고, 종합적인 비지니스 로직을 조율하는 Controller의 역할에는 맞지 않다고 생각했습니다.

따라서 ‘구매자’라는 객체를 식별하여, 구매자와 로또 발매기가 협력하도록 설계했습니다.

class Customer{
		public void buyLotto(Store store){
				this.lottoBundle = store.sellLotto();
		}
}

class LottoStore{
		public LottoBundle sellLotto(){
		
		}
}

기존에는 다음과 같이 Controller가 로직의 흐름을 모두 관리하는 방식이었습니다.

  • 구매 금액을 입력받아 Store에 넘겨준다.
  • Store는 LottoBundle을 반환한다.
  • Controller 내부 메서드에서 LottoBundle를 사용해, 다음 로직을 호출합니다.

이렇게 모든 호출부의 반환을 Controller가 관리하는 형태는, 객체의 메서드가 단순히 절차에 따라 호출되어 행동의 결과를 반환하기 때문에, ‘일회성 객체’로 느껴졌습니다.

그러나 Customer가 Store와 협력하고, 그렇게 획득한 LottoBundle로 다른 객체와 협력하니, Customer가 정말 살아있는 객체로 느껴졌습니다.

2. 실패 및 아쉬운 점

2-1. 살아있는 문서로 관리하기

살아있는 문서로 만들자! 라고 의식했지만, 그러지 못한 순간이 많았습니다. 특히, 어떤 문제를 맞이했을 때, 이를 해결하기 위한 방안에 집중했습니다. 그러다 보니, 구현 기능 목록에 업데이트를 해야하는 걸 까먹고, 구현이 된 후에야 기능 구현 목록을 업데이트한 적이 꽤 있었습니다.

2-2. this의 쓰임

this가 어느 부분에서 사용할 때는 명시적으로 객체 내부의 상태라는 걸 잘 드러내 준다고 생각합니다. 그러나 온점을 통해 접근하다 보니, this와 stream을 같이 사용하면 가독성이 떨어지는 걸 느꼈습니다. 그렇다고 어떨 때는 this를 쓰고 어떨 때는 this를 사용하지 않으면 코드를 작성하는 기준이 명확하지 않다고 생각합니다. 이부분은 계속 고민해보겠습니다. + 글을 쓰면서 생각해보니 this 사용보다는 명확한 변수 네이밍이 근본적인 해결책이라는 생각이 들었습니다.

2-3. 변수 네이밍을 잘 짓지 못했다.

WinningLotto는 당첨번호와 보너스 번호를 필드로 가집니다.

이때, 사용자의 Lotto와 비교하는 로직을 구현하기 위해서 일반당첨번호를 Lotto를 가지도록 구현했습니다. 같은 클래스 끼리는 private에 접근이 가능하다는 장점 덕분에 Getter를 지양하면서 값 비교를 할 수 있었습니다.

그러나 ‘당첨번호’라는 네이밍이 Lotto에 매핑 되는 것이 매우 어색하다고 느껴졌습니다. 또한 당첨번호와 보너스 번호의 네이밍을 winningLotto, bonusNumber로 사용했는데, 같은 번호라는 의미와 달리 계층 수준이 달라서 어색하게 느껴졌습니다. 그렇다고 변수명을 normalNumbers로 짓자니 타입은 Lotto이네요. 근본적으로 설계가 잘못된 게 아닐까 하는 아쉬움이 많습니다.

2-4. 출력 변환 책임

지금까지 출력 System.out.println()은 OutputWriter의 책임이었습니다. OutputWriter는 상수 메시지 or 포맷과 출력할 매개인자를 가지도록 설계했습니다.

ApplicationView는 InputReader와 OutputWriter를 조합하여, 안내메세지 + 입력대기, 결과 출력을 구현하도록 설계했습니다.

그러나, 출력 내용이 복잡해지면서, 출력을 위해 변환하는 책임이 파편화되었습니다. 예를 든다면, “5개 일치, 보너스볼 일치 30,000,000원” 같은 메세지를 출력하기 위해 로또 당첨 순위인 LottoRank가 내부적으로 입력 형식에 의존하고 있다는 점이 있습니다.

2-5. 구현 순서

이번 회차에서 피드백에 있는 클래스 구현 순서를 지키지 못했습니다. 해당 내용은 읽었은나, 상수 부분을 빠뜨리고 피드백은 반영하지 못했습니다.

2-6. 테스트 복잡성

기본적인 Money, Number, Lotto 단위의 테스트는 쉽게 작성할 수 있었으나, Customer와 WinningLotto간의 협력을 테스트하는데 힘들었습니다. 확실히 Customer의 행위가 원시타입이 아닌 객체와 강하게 결합되어서 테스트를 하는 데 힘이 들었던 것 같습니다.

3. 다음번에는

3-1. 살아있는 문서와 소통하기

READMD.md 가 살아있는 문서가 되기 위해서, 그리고 이와 잘 소통하기 위해서 기능을 구현하기 전에, 구현 기능 목록을 확인하는 습관을 만들겠습니다. 또한 처음부터 완벽한 READMD.md를 만들겠다는 욕심보다는 기능 목록을 점점 업데이트하겠습니다. 이를통해 완벽하지만 죽은 문서 대신, 지속적으로 소통하며 살아있는 문서를 만들도록 노력하겠습니다.

3-2. this의 쓰임을 생각하기

this를 사용하는 기준을 정립해보고 싶습니다. 어떨 때 사용하면 좋고, 어떨 때 사용하는 건 별로인지, 혹은 사용을 지양해야하는 건 아닌 지 고민해보고 레퍼런스를 찾아보겠습니다.

현재 생각은 this를 사용하기 보다는 명확한 변수 네이밍을 통해서 간결함을 유지할 수 있도록 하는 게 좋다고 생각합니다.

3-3. 네이밍

지금까지는 네이밍을 지을 때, 단순히 책임에 대한 적절한 영어를 찾았습니다. 그러나, 이번에 처음으로 잘못된 설계가 초래하는 네이밍 모순 겪었습니다. 주석보다는 적절한 네이밍, 모호한 네이밍 보다는 적절한 설계를 느끼면서, 다시 한번 설계의 중요성을 느끼게 되었습니다.

3-4. 출력 책임

지금까지는 OutputWriter에 매개인자로 String 타입만 넘겨주어서, OutputWriter가 다양한 타입에 의존하는 걸 지양해왔습니다. 그리고 ApplicationView를 통해 조합하여, 사용했습니다.

출력 형식이 복잡해질수록 새로운 변화를 추구해야할 거 같습니다.

이런 경우에는 Dto를 사용하면 좋을 것 같습니다. 사실 이번에 Dto를 사용하지 않은 이유는, 미션이 그렇게 복잡하진 않을거라 생각했고, Dto 대신 객체 내부 로직으로 해결하고 싶었기 때문입니다. 그러나 Getter와 Dto를 지양하면서 결과적으로 출력책임이 파편화되었네요.

다음부터 LottoResult 같은 객체가 있다면, Record 타입의 Dto를 만들어서 계층간의 값을 전달하겠습니다. 또한 이를 ApplicationView에서 적절히 변환한다면, 계층과 객체간의 역할과 책임이 더욱 명확해질 수 있을 거 같습니다.

3-5. 구현 순서

이번에는 미처 상수 부분을 먼저 작성하지 못했습니다. 다음 오픈 미션 주차에는 각 객체가 사용할 상수는 무엇인 지 확인하고 이를 먼저 정의해보도록 노력하겠습니다.

3-6. 테스트코드

금주에는 시간이 없어, 코딩대신 머리속으로 구상만 하는 시간이 많았습니다. 때문에 테스트 코드에 대해서 개선할 수 있는 시간이 부족했습니다. 단위 테스트를 작성할 수록 디버깅 비용이 절감된다는게 정말 좋았는데 너무 아쉽습니다.

그리고 결정적으로 기존에 작성되어있는 테스트가 살아있는 디버깅 문서가 되어준다는 점이 좋았습니다. Lotto 단위 테스트 코드를 작성한 뒤, WinningLotto에서 많은 변화가 있을 때, 기존의 테스트 코드가 스스로 디버깅을 해주는 효과를 내주었습니다. 덕분에 변경에 따른 유지보수 비용을 절감할 수 있다는걸 깨달았습니다.

다음 2주동안(4-5주차)은 테스트코드를 잘 작성할 수 있도록 고민하고 노력해보고싶습니다.

'우아한 테크 코스 8기' 카테고리의 다른 글

우아한 테크 코스 8기 Level 1 - 1주차  (0) 2026.03.03
[우아한 테크 코스 8기] 최종 합격  (0) 2026.01.23
[우아한 테크 코스 8기] 1차 합격 및 최종 코딩테스트 후기  (0) 2025.12.30
[우아한 테크 코스 8기] 프리코스 2주차  (0) 2025.10.27
[우아한 테크코스 8기] 프리코스 1주차  (0) 2025.10.20
'우아한 테크 코스 8기' 카테고리의 다른 글
  • [우아한 테크 코스 8기] 최종 합격
  • [우아한 테크 코스 8기] 1차 합격 및 최종 코딩테스트 후기
  • [우아한 테크 코스 8기] 프리코스 2주차
  • [우아한 테크코스 8기] 프리코스 1주차
koreaioi
koreaioi
  • koreaioi
    koreaioi
    koreaioi
  • 글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (187)
      • JAVA (3)
      • 알고리즘 (90)
        • 백준 (11)
        • String(문자열) (12)
        • Array(1, 2차원 배열) (13)
        • Two pointers, Sliding windo.. (6)
        • HashMap, TreeSet(해쉬, 정렬지원 S.. (5)
        • Stack, Queue(자료구조) (8)
        • Sorting and Searching(정렬, 이.. (10)
        • Recursive, Tree, Graph(DFS,.. (14)
        • DFS, BFS 활용 (6)
        • 다시 시작! (2)
        • 기초 수학 (1)
      • 일상 (26)
      • Github (1)
      • MSA 공부 (4)
      • 경제, 금융, 디지털, 시사 (3)
      • 라즈베리파이 (10)
      • 프로젝트에서 일어난 일 (22)
      • FrontEnd 공부 (9)
        • React (8)
      • Spring (2)
      • 기술 세미나 (2)
      • DB (3)
      • 우아한 테크 코스 8기 (10)
      • 잡생각 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
koreaioi
[우아한 테크 코스 8기] 프리코스 3주차
상단으로

티스토리툴바