[우테코 6기] 프리코스 1주 차 회고

Hanjmo·2023년 10월 26일
2
post-thumbnail

⚾️ 1주 차 미션

이번 주차의 미션은 숫자 야구 게임을 만드는 것이었다.
숫자 야구는 중고등학생 때부터 대학교, 군대에서까지.. 친구들과 지겹도록 했던 게임이라 룰 자체는 익숙했다.

미션 저장소와 내가 제출한 PR 주소는 아래에 있다.

🎯 1주 차 목표 달성 여부

  • ✅ 살아 있는 기능 목록 작성하기
  • ✅ 나만의 Git 커밋 주기, 메시지 형식 정하기
  • ✅ 이유 없는 코드 작성하지 않기
  • ✅ 요구 사항 모두 만족하기
  • ✅ 프리코스 커뮤니티 열심히 참여하기

📖 학습한 내용

살아 있는 기능 목록 작성하기

지난 팀 프로젝트에서 기능 명세서 초안을 작성했으나, 요구 사항이 수정되었을 때 명세서에 이를 반영하지 않아 많은 어려움이 있었다. 이러한 경험을 떠올리며, 살아 있는 문서를 작성하기 위해 다음과 같은 노력을 했다.

  • 프로그램 실행 과정을 순서도로 나타냈다.
    나는 어떻게 하면 요구 사항 및 전체적인 과정을 명확하게 파악할 수 있을지 고민했다. 기능을 하나라도 놓치는 순간 많이 꼬여버릴 것이 분명했기 때문이다. 작년에 수강한 컴퓨팅 사고라는 교양 수업에서 배운 알고리즘 순서도가 떠올랐고, 이를 활용하기로 했다.
    아래와 같이 draw.io에서 프로그램이 실행되는 일련의 과정을 그려 README에 포함했다.
    baseball flow
    이처럼 실행 흐름도를 그림으로써, 자연스럽게 미션의 전체적인 흐름과 요구 사항을 파악할 수 있었다.

  • 구현해야 할 모든 기능마다 체크박스를 만들었다.
    미션을 중단하고 잠시 다른 곳에 집중했을 때, 다시 돌아와서 미션을 진행하려고 하면 방향을 잃어버리는 문제가 발생할 수 있을 것이라 생각했다. 그래서 나는 하나의 기능을 구현했을 때, 잊지 않고 그 기능에 해당하는 체크박스를 활성화시키려고 노력했다. 그 결과 잠시 다른 일을 하다 와도 전체적인 진행 상황을 쉽게 파악할 수 있게 되었다. 이 방식은 진행 상황을 쉽게 파악할 수 있게 해줄 뿐만 아니라, 내게 작은 성취감을 주어 더 깊이 있게 몰입할 수 있도록 도와주었다.

Git 커밋 단위, 메시지

지금까지 프로젝트를 진행할 때마다 느낌 가는대로 커밋하는 습관을 가지고 있었고, 거기에 메시지는 알아보기 쉽지 않았다. 이를 개선하고자 나만의 Git 커밋 단위와 메시지 포맷을 만들고자 노력했다.

  • 커밋 메시지 형식
    커밋 메시지 형식의 경우 AngularJS Git Commit Message Conventions을 참고하여 type, scope, summary로 분할했다. 이를 통해 커밋 내역을 봤을 때 어떤 파일을 어떤 이유로 수정했는지 명확하게 파악할 수 있었다. 추가로 이모지를 활용해 가독성을 높여볼까도 생각해봤지만, 처음부터 많은 것에 집중하면 정작 중요한 것을 놓칠 수도 있다고 판단해 잠시 내려놓기로 했다.

  • 커밋 주기
    커밋 메시지는 이미 존재하는 컨벤션을 따르면 되기 때문에 어렵지 않았지만, 커밋 주기는 그렇지 않았다... 많은 사람들이 “기능 단위로 커밋하라”라는 말을 하는 것을 봤지만, 내가 느끼기에 “기능 단위로”라는 말은 주관적이고 모호했다. 그래서 다른 사람들의 조언은 뒤로 하고, Git 커밋이 익숙해질 때까지 나만의 리듬을 찾는 것이 중요하다고 생각했다. 따라서 나만의 커밋 규칙을 정했는데, 이는 커밋 시점의 파일을 2개로 제한하는 것이었다. 한 번에 여러 파일을 수정하려고 하면, 그 작업은 여러 개념이나 기능이 복잡하게 얽혀 있는 상황을 의미한다고 판단했기 때문이다. 이러한 규칙을 적용한 덕분에 각 커밋이 독립적인 변화를 나타낼 수 있게 되었다.

