[우아한테크코스 5기] 레벨 1 - 5주차 회고

Glen·2023년 3월 12일
0

회고

목록 보기
5/25

3월 6일 월요일

오늘은 월요일이라 늦게 등교하는 날이다.
오늘 데일리 미팅에서 조원들끼리 마니또를 하기로 했다.
나의 마니또는 연어였는데 연어의 소원은 공부할 자리 맡아주기였다.
과연 안 들키고 자리를 맡아 줄 수 있을지 모르겠다. ㅋㅋ

그 후 간단히 데일리 미팅을 끝내고 오늘 블랙잭 미션의 피드백이 와서 간단히 피드백을 반영하고 하루를 끝냈다.

그리고 레벨1 조원인 제이, 엔델, 연어 그리고 다른 크루인 필립과 간단히 저녁에 건대입구에 있는 코젤 다크 하우스에서 맥주를 마시고 헤어졌다.

나는 술을 좋아하는데, 최근엔 위스키를 자주 마신다. 그 전엔 맥주를 자주 마셨는데 간만에 좋아하던 맥주를 마시니 기분이 굉장히 좋아졌다. ㅋㅋㅋ
역시 인생의 즐거움은 알코올에서 나오지 않을까

3월 7일 화요일

오늘은 블랙잭 미션 피드백 강의가 있는 날이다.
강의 내용 중 캐싱에 관한 얘기가 있었다.
블랙잭 미션의 도메인 중 하나인 Card는 필드로 Rank, Suit를 가지는데, 이때 Rank, Suit는 열거형이고 내부의 상태가 변하지 않고 생성할 갯수(모든 플레잉 카드의 합인 52개)가 정해져 있어, 미리 모든 Card의 인스턴스를 어딘가 저장해두고 new로 인스턴스를 생성할 필요 없이 기존의 생성된 인스턴스를 재활용하면 성능상 이점을 누릴 수 있다.

내가 구현했던 방식은 이랬다.

private static final Map<Suit, Map<Rank, Card>> CACHE;

static {
	CACHE = Rank.stream()
        .flatMap(rank -> Suit.stream()
                .map(suit -> new Card(suit, rank))
        ).collect(groupingBy(card -> card.suit,
                toMap(card -> card.rank, card -> card)));
}

// private 생성자

public static Card of(Suit suit, Rank rank) {
    return CACHE.get(suit).get(rank);
}

지금 로직은 Map 내부에 또 Map을 사용하여 Card를 가져올 때 get을 2번 호출해야 했다.
따라서 이 부분을

private static final Map<Integer, Card> CACHE;

static {
    CACHE = Rank.stream()
            .flatMap(rank -> Suit.stream()
                    .map(suit -> new Card(suit, rank))
            ).collect(toMap(Card::hashCode, Function.identity()));
}

public static Card of(Suit suit, Rank rank) {
    return CACHE.get(Objects.hash(suit, rank));
}

이렇게 key로 hashCode를 사용하여 내부 로직을 더 깔끔하게 만들었다!
이때 필드가 2개 이상일 때 Map의 key를 사용하는 여러 가지 방법이 있는데,
1. Map 내부에 Map을 두어 찾기
2. hashCode로 key를 만들기
3. 문자열로 key를 만들기 (SQL의 슈퍼키와 유사)
강의에서는 3번의 방법을 사용했는데, 나는 2번을 사용했다.
추후 시간이 된다면 해당 방법들의 장단점을 정리해봐야겠다.

그리고 블랙잭 미션 피드백을 반영하고 제출을 다시 했다.
빨리 머지가 돼서 2단계를 구현하고 싶다.. ㅋㅋㅋ
글쓰기 미션도 해야 하는데 코딩하는 게 100만 배 더 재밌는 것 같다.

그리고 지난주 금요일에 산 소프트웨어 장인을 이번 주 내로 다 읽어볼 생각이다. (벌써 절반 정도 읽었다!)

