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

Glen·2023년 6월 4일
0

회고

목록 보기
15/25

5월 30일 화요일

장바구니 미션 페어 프로그래밍 🧺

장바구니 협업 미션은 0, 1, 2단계로 구분 되어있다.

우테코 미션은 1단계까지 페어와 진행하고, 2단계부터는 따로 구현한다.

이번 장바구니 협업 미션도 마찬가지이다.

하지만 이번 미션이 레벨2 마지막 미션이기도 하고, 다른 과정의 크루와 처음으로 협업을 진행하는 미션이라 2단계까지 페어와 같이 진행을 해보기로 했다.

마치 권위에 도전하는 반란군처럼 💪

이전 지하철 미션을 하며 제일 크게 아쉬웠던 것은 서로 설계에 관해 얘기하며, 같이 작업할 수 있는 시간이 무척 짧다는 것이다.

페어 프로그래밍은 정말 좋다고 생각하는데, 함께 할 수 있는 시간이 너무 짧다.

길어 봤자, 3일이 전부라 설계만 하는데도 시간이 빠르게 지나가서 구현할 수 있는 시간이 없다.

그래서 이번엔 그냥 2단계까지 페어와 구현을 했다.

월요일이 대체 공휴일이라, 쉬는 날인데 불구하고 페어와 같이 캠퍼스로 등교해서 열심히 작업했다.

화요일엔 오전에 이전 페어와 지하철 미션의 학습로그 말하기를 하고, 오후부터 장바구니 미션을 페어와 하기로 했는데, 여러 일정이 있어 1~2시간 정도밖에 하지 못했다. 😂

수요일까지 구현하기로 한 기능을 완성하려면 오늘 주문 기능을 마무리해야 했지만, 협업하는 안드로이드 크루분들이 일정 때문에 목요일로 하기로 미뤄져 오늘은 여유롭게 보내고 내일마저 마무리하기로 했다.

5월 31일 수요일

장바구니 미션 태워버리기 🔥

30일부터 백엔드 과정은 강의가 없어서, 남은 시간 전부는 자습 시간이다.

그래서 오전부터 쭉 페어와 미션을 수행했다.

지하철 미션을 구현할 때 비즈니스 로직을 대부분 서비스 계층에 구현했는데, 이번 미션에선 성능 따윈 개나 줘 버리고 도메인에 최대한 비즈니스 로직을 가지게 했다.

객체가 어떤 기능을 수행하려면, 자신의 상태를 완벽하게 가지고 있어야 한다.

예를 들어, 주문 객체는 여러 주문 목록을 가지고 있다.

주문 목록은 상품과 수량이 포함된다.

UI에서 주문 목록을 보여줄 때, 주문 목록의 가격의 합을 보여줘야 한다.

이때 여러 방식으로 구현이 가능하다.

단순히 데이터베이스에서 모든 상품 목록의 가격의 합을 구해 저장한 뒤, 꺼낸 뒤 반환하면 된다.

SELECT SUM(order_items.price) AS total_price 
FROM orders 
JOIN order_items ON orders.id = order_items.order_id 
WHERE orders.id = :orderId;

하지만 이것은 전혀 객체 지향적인 설계가 아니다.

주문의 총합 가격은 주문 목록이 가지고 있는 가격을 전부 더하면 된다.

주문 목록의 가격을 구하는 방법은 다음과 같이 할 수 있다.

public long calculateTotalPrice() {
    return orderItems.stream()  
    .mapToLong(OrderItem::getPrice)  
    .sum();
}

하지만 이 경우 문제가 생긴다.

객체 지향적인 설계에 따라 총합 주문 가격을 구하려면, 정상적인 상태의 List<OrderItem> 객체가 있어야 한다.

다시 말해, 주문의 총합 가격을 구하려면 DB에 조회 쿼리가 주문에 대한 1번이 아닌, 주문 목록에 대한 N번의 쿼리로 조회해야한다.

데이터 중심의 설계를 따르면 OrderItem 객체를 모두 가져올 필요가 없다. 한 번의 쿼리로 조회할 수 있다.

성능을 챙긴다면 이 방법이 합당해 보인다.

하지만 데이터 중심적인 설계의 문제점은 테스트 코드를 작성할 때 시작된다.

도메인에 비즈니스 로직이 있다면, 테스트 코드를 작성할 때 전혀 데이터베이스나 외부의 자원에 대한 의존 없이 테스트 코드를 작성할 수 있다.

하지만 비즈니스 로직이 외부에 있고, 데이터베이스를 의존하게 된다면 테스트 코드 또한 외부 자원에 대한 의존을 갖게 되어 테스트 코드 작성이 매우 힘들고 불편하다.

결론적으로 프로젝트의 핵심이라고 할 수 있는 도메인과 비즈니스 로직들이 변하기 쉬운 외부 자원에 영향을 받는 것이다.

그래서 이번엔 최대한 도메인에 비즈니스 로직을 구현하려고 했다.