Randoms API

랜덤 값을 생성하는 기능을 구현하던 중 문득 우아한테크코스에서 제공하는 Randoms가 어떻게 동작하는 것인지 궁금해졌다. 그래서 Randoms API의 동작 원리를 가볍게 살펴봤다.

java.util.Random을 사용하여 난수를 생성한다는 것은 쉽게 파악했지만, ThreadLocalRandom은 처음 접하는 개념이라 Java 문서와 여러 블로그를 찾아봐야 했다.
얕게나마 찾아본 결과 ThreadLocalRandom은 멀티 스레드 환경에서도 안정적으로 사용할 수 있다는 것을 알 수 있었다.

이 과정을 통해 API에 대해서 깊게 파고들면, 다양한 개념에 대해서 빠르게 학습할 수 있다는 사실을 깨달았다. 왜 다들 공식문서나 API 뜯어보라 하는 건지 조금이나마 알겠음..

아래는 내가 학습한 내용을 정리한 글이다.

https://velog.io/@hjm2530/우테코에서-제공하는-Randoms.pickNumberInRange의-동작-원리에-대해-알아보자

역할과 책임의 분리

컴퓨터의 수를 관리하는 역할을 수행하는 ComputerNumbers의 생성 로직에 대해 정말 많이 고민했다.

처음에는 ComputerNumbers의 생성자에서 숫자를 생성하도록 코드를 작성했다. 이는 ComputerNumbers가 생성되는 시점에 반복문을 돌면서 NumberGenerator가 랜덤 숫자를 생성하고, 이를 List로 변환하는 로직이었다.

하지만 이러한 방식의 숫자 생성은 테스트 코드 작성에 어려움을 주었다. 예를 들어, ComputerNumbers와 플레이어의 수를 관리하는 PlayerNumbers를 비교하는 테스트의 경우 ComputerNumbers는 랜덤 숫자를 가져서는 안된다.

ComputerNumbers에 대한 테스트를 포기해야 하나 싶던 그때, 한 가지 해결책이 떠올랐다. 그것은 역할과 책임을 분리하는 것이었다.
반복문을 돌면서 임의의 3자리 수를 만드는 책임은 새로운 객체 ComputerNumbersGenerator에게 넘겨주고, ComputerNumbers는 그저 ComputerNumbersGenerator가 반환한 List를 받기만 하는 방식으로 코드를 수정했다. 이렇게 함으로써 ComputerNumbers를 테스트할 수 있게 됨과 동시에 역할과 책임 분리의 중요성을 깨닫게 되었다.

물론 랜덤값을 테스트할 수 있도록 테스트 코드를 작성하는 것이 더 좋은 방법이었던 것 같다. 이는 2주차에 다뤄보자.

Map 초기화

볼과 스트라이크를 카운트하는 역할을 수행하는 BallCounter의 경우 Map을 사용하여 볼과 스트라이크의 개수를 관리하도록 작성했다.
각각의 개수를 int 타입으로 관리할 수도 있었지만, 다양한 Collection API를 학습해보고자 Map을 선택했다.