저녁엔 용인에 사는 친구한테 놀러 가 고기와 커피를 얻어 마시고 가지고 있던 이마트 상품권 3만 원어치를 전부 맥주에 flex 해버렸다.
당분간 맥주 신나게 마실 수 있을 것 같다. ㅋㅋㅋ

3월 8일 수요일

오늘 드디어 블랙잭 미션 1단계가 머지가 됐다!!!
하지만 그만큼 어마한 피드백을 받았는데 다른 건 어떻게 한다 해도 Service 계층을 없애고, Controller에 로직을 위임하라는 피드백이 있어 이걸 다시 어떻게 리팩터링 해야하나.. 깊은 고뇌에 빠졌다.
원래 Controller에 로직이 많아 Service 계층을 만들고 사용한건데.. 😂
그래도 다시 코딩할 일이 생겨 기분이 좋다!

그리고 오늘 점심은 롯데월드몰에 가서 레벨1 조원들과 식사했는데, 이유가 마니또에서 내가 적은 소원이 롯데월드타워 같이가기 였기 때문이다. ㅋㅋㅋ
롯데월드몰은 롯데월드타워가 아니긴 한데, 그래도.. 인정 ㅋㅋㅋ

우테코에 와서 어릴 때 하던 여러 가지 활동을 다 큰 성인이 돼서 하는데 기분이 좀 묘하다 ㅋㅋ 다시 어릴 때로 돌아간 기분

그 뒤 캠퍼스에서 Service 로직을 어떻게 Controller에 다시 옮기지라는 고민만 하다, 지금 상태로 답이 나올 것 같지 않아 그냥 책을 좀 읽다가 다른 크루들과 잡담만 한 것 같다.

그리고 Mermaid에 관해 크루들과 얘기가 나왔는데 나도 이번 블랙잭 미션에 시범 삼아 적용해보고, 사용이 편하고 효과가 좋으면 쭉 사용해볼 예정이다.

3월 9일 목요일

오늘 새벽 1시까지 열심히 코딩하고 블랙잭 미션 2단계 기능을 완성한 뒤 PR을 보내고 자고 일어났다.
기존에 구조를 잘 작성해둬서 기능 요구 사항이 변경되더라도 기존 코드를 크게 변경한 부분이 없이 2단계 기능 구현이 쉽게 완성되었다!

다만 한 가지 걸리는 점은 열거형인 GameResult에 로직을 추가한 것인데

GameResult

WIN("승", IntUnaryOperator.identity()),
LOSE("패", money -> -money),
DRAW("무", money -> 0),
BLACKJACK("블랙잭", money -> (int) (money * 1.5));

public int applyBet(int money) {
    return intUnaryOperator.applyAsInt(money);
}

Bet

public Bet calculateResult(GameResult gameResult) {
    return new Bet(gameResult.applyBet(bet));
}

Player

public Bet matchGameWithBet(Dealer dealer) {
    GameResult gameResult = matchGame(dealer);
    return bet.calculateResult(gameResult);
}

와 같이 Player가 Dealer와의 게임 결과에 따라 배팅금을 다시 반환하는 구조로 설계했다.

나름대로 기존의 코드를 크게 변경하지 않고 기능을 구현했다고 생각은 하는데, 과연 좋은 방법인진 잘 모르겠다. 😂 빨리 리뷰가 왔으면...

오늘도 강의는 없고 이미 피드백은 제출한 상태라 할게 크게 없어 어제와 같이 책을 좀 보다가 다른 크루들과 잡담을 많이 했다.

그리고 오늘 내가 하는 스터디인 회고 모임에서 간단히 오프라인으로 야유회를 진행했다.
가볍게 석촌호수를 한 바퀴 산책하고 뇌 구조 그리기를 하여 서로의 고민과 생각을 공유하고 간단히 자기소개를 했다.

이제 거의 한 달이 지났는데도 아직 온보딩 조원들과 레벨1 조원들 외엔 어색했는데 이번 기회로 다른 크루들과 조금 가까워진 것 같다.