즉, 서비스 레이어는 단순히 도메인을 리포지터리 계층에서 꺼낸 뒤, 도메인에 메시지를 전달하는 역할만 수행한다.

쓰다 보니 너무 기술적인 얘기만 해버렸다. 🤔

결론은 열심히 고민하고 설계했다.

조금? 일상적인 얘기를 하자면 오전에 데일리 미팅에서 마피아 게임을 했는데, 내가 경찰로 지목됐다.

이전까지 마피아 게임을 하며 한 번도 시민이 이긴 적 없었는데, 끝까지 살아남으며 모든 인원의 정체를 파악한 덕분에 처음으로 시민의 승리로 이끌었다. ㅋㅋㅋ

그리고 저녁에도 마피아 게임을 또 했는데, 이번엔 마피아 역할로 지목됐다.

갈고 닦았던 권모술수를 바탕으로 최후의 3인까지 살아남아, 최종적으로 마피아의 승리로 만들었다. ㅋㅋㅋㅋㅋ

내일까지 주문 기능을 완성해야 하므로, 간만에 23시까지 캠퍼스에 남아있었다.

완성은 22시쯤 했지만, 이왕 남은 거 23시까지 마무리했다.

레벨1 미션에선 구현하는데 바빠서 설계에 큰 신경을 쓰지 않았는데, 이제 언어에 익숙해지고 나서부터 설계에 신경을 쓰는 것 같다.

설계 때문에 머리가 아프지만, 그만큼 설계에 신경이 쓰인다는 것은 새로 겪는 성장통이 아닐까 싶다.

설계에 익숙해지면 또 무엇이 나를 기다리고 있을지 기대도 되고 걱정도 된다. 😂

6월 1일 목요일

선릉 출장 🏙

지난주에 협업을 하는 안드로이드 크루분들이 잠실에 와서, 이번엔 우리가 선릉으로 갔다.

우리 말고도 선릉에 가는 크루들이 꽤 있어서, 다 같이 선릉으로 우르르 이동했다.

선릉 캠퍼스는 최종 코테를 볼때 처음 와봤는데, 그때를 생각하면 아직도 아찔하다. ㅋㅋㅋㅋㅋㅋ

그 이후엔 주말에 몇 번 와본 적이 있다.

내부 시설은 확실히 잠실캠이 더 좋은 것 같다.

선릉캠은 컨셉이 우주선 컨셉이라 분위기가 차갑고 조금 답답한 느낌이라면, 잠실캠은 더 초록초록하고 따뜻한 분위기라 심신에 안정감이 있다.

거리는 선릉캠이 더 가깝긴 해도, 나는 조금 더 가서라도 잠실캠을 갈 것 같다. 😂

점심은 안드로이드 크루분들이 안내해 준 백소정에 가서 돈까스를 먹었다.

후식으로 커피는 로스터리 락온에 가서 콜드브루를 마셨다.

선릉은 거의 가본 적이 없어서 괜찮은 식당과 카페를 잘 모르는데, 덕분에 좋은 식당과 카페 정보를 습득했다.

좋은 카페를 생각하니 이번에 레벨3 기획서를 제출한 게 생각난다.

커피를 주제로 기획서를 작성했는데, 집에서 커피를 내려 마실 때마다 항상 고민이 드는 게 커피 원두이다.

커피 원두는 종류가 무척 많다.

원두는 각자 개성이 다르고, 커피를 내릴 때 방법도 달라진다.

그래서 새로운 원두를 사면, 그에 따라 추출 세팅을 다시 해야 한다. 😂

이런 불편을 느껴, 원두의 특색을 기록해 두고 공유하는 플랫폼을 기획했다.

이미 공개된 서비스들이 많지만, 추출 세팅들을 공유하는 플랫폼은 찾기 힘들었다.

그래서인지 조금이나마 경쟁력 있는 서비스가 되지 않을까 싶다.

지금은 에스프레소 머신으로 커피를 마시지만, 지금은 또 드립커피에 욕심이 생긴다.

다음 달에 생활비가 들어오면, 핸드밀과 드립커피 용품을 사서 드립으로 마셔봐야겠다. ☕️

다시 본론으로 돌아가서, 안드로이드 크루분들과 완성한 기능들을 시연하고, 새로 구현해야 할 것이 있는지 회의했다.

주문 목록을 보여줄 때 상품의 이름이 나오지 않아서, 첫 번째 구매한 상품의 이름과 구매한 상품이 여러 개이면 외 2개 같이 보여줄 필요가 있었다.

만약 이번 미션을 데이터 중심적으로 설계했다면 기존의 코드를 고려하고, 수정할 부분이 많았을 것이다.

하지만 비즈니스 로직을 도메인 객체에서 구현했기 때문에 기존의 코드를 건드리지 않고 단순히 다음과 같이 구현할 수 있었다.

class Order {
    ...
    