여기서 고민한 부분은 볼과 스트라이크의 초기값을 설정하는 방식이었다. Map을 초기화하는 방식에는 생각보다 많은 방법이 있었고, 각각의 사용법과 장단점에 대해서 학습했다.
하지만 이중에서 딱! 끌리는 방식이 없었다. 나사 하나 풀린채로 Java 공식문서를 살펴보던 중 getOrDefault()라는 메서드를 발견했다.
오아시스를 찾으면 이런 기분일까..?

이를 사용함으로써 Map을 초기화할 필요없이 기본값을 반환하여 훨씬 간결하고 가독성이 좋은 코드를 작성할 수 있게 되었다. 이에 대한 내용은 블로그에 포스팅했다.

https://velog.io/@hjm2530/Map을-초기화하는-다양한-방법과-getOrDefault

객체 설계 과정 공유

객체지향을 클래스 중심으로 학습했던 나는 객체를 설계하는 과정이 낯설었다. 그러나 객체지향의 사실과 오해라는 책을 읽은 후 객체지향의 본질에 대해서 다시 생각할 수 있게 되었고, 객체지향 설계 기법에 대한 감도 잡을 수 있었다.

나처럼 객체지향 설계 기법에 대한 감이 부족한 동료들을 위해 내가 객체를 설계하는 과정에 대해서 공유하고자 블로그에 글을 작성하여 공유했다.

내가 가진 것을 글로 풀어내는 과정에서 기존에 생각하지 못했던 문제를 발견할 수 있었고, 추상적으로 잡혀 있던 개념을 구체적으로 정립할 수 있게 되었다. 이러한 글쓰기를 통해 지식을 공유하는 행위는 내게 또 다른 즐거움을 주었다. 앞으로도 많은 글을 작성하여 많은 사람들에게 도움을 주고 싶다.

아래는 내가 포스팅한 내용이다.
https://velog.io/@hjm2530/내가-객체를-설계하는-과정

🫠 아쉬운 점

의미 없는 주석

1주차 공통 피드백을 보면, 아래와 같은 내용이 포함되어 있다.

이를 보고 생각난 나의 무수한 주석들..

주석은 되도록 모두 달아놓는 것이 좋다고 생각했지만, 과도하면 오히려 가독성을 저해한다고 한다.

"뭐든 적당한 게 좋다"라는 말은 정말 만물 공통인 듯하다...

static 키워드

아래는 1주차 미션이 끝나고 받은 코드 리뷰 중 하나다.

볼과 스트라이크를 세는 역할을 수행하는 BallCounter 클래스의 모든 메서드를 static 메서드로 작성했다.
왜 static을 메서드로 만들었냐고 묻는다면.. 많은 곳에서 인스턴스 생성 없이 호출될 것 같아서..?
하지만 이는 적절한 답이 아니라고 생각한다. 그리고 나는 아직 static 키워드에 대한 개념이 부족하다고 느꼈다.

🔥 2주 차 목표

  • 1주차 공통 피드백 반영하기
  • 함수를 분리하고, 각 함수별로 테스트 코드 작성하기
  • 어떤 예외가 있을지, 그리고 어떤 테스트 코드를 작성할 수 있을지 고민하기
  • 랜덤값 테스트하기
  • Java API 적극 활용하기
  • static 키워드 학습하기
  • 객체지향의 사실과 오해 1~3장 읽고, 미션에 적용하기

🌙 마무리

프리코스가 시작된지 벌써 일주일이 지났다.

이전까지 수많은 경쟁속에서 고통의 시간을 보냈다면, 지금은 다양한 동료들과 함께 성장하며 많은 것을 느낄 수 있는 즐거운 시간을 보내고 있다.

남들보다 잘해서 합격하겠다는 마음은 잠시 내려놓고, 이번 기회에 함께 성장하는 방법을 배우기로 굳게 다짐했다. 그래서 잘하는 동료에게서는 무엇을 배울 수 있을지, 도움이 필요한 동료에게는 무엇을 나눌 수 있을지 고민하며 일주일을 보낸 것 같다.

앞으로도 불안한 마음보다는 즐거운 마음으로 프리코스에 참여해야지.

0개의 댓글