[우아한테크코스 4기] Level 1 4일차 회고

Jihoon Oh·2022년 2월 12일
0

화요일부터 시작한 우테코가 어느새 벌써 4일차. 오전에는 강의가 있고, 오후에는 페어 프로그래밍을 마무리하고 최종적으로 1차 PR을 마무리하는 시간이 있었다. 금요일에는 포수타(포비의 수다 타임...? 뭐 그런 이름이었던 것 같은데...)가 있다고 했지만, 첫 주는 페어 프로그래밍을 할 시간이 적었으므로 오늘은 포수타가 아닌 페어 프로그래밍 마무리를 하는 시간을 주는 듯 했다.

TDD 강의

데일리 미팅이 끝나고 10시 반부터는 네오의 TDD(Test Driven Development: 테스트 주도 개발) 강의가 있었다. 강의는 한시간 반 정도 진행됐는데, 사실 TDD 자체가 그냥 키워드로 아 그런게 있구나 하고 듣기만 했지 학생 때 한 번도 해본 적이 없었던 개발 방식이었어서 생소했다. 그나마 학교 프로젝트나 토이 프로젝트를 할 때 테스트 코드를 꼬박꼬박 쓰기는 했던 것 같은데, TDD는 단순히 테스트 코드를 쓴다고 TDD인 것이 아니었다.

TDD 자체를 깊게 설명하자면 워낙 길 것 같아서, 이 부분은 따로 강의 녹화본을 돌려보면서 정리 하려고 하고, 간단하게 설명하자면 실패하는 테스트 코드를 먼저 작성하고 그 테스트코드가 성공하도록 프로덕션 코드를 작성하는 방식이라고 할 수 있을 것 같다. 즉, 내가 기존에 개발하던 방식이

설계 -> 프로덕션 코드 작성 -> 테스트 코드 작성 -> 테스트 실행 -> 프로덕션 코드 리팩토링

의 과정을 거쳤다면, TDD 방법론을 채택하면

설계 -> 설계에 맞는 테스트 코드 작성 -> 테스트 실패
-> 테스트가 성공하도록 프로덕션 코드 작성 -> 모든 테스트 성공 -> 프로덕션 코드 리팩토링 

의 과정을 거치게 된다고 볼 수 있다.

나는 여태까지 내가 의도한 프로덕션 코드의 동작과 값을 테스트하는 용도로 테스트 코드를 사용했었는데, 그게 아니라 설계에 맞는 테스트 코드를 작성해서 테스트 실패를 하고(당연히 프로덕션 코드가 없으니까 처음에는 테스트 실패) 테스트 코드가 일단 성공하도록 프로덕션 코드를 작성해나간 뒤 모든 테스트가 성공하면 프로덕션 코드를 리팩토링 한다는 점에서 달랐다.

페어 프로그래밍을 하면서도 최대한 TDD 방법론을 채택해보려고 했는데, 사실 초반부에 작은 도메인 단위에서는 그럭저럭 잘 해나간 것 같은데 조금만 규모가 커지거나 코드가 복잡해져도 프로덕션 코드 없이 어떻게 테스트를 작성해야 할 지 막막했다. 아직은 프로덕션 코드를 바탕으로 테스트를 작성하는 것이 익숙해서 테스트 코드를 바탕으로 프로덕션 코드를 작성한다는 사고 방식이 장착되지 않은 탓이랴.

요즘 굉장히 핫한 방법론이기도 하고, 첫 강의부터 소개할 정도로 우테코에서도 중요하게 여기고 있는 듯 하니 녹화본을 다시 보면서 손에 익을 수 있도록 정리하는 시간을 가질 필요가 있을 듯 싶다.

첫 번째 페어 프로그래밍 끝!

오후에는 연로그와의 페어 프로그래밍을 마무리지었다. 프로덕션 코드의 로직을 크게 변경한 부분은 없었고, 어제 페어 프로그래밍을 마치고 서로 개인적으로 생각해 본 부분들과 오전에 TDD 강의를 들으면서 생각난 부분들을 가지고 이야기를 나누어보았다.

내가 어제 코드를 보면서 제일 신경쓰였던 부분은, 다른 validate 메소드들은 void 형으로 검증에 실패했을 때 IllegalArgumentException을 던지는 형태였다면, Cars 클래스의 validateDuplicatedName 메소드는

private boolean validateDuplicatedName(String[] carNames) {
    long distinctSize = Arrays.stream(carNames)
        .distinct().count();
        
    return distinctSize != carNames.length;
}

로 boolean 값을 던져서 상위 메소드에서 그 boolean 값을 가지고 처리를 해준다는 점이었다. 초반에 코드를 짤 때는 검증 시에 boolean 값을 던지도록 작성을 했다가 리팩토링을 미처 하지 못하고 넘어간 부분이었는데, 코드의 일관성을 위해서 이 부분을 수정해야 한다는 생각이 들었고 연로그도 동의해서 다음과 같이 수정했다.