레벨2부터는 다른 스터디에 참가해서 더 많은 크루들과 모임을 했으면 좋겠다는 생각이 든다.

3월 10일 금요일

오늘은 데일리 미팅에서 레벨1에서 목표, 우테코를 수료하는 시점 나의 모습을 이야기 나눴다.
나는 평소에 고민을 많이 하는 편이 아니라 이에 대해 큰 고민을 한 적이 없어서 어려웠었다.

그래도 레벨1에서 목표가 있었다면 지금 이렇게 쓰고 있는 회고나 블로깅이 아닐까
평소에 학습하면 머릿속에만 기억해두고 기록처럼 어딘가 작성을 해본 적이 없다.
있다고 해도 그저 받아쓰기처럼 의미 없이 기록해둔 것이 전부이다.

이전 우테코를 수료했던 사람들과 같이 우테코를 다니고 있는 크루들을 보면 다들 블로그도 열심히 하고, 기록도 틈틈이 해두는 편이라 나는 그게 정말 부럽고 배우고 싶었다.
그래서 내가 생각한 레벨1의 목표는 최소한의 블로깅 능력과 기록을 해둘 수 있는 능력을 기르는 것이다.

그리고 우테코를 수료하는 시점 나의 모습은 남들 앞에서 뻔뻔하게 말할 수 있는 지식을 습득하는 것이 목표이다.

세상에는 정답이 있는 것보다 정답이 없는 문제가 많다.

그러다 보니 사람마다 각각 의견이 다르고 항상 논쟁이 일어난다.

그 속에서 나는 남의 의견에 눈치 보지 않고 나 스스로 옳다고 말 할 수 있는 지식과 능력을 보유하고 싶다.

나의 의견이 당연히 정답은 아니겠지만, 정당성있고 남들이 듣기에도 합리적인 그런 지식과 능력 말이다.

아무튼 그렇다. ㅋㅋ

그리고 블랙잭 미션의 두 번째 피드백 강의가 있었다.
강의에선 상태 패턴을 적용하는 것을 보여줬다.

어제 상태 패턴 테코톡 발표가 있어서 발표를 보고 이번 블랙잭 미션에도 상태 패턴을 사용해보고 싶었는데 강의에서 상태 패턴을 적용하는 모습을 보고 나도 한 번 사용해보기로 했다.

상태 패턴의 구조는 정말 매력적이었는데, 상태 패턴을 구현하고 사용해보려고 하니 구조는 좋아도 적용하기가 정말 힘들었다.
대체 왜 사용을 해야 하지? 싶을 정도로

결국 딜러와 플레이어의 게임 결과를 비교하려면 외부에서 결과를 서로 알아야하고, 비교해야 하는 데 이럴거면 기존의 방식과 크게 차이를 못 느끼는 것과 더불어 오히려 구조가 더 복잡해져 가독성이 떨어지는 것 같았다.

그래서 기존 코드로 다시 돌아왔다. ㅋㅋㅋ

강의에서 디자인 패턴에 대해 한 가지 말이 있었다.
망치를 들고 있으면 모든게 못으로 보인다

내가 자주 하는 말 중 하나이다.

아무리 디자인 패턴이니 기술이 좋다 하더라도, 그것만 생각해버리면 모든 것에 적용하려 하고 숲을 봐야 하는데 나무만 보게되는 느낌이 들게 된다.

과유불급이라는 말이 있듯이, 항상 과한 게 좋지는 않다. 기술이란 항상 필요할 때 적용해야 하고 Silver Bullet은 없다.

저번에 한 번 생각했던 말이지만, 좋은 프로그래머란 규모에 따라 적절한 기술을 사용하는 프로그래머가 좋은 프로그래머가 아닐까?

말이 길었다.

아무튼 이번 주도 무사히 끝났다!

빨리 블랙잭 미션 2단계 피드백을 받고 다음 주에 체스 미션을 하고 싶다.

profile
꾸준히 성장하고 싶은 사람

0개의 댓글