각종 후기/우아한테크코스

[우아한 테크코스 3기] LEVEL 1 회고 - 로또 2단계 미션의 1차 피드백을 받아보다 (25일차)

제이온 (Jayon) 2021. 2. 26.

 

 

안녕하세요? 제이온입니다.

 

오늘은 크게 수업과 로또 미션 피드백 반영을 하였습니다.

 

 

로또 미션 피드백 수업

오늘은 오전에 포비가 약 2시간 30분 정도 수업을 진행해 주셨습니다. 초반 1시간 동안은 정신 교육(?)을 진행하였고, 나머지는 리팩토링 중 TDD 하는 과정을 라이브 코딩해 주셨습니다. 제가 기억에 남는 부분에 대해서만 기록해 보겠습니다.

 

첫 번째는 아웃사이드 인 방식으로 학습하지 말라는 것입니다. 이것이 무엇이냐면, 주변에서 TDD가 좋다, OOP가 좋다, 디자인 패턴 알아야 한다, 누구 누구는 스터디를 한다더라하면서 남들에 의해 공부를 하게 되는 것을 말합니다. 이것은 자칫하면 번아웃으로 가는 지름길이 될 수 있습니다. 왜냐하면, 현재 자기 자신보다 잘하는 사람들과 비교하게 되어 금방 지칠 수 있기 때문이죠.

 

따라서, 포비는 반란군 기질을 가짐으로써 남들의 의견을 어느 정도 무시할 줄 알아야 한다고 말씀하셨습니다. 즉, 본인만의 기준을 세우고 묵묵하게 학습을 하라는 것이었죠. 그리고 이것을 인사이드 아웃 방식이라고 합니다.

 

인사이드 아웃 방식을 잘하기 위해서는 개인 회고나 학습 로그를 작성한 뒤, 한 가지에 일에 집중하는 습관을 만들어서 작은 성공의 맛을 보아야 한다고 하셨습니다. 또한, 한 번에 여러 가지를 하는 것이 아니라 한 가지 일에 집중을 하는 것이 중요하다고 하셨습니다.

 

이렇듯, 포비는 스스로의 기준을 세워서 남들과 비교하지 않고 꾸쭌하게 자기가 할 일을 지속하는 사람이 프로그래밍 뿐만 아니라 인생을 살아가는 데 있어서 좋은 태도라고 말씀해 주셨습니다.

 

저도 최근 들어서 잘하는 크루들을 보며 주눅이 들었는데, 그럴 시간에 어제의 나와 오늘의 나를 비교하면서 부족한 점을 찾아 보완하도록 노력해야겠다고 생각하였습니다.

 

 

두 번째는 리팩토링할 때는 과도기적인 코드가 있어야 한다는 것입니다. 이것이 무슨 말이냐면, 리팩토링하고 싶은 메소드가 있다면, 거기서 바로 수정하지 말고 따로 복붙을 해 와서 수정을 해 보라는 것입니다. 컴파일 에러가 발생하면 테스트를 제대로 할 수 없으므로, 최소한 테스트는 할 수 있도록 코드를 수정하는 것이 중요하다는 의미죠.

 

저는 수정할 코드를 바로 고쳐서 컴파일 에러가 발생하면 바로 바로 변경하는 편이었는데, 곰곰히 생각해 보니 이 방법을 하다가 맞지 않다는 것을 깨달으면 다시 원상태로 돌려놓는 것이 귀찮았습니다. 앞으로 과도기적인 코드를 작성하여 리팩토링하도록 해야겠습니다.

 

 

마지막으로 캐싱입니다. 우테코 과정을 따라오면서 불변 객체의 장점을 느끼고 있는데, 한 가지 단점이 있다면, new 키워드를 통해 이 객체를 많이 생성한다면 성능이 느려진다는 것입니다. 그리고 포비는 이에 대한 해결책으로 캐싱을 제시하였습니다.

 

이번 로또 미션을 예로 들면, 로또의 숫자가 1부터 45까지이므로 "로또 숫자"를 불변 객체로 만들어서 미리 1부터 45까지 "로또 숫자" 객체를 만들어 두는 것입니다. 아래 코드를 보면 이해가 빠르실 겁니다.

 

 

    private static final int LOTTO_MIN_NUMBER = 1;
    private static final int LOTTO_MAX_NUMBER = 45;
    public static final String OUT_RANGE_NUMBER_ERROR_MESSAGE = "범위가 초과된 숫자 입력입니다.";

    private static final Map<Integer, LottoNumber> lottoNumbers = new HashMap<>();
    private final int number;

    static {
        for (int i = LOTTO_MIN_NUMBER; i <= LOTTO_MAX_NUMBER; i++) {
            lottoNumbers.put(i, new LottoNumber(i));
        }
    }

    private LottoNumber(final int number) {
        this.number = number;
    }

    public static LottoNumber from(int number) {
        if (!lottoNumbers.containsKey(number)) {
            throw new IllegalArgumentException(OUT_RANGE_NUMBER_ERROR_MESSAGE);
        }
        return lottoNumbers.get(number);
    }

 

 