public void validateDuplicatedName(String[] carNames) {
    long distinctSize = Arrays.stream(carNames)
            .distinct().count();
    if (distinctSize != carNames.length) {
        throw new IllegalArgumentException(ErrorMessages.DUPLICATED_NAME);
    }

그 외에 수정한 부분으로는, 우승자를 구할 때 참가자들 중 가장 먼 거리를 이동한 참가자의 위치를 구하는 getMaxPosition() 메소드를 수정했다. 원래 코드는

private int getMaxPosition(List<Car> cars) {
    int max = Integer.MIN_VALUE;
    for (Car car : cars) {
        max = Math.max(max, car.getPosition());
    }
    return max;
}

였는데, 인스턴스 변수인 max를 쓰지 않고 구할 수는 없을까 생각해 보다가 stream 메소드 중에 max() 메소드가 생각나서 연로그에게 스트림을 사용하는 방식으로 바꿔보자고 물어보았다. 고려할 부분은 max()가 Optional을 반환한다는 점인데, 나는 어차피 최소한 0 값이라도 나올테니까 예외 처리에 의미가 없다고 생각해서 get()을 그냥 쓰거나 orElseThrow()에 인자를 집어넣지 않고 쓰는게 어떨까 라고 했는데, 연로그가 그러면 그냥 orElse()로 0을 반환하는 것이 어떻겠냐는 의견을 제시해서 결과적으로는 다음과 같은 코드가 되었다.

private int getMaxPosition(List<Car> cars) {
    return cars.stream()
            .mapToInt(Car::getPosition)
            .max()
            .orElse(MIN_POSITION); // MIN_POSITION = 0
}

정리하고 나니까 훨씬 깔끔한 코드가 되었다고 생각한다.

그 뒤로 몇 가지 의견을 더 나누어 보았으나, 딱히 리팩토링 할만한 부분은 없다고 생각해서 페어를 끝내고, 각자 담당 리뷰어 분께 Pull Request를 요청하고 리뷰를 요청했다. (3일동안 페어 하느라 수고 많았습니다 연로그!) 이제 자동차 레이싱 미션의 남은 기간은 페어가 아닌 나 혼자서 리뷰어분께 코드 리뷰 요청을 하고 피드백을 받아서 수정하는 과정을 반복하게 된다.

팀 프로젝트 - 보이는 라디오

어느정도 휴식을 취한 이후에, 저녁 8시 반이 되어서 zoom으로 보이는 라디오 15조 회의를 가졌다. 첫 회의때는 컨셉, 주제, 시놉시스만 정했기 때문에 이번 회의에서는 대본을 쓰고 역할을 나누는 과정을 거쳤다. 우리 조는 올바른 협업에 대한 자세 라는 주제를 정했고, 주제를 녹여내기 위한 컨셉으로는 한 때 유튜브에서 컬트적인 인기를 끌었던 "가짜사나이" 컨셉을 채용하기로 결정했다. 아무래도 관련된 밈이나 명대사가 많은 만큼 여러가지 조건을 만족하기 좋겠다는 판단에서였다. (그런데 컨셉 제안을 내가 해서 그런지는 몰라도 내가 가짜사나이에서의 이근 대위 역할을 맡게 됐다...)

마침 작년인가 재작년인가 블라인드에 누가 가짜사나이를 패러디한 가짜개발자 라는 유머글을 올렸어서, 거기서 대사를 몇 개 따와서 우리 아이디어와 섞었다. 처음엔 시나리오를 잘 쓸 수 있을까 걱정했는데, 막상 8명이 모여서 시나리오를 쓰고 보니까 꽤나 웃긴 시나리오가 나왔다. (당일날 다른 크루들이 잘 웃어줘야 할텐데...)

시나리오 관련해서 봉착했던 난관은 4~5분이라는 시간 제한이었다. 처음에 4~5분이라는 제한 시간을 들었을 때 '5분은 너무 짧지 않나?' 라는 생각을 했었는데, 정작 시나리오를 쓰고, 역할을 정한 뒤 대본 리딩을 하고 나니까 최소 시간인 4분에 한참 모자랐다. 아무리 배경 바꾸고 하는 데 시간이 소요된다고 해도 분량이 모자라서 결국 시나리오에 대사를 추가해서 해결했다. 그 과정에서 크루들의 온갖 드립이 나와서 원없이 웃은 것 같다. 대본 리딩에서의 웃참 실패는 덤이랄까.


(신상 보호를 위해 다른 분들의 얼굴은 가려드렸습니다)

배경까지 맞춰가면서 연습했는데, 솔직히 뭐랄까... 킹받는다. 그래도 뭔가 좋은 결과물이 나올 것 같고, 연습만으로도 재밌는 회의였다. 회의가 끝나고는 팀원들이 다들 안자고 새벽 1시까지 수다를 떠느라 시간 가는 줄을 몰랐다. 다른 팀들은 6인인데 우리 팀은 8인이어서, 현재 거리두기 제한인 6인에 걸려서 실제로는 만나지 못한다는 점을 다들 아쉬워했다. 그래서 결국 (내 주도로) 다음주에 랜선 술자리를 가지기로 결정. 미팅을 마무리지었다.

우테코 첫 주말

이제 우테코 첫 주말이다. 아마 주말이지만 쉬지는 못할 듯 하다. 코드 리뷰 답변이 오면 그에 맞춰서 리팩토링을 고민해보고, 코드를 수정해야 하기 때문이다. 음, 주말까지 공부했던 적이 언제인지는 모르겠는데, 어쨌든 주말에도 공부를 할 생각을 하니 막막하기도 하면서 한편으로는 열심히 사는 것 같아서 기분은 좋다.

profile
Backend Developeer

0개의 댓글