    public String getFirstProductName() {  
        return orderItems.stream()  
            .map(OrderItem::getProduct)  
            .map(Product::getName)  
            .findFirst()  
            .orElseThrow(() -> new IllegalOrderException("해당 주문 상품을 찾을 수 없습니다."));  
    }

    public int getOrderItemCount() {  
        return orderItems.size();  
    }
}

좋은 설계란, 단순히 설계했을 때 쉽게 알 수 없지만, 추후 변경 사항이 생겼을 때 확실하게 체감할 수 있다.

우리가 구현한 설계가 완벽한 설계는 아니지만, 좋은 설계임을 느끼게 되었다.

그렇게 18시까지 부족했던 테스트 코드를 작성하고 빠르게 칼퇴했다.

원래 오늘까지 제출하고 싶었는데 생각보다 늦어졌다. 😂

내일은 제출할 수 있도록 해봐야지...

6월 2일 금요일

협업 미션 마무리 🎬

드디어 협업 미션을 마무리 지었다.

처음엔 생각보다 할 게 없어 걱정도 안 하고 그냥 멍하게 보냈다.

하지만 2단계에 API 명세와 추가 기능 구현에 따라 무지막지하게 할 게 생겨버렸다. 😂

오전 데일리 미팅에서는 skribbl라고 하는 웹으로 할 수 있는 캐치마인드를 했다.

그리고 어릴때 부터 단련된 캐치마인드 실력으로 1등을 했다 ㅋㅋㅋㅋㅋ

사실 뽀록이 많이 터지긴 했지만... ㅋㅋㅋㅋㅋ

11시부터 다시 페어와 만나 간단하게 코드를 리팩터링 하고, 점심을 먹으러 갔다.

원래 친구가 잠실로 온다고 해서 친구와 먹기로 했는데, 이 녀석이 갑자기 당일 파토를 내는 바람에 졸지에 낙동강 오리알이 되어버렸다.

아무튼 점심을 따로 먹는 크루들을 모아서 무한으로 제공되는 오한수 우육면가에 가서 우육면을 먹었다.

그리고 우육면 집 바로 옆에 푸가라고 하는 에스프레소 바가 있는데, 커피를 기가 막하게 잘하는 집인지 지하상가에 있는 조만한 커피집에 20명 정도 줄을 서고 있었다.

그래서 얼마나 커피를 잘하는지 궁금해서 나도 기다려서 마셔봤다.

인기가 많은 이유를 알 것 같은 게, 정말 좋은 커피 그라인더를 사용하고(ek43), 에스프레소 바라고 하기 뭐한 게 드립 커피를 주력으로 하는데, 드립 커피가 겨우 3500원 밖에 하지 않는다.

원두에 따라 추가적인 요금을 받기는 하지만, 이 가격에 이 맛의 드립 커피라니...

다시 한번 드립커피 용품을 마련하고 싶은 욕심이 불타올랐다. 🔥

물론, 산미를 좋아하지 않는다면 그냥 에스프레소를 마실 것을 권장한다. ㅋㅋㅋ

캠퍼스로 돌아와서, 이번 협업 미션에 대해 회고 시간을 가졌다.

같이 미션을 구현한 페어인 그레이와는 붙어 있는 시간이 많아 회고할 얘기가 많았는데, 협업을 같이한 안드로이드 크루분들과는 붙어 있던 시간이 그렇게 많지 않아 크게 얘기할 거리가 없었다.

작성해야 할 목록은 많은데.. 이야기를 지어낼 수도 없는 노릇이라 매우 힘들었다. 😂

그래도 이렇게 다 같이 모여 회고하는 시간을 가지니, 내가 어떤 점이 부족했었고 어떤 점을 잘했는지 알 수 있었다.

같이 일하고 싶은 사람이 되도록 노력해야겠다는 다짐을 다시 하게 만든다.

미션은 완성했지만, 아직 리팩터링 하고 싶은 부분이 있어 저녁까지 남아있었다.

하지만, 이미 API 명세가 만들어졌고 협업하는 크루들이 그것을 사용하고 있기 때문에 1시간 정도 작성했던 코드를 다시 지울 수밖에 없었다. 😭

설계가 이래서 정말 중요하구나...

이번 주는 월요일이 공휴일이라 빠르게 한 주가 지나갔다.

다음 주도 화요일이 공휴일이고, 수요일, 목요일이 레벨 인터뷰를 하는 날이라 사실상 하루만 캠퍼스에 나오면 된다.

레벨2를 처음 시작했던 날이 저번 주 같은데... 시간이 정말 빠르게 흘러갔다.

레벨2 기간 동안 무언가를 배운 것은 정말 많지만, 레벨 인터뷰 때 그것을 말할 정도로 배웠다고 할 수 있을지는 모르겠다.

다음 주에는 레벨 인터뷰를 대비해서 내가 무엇을 배웠는지 정리해 보는 시간을 가져봐야겠다.

끝.

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

0개의 댓글