이렇게 해쉬맵을 사용하여 사전의 "로또 숫자" 객체를 만들어 놓고, 필요할 때마다 꺼내 쓰는 것입니다. 물론, 범위가 over된다면 예외를 발생시키는 것이죠. 이것은 45개의 데이터만 필요하므로 성능 면으로도 뛰어나다는 장점이 있습니다.

 

 

로또 미션 2단계 1차 피드백

피드백 내용 자체는 많지 않았습니다.

 

 

 

 

 

 

첫 번째는 LottoService에 있는 로직을 LottoRepository로 옮기는 것입니다. 사실, 이 외에도 LottoService의 필요성이 점점 떨어져서 여기 있는 로직을 분산시켰습니다. 로또를 긁는 로직을 LottoRepository로, 수익률을 구하는 것은 EarningRate 클래스로 분리하였습니다.

 

 

그 외에 LottoRepository라는 이름 대신 Lotteries로 수정하였습니다. 왜냐하면, 나중에 웹을 공부할 때 Repository 레이어라는 것이 있어서 혼동의 여지가 있음을 알게 되었기 때문이죠. 데이브는 추가적으로 무언가가 복수 개 있다고 저장소라는 네이밍을 쓰는 것은 피하는 편이 좋다고 조언해 주셨습니다.

 

 

 

 

 

 

마지막으로 수동 구매로 인해 늘어난 구조를 바로 잡는 것입니다. 처음에 데이브가 올려주신 코드대로 TicketCreator을 상속받는 자동 구매, 수동 구매, 기타 구매 객체로 분리해 보았습니다. 여기서 공통 메소드로는, 로또를 생성하는 generate()라고 판단하였고, TicketCreator 인퍼테이스를 만들었습니다.

 

하지만, 자동 구매의 경우 Lotteries와 티켓의 개수를 인자로 받아와야 하고, 수동 구매의 경우 Lotteries와 수동 입력한 Lotto 객체를 인자로 받아와야 합니다. 즉, 메소드명은 같을지라도 인자는 달라서 이를 인터페이스로 정의할 수가 없었습니다.

 

그렇다고, TicketCreator을 클래스로 생성하여 하위 클래스를 상속해 주려고 하니까, TicketCreator을 무엇으로 정의할 지가 애매하여 철회하였습니다.

 

또한, for문 내에서 로또를 생성하고 생성한 로또 수 만큼 counter를 빼는 것도 문제가 있었습니다. 바로, 수동 구매는 사용자의 입력이 선행되어야 하므로 for문 안의 부득이하게 if문이 생긴다는 것이죠. 현재는 자동 구매와 수동 구매 2개밖에 없으므로 이 방법이 괜찮을지 모르곘는데, 나중에 제3, 제4의 구매 방법이 생긴다면 for문 내의 if문이 늘어나는 문제가 발생합니다.

 

그래서 위 두 가지 사항을 들어서 데이브에게 DM을 보내 보았더니, 같이 주말 동안 다시 생각해 보자는 답변이 들어왔습니다. 저도 이 고민은 주말에 걸쳐서 계속 해 보려고 합니다.

 

 

여담으로, Ticket 객체 안에 전체 가능한 티켓 개수와 수동 구매한 개수를 멤버 변수로 지정하는 것도 고민해 봤는데, 구조는 깔끔하더라도 제3, 제4의 구매 방식이 생긴다면 유지 보수가 그렇게 좋아 보이지는 않았습니다. 그래도 다음 주 미션 전까지 명쾌한 구조가 떠오르지 않는다면 이 구조로 작성하려고 합니다.

 

 

정리

오늘은 포비의 명강의를 듣고, 로또 미션 피드백을 반영하는 데 시간을 쏟았습니다. 비록, 티켓 구매와 관련하여 이쁜 추상화 구조는 잡지 못하였지만 다양한 구조를 고민해 보는 유익한 시간이었다고 생각합니다.

 

내일은 우테코 기간동안 지낼 방을 찾으러 발품 팔아야하는데, 부디 원하는 방이 있었으면 좋겠습니다.

댓글

추천 글