우아한 테크 코스 2023년 6기 프리코스 3주차 회고
우테코를 시작한지 3주차..
개인적으로 가장 바빴으면서 가장 깨달음을 얻었고 가장 코드를 못 짠 순간이 언제냐고 하면
망설임 없이 이 3주차를 고를 것이다.
눈물과 고통의 3주차 회고.. 시작..
3주차 회고 간단 요약
3주차가 시작되었다.
3시가 되자, 어김없이 새로운 공통 목표와 피드백이 주어졌다.

한 함수 한가지 기능, 기능 명세, 테스트 코드 작성까지
상세한 설명이 적혀있었는데 신기한 점들은 대다수의 부분들이 이미 해당 주차 코드 리뷰로 받은 피드백을 통해서 고민해보았던 부분들이었다.
2주차회고
뭔가 리뷰어분들 덕분에 늘 방향성을 미리 잡아가는 것 같아 고마울 따름...😢
3주차의 목표는
이었고 마침 30분의 리뷰어께서
Wrapper 클래스, 싱글톤 패턴, 도메인 분리, 팩토리 메서드
같이 새로운 키워드를 많이 주셨기 때문에
1주차와 2주차 처럼 충분히 학습하고 나의 성장에 맞게 끼워넣으면 된다고 계획했다.
모든일은 뜻대로 흘러가지 않는다.
나는 리뷰에 기여하고 이를 정리하는 시간 2일, 학습하는 시간 2일, 구현 시간 2일로
늘 화요일에 미리 제출해왔고 이번에도 시간적인 계획을 이렇게 잡았었다.
리뷰를 하고 보니 어라?
4일이 지나있었다. 심지어 PR이 들어가지는 것 부터가 힘들어 공유하기도 힘들어졌다.
구현이 급하다는 이유로 리뷰를 대충하기 싫어 하나하나 보다보니
시간이 전부 지나간 것이었다.
그러다 보니 다른 분들께 도움을 드리기도 어려워졌다.
그리고 곧이어 두번째 실수를 했다.
기존에 계획했던 기간대로 코드를 짜려고 했던 것이다.
지금 보면 당연히 아직 소화되지 못한 수많은 피드백들을 얹어보려고 하니 문제가 된다고 생각했지만 당시에는 열쩡 가득차맨 이었기 때문에
잠을 자지 않으면 가능할 것이라고 판단했다. (돌이켜 보면 더 자지 않을 잠도 없긴 했다)
"판단했다" 왜 과거형일까..?
계획했던 기간내에 또 다른 일들이 발생하지 않을 것이라고 생각한 나의 오만이었다.
갑작스러운 프로젝트 멘토 회의 라던지, 문제 발생으로 인한 대처라던지
여러 상황들의 발생들로 계획과 점점 더 멀어져갔고
심지어 이번주의 목표인 테스트 코드를 왜 짜는지에 대해 생각해보기 조차 못할 것만 같아
소화되지 못한 지식 + 급한 마음 으로 인해 코드를 자주 뒤엎게 되었다.
개인적으로 나는 신기하게 주위에서 🙋♀️웅성웅성 웅얼 웅얼🙋♀️ 소리가 나면
집중이 되어서 일부러 카페 ASMR을 찾아 듣는 사람이다.
작은 사담..
개인적으로 뉴욕이나 파리 같이 다들 바쁘게 움직이는 곳에서 일해보고 싶은 꿈이 있어서
해외 분위기가 나는 카페 ASMR을 찾는데,
https://youtu.be/yyZxsDMcLVo?si=a3JLnZj-aNOP0iyN
요걸 아주 아주 추천한다...🫶🫶
파리...의 카페 ASMR 인데 해외 분위기 물씬... 이지만 파리는 안가봤습니다.
비슷한지 가보신 분이 후기 부탁드립니다.
또, 교내 동아리에서도 모각공을 열었을때 지금은 문화처럼 잡힐 정도로 다들 좋아했어서
내가 거주하는 지역의 모각코를 열었다.
다행히 생각보다 많은 분들이 참여해주셨고,
자연스럽게 우테코 지원 동기 같은 것들을 물어보고 듣게 되었던 것 같다.
신기하게도 다들 지난 주차들 미션에서 같은 어려움을 겪어왔고,
고민하고 있던 부분들도 어느정도 동일해서 신기했다.
이런 부분들이
나 혼자 속도를 내지 못하고 어려워 하는 것이 아닐까 하는 마음에 위로가 되어주었다.
가장 빠르게 속도를 내었던 순간들을 생각하며 계획을 세우기 보다는
지금 속도로 목표에 도달할 수 있는 계획을 다시 세우자!

계획을 전부 갈아 엎었다.
무엇이 문제라고 느끼는지 아는 것도 중요하지만
그 문제를 해결하기 위해 지금 적절한 리소스를 투자할 기간이 있는지 파악하는 것도 중요하다는 것을 알았다.
문제를 해결하더라도 기간안에 완수하지 못하면 팀으로써는 내 해결이
무의미할 수도 있겠다는 생각이 들었다.😢
그렇게 약 3번동안 모각공을 열며 몰입 환경을 만들고 구현에만 집중하고자 했다.
당연한 결과로
내가 작성한 코드는 정말 만족스럽지 못했다.
그동안 피드백을 주신 분들께도 미안해 commit 조차 하지 않고
바로 refactoring을 할 정도였다.
반전
아마 회고 글 보신 분들은 이렇게 생각할 것 같다.
오...결국은 코드를 잘 짜셨나보다!
아니다 코드는 그대로 맘에 들지 않았다.
반전은 코드의 결과가 아닌
테스트 코드를 왜 짜는지에 대해 생각해보기를 이룰 수 있었다는 것이다.
지금까지의 순서는 이러했다.
그러다 보니 지금까지는 테스트 코드를 작성한 이후 코드를 리팩토링 할 일이 없었다.
class LottoTest {
@DisplayName("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.")
@Test
void createLottoByOverSize() {
assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 6, 7)))
.isInstanceOf(IllegalArgumentException.class);
}
@DisplayName("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.")
@Test
void createLottoByDuplicatedNumber() {
// TODO: 이 테스트가 통과할 수 있게 구현 코드 작성
assertThatThrownBy(() -> new Lotto(List.of(1, 2, 3, 4, 5, 5)))
.isInstanceOf(IllegalArgumentException.class);
}
@DisplayName("중복된 로또 번호 객체 생성")
@Test
void createDuplicateLotto() {
Assertions.assertSimpleTest(() -> {
List<Integer> numbers = Arrays.asList(2, 23, 33, 9, 2, 45);
assertThrows(InputIllegalArgumentException.class, () -> new Lotto(numbers));
});
}
그러나 테스트 코드를 짜고 리팩토링 하니 이와 같은 장점이 발생했다.
개인적으로 느낀 감정은
" 테스트 코드는 또 하나의 기능 명세 문서 같다 "
였다.
그래도 지금 내 속도에서 적용 가능한 피드백은 적용해야한다!
public class Lotto {
private final List<Integer> numbers;
private static final int LOTTO_LENGTH = 6;
private static final int START_RANGE = 1;
private static final int END_RANGE = 45;
계속해서 public으로 만들던 상수를 private으로 바꿔주었다.
이게 전부 나의 접근제어자 리뷰어 선생님 hlmg님 덕분이었다.
이 자리를 빌어 감사합니다...🩵
public class Input {
private static final Pattern REMOVE_REGEX_PATTERN = Pattern.compile("\\s");
private static final String DIVIDING_STANDARD = ",";
public static int inputNumber() {
try {
return Integer.parseInt(Console.readLine());
} catch (NumberFormatException e) {
throw new InputIllegalArgumentException(InputError.MUST_BE_DIGIT);
}
}
저번 리뷰 때,
NumberFormatException이 발생하는 곳에서
IllegalArgumentException으로 잡아주는 것을 리뷰어 께서 찾아주셨다!
Exception은 자세할 수록 좋으니 이번 3주차에서는 던지는 에러로 잡아주었다.
public class MoneyTest {
private static final int PRICE = 1000;
@DisplayName("money 생성")
@ParameterizedTest
@ValueSource(longs = {1000, 2000, 3000})
void createMoneyWithAmount(long amount) {
Money money = Money.getInstance(amount);
long lotteryCount = amount / PRICE;
assertEquals(lotteryCount, money.getLotteryCount());
}
@DisplayName("음수로 money 생성")
@ParameterizedTest
@ValueSource(longs = {-1000, -2000, -3000})
void createMoneyWithNegative(long amount) {
assertThrows(InputIllegalArgumentException.class, () -> Money.getInstance(amount));
}
@DisplayName("PRICE로 나누어 지지 않는 money 생성")
@ParameterizedTest
@ValueSource(longs = {1500, 3099, 2999})
void createMoneyWithNotDivide(long amount) {
assertThrows(InputIllegalArgumentException.class, () -> Money.getInstance(amount));
}
}
저번 2주차 에서는 어노테이션을 잘 응용하지 못했었다!
그래서 이번 주차는 @ParameterizedTest 와 @DisplayName을 응용해서 Test를 짜보았다.
사용할 수 있는 풀이 늘어난 기분이라 묘하게 뿌듯했던 기억이 난다.
리뷰어 분을 통해서 Arrays.asList()를 사용하여
이후에 추가나 수정이 가능한 객체를 만들어 Return 해왔음을 알게되었다.
이를
public class LotteryPapers {
private final List<Lotto> lotteries;
private final long lotteryAmount;
private LotteryPapers(List<Lotto> lotteries, long lotteryAmount) {
this.lotteryAmount = lotteryAmount;
this.lotteries = lotteries;
}
public static LotteryPapers createLotteryFrom(long lotteryAmount) {
RandomNumberGenerator randomLotteryGenerator = new RandomLotteryGenerator();
List<Lotto> lotteries = LongStream.range(0, lotteryAmount)
.mapToObj(i -> new Lotto(randomLotteryGenerator.generateRandomLotteries()))
.toList();
return new LotteryPapers(lotteries, lotteryAmount);
}
처럼 toList()를 사용하여
이후 불변객체를 return해주도록 작성해보았다.
한 리뷰어께서 매직 넘버에 대해 알려주셨다.
사실 이때까지 매직 넘버의 존재를 몰랐었는데, 찾아보니
특정한 곳에서 사용하지만 상수로 선언하지 않고 직접 사용하는 숫자
라는 뜻이었다.
public class Money {
private static final int ESSENTIAL_RESULT = 0;
private static final int LOTTERY_PRICE = 1000;
그래서 위와 같이 평소에 매직넘버로 사용하던 부분들을 상수로 선언해보았다.
기존에는 망설임 없이 getter을 사용해서 직접 계산한 결과를 return해줬었다.
그러나 이번에는 한번 시도해보고 싶어
// LottoResult.class
public double <getTotalRate() {
long totalReward = calculateTotalReward();
long totalSpent = calculateTotalSpent();
return (double) totalReward / totalSpent * 100;
}
private long calculateTotalReward() {
return this.resultCounter.entrySet().stream()
.mapToLong(entry -> entry.getKey().getReward() * entry.getValue())
.sum();
}
private long calculateTotalSpent() {
return this.resultCounter.values().stream()
.mapToLong(Long::valueOf)
.sum() * 1000;
}
...
// LotteryGame.class
private void checkTotalRate() {
printTotalRateMessage(OutputMessage.TOTAL_RETURN_RATE, lottoResult.getTotalRate());
}
과 같이, 정보를 가지고 있는 객체가 계산하여
가져오도록 바꾸어 보았다.
아직 전부를 바꾸지는 못했지만😥
내 속도에 맞춰 시도해보고 4주차때는 좀 더 다양한 시도를 해보는게 좋다고 생각했다!
나에게는 우아한 테크 코스를 하며 목표가 있었다.
내가 우아한 테크코스가 프리코스가 끝나더라도 아쉽지 않게 많은 것을 시도해보고
많은 분들을 뵙게 된 만큼 여러 사람들과 함께 서로 도움을 주고 받고
아 그때 ~했을때 좋았지 한번 시도해볼까?
할 수 있는 경험을 하기를 원했다.
그렇기에 이것저것 많은 시도를 해보았다.
public class LotteryShop {
private final LotteryPapers lotteryPapers;
private LotteryShop(LotteryPapers lotteryPapers) {
this.lotteryPapers = lotteryPapers;
}
public static LotteryShop buyLotteryFrom(Money money) {
long lotteryCount = money.getLotteryCount();
LotteryPapers lotteryPapers = LotteryPapers.createLotteryFrom(lotteryCount);
return new LotteryShop(lotteryPapers);
}
private static Money moneyInstance;
private Money(long money, long lotteryCount) {
this.money = money;
this.lotteryCount = lotteryCount;
}
public static Money getInstance(long amount) {
if (moneyInstance == null) {
validateMoney(amount);
return new Money(amount, amount / LOTTERY_PRICE);
}
return moneyInstance;
}
그러나 그러다보니 여러가지 문제가 발생했다.
우선 앞서 말한대로 학습이 덜 된 채로, 즉 나의 속도에서 무리인 결과를 내려고 했던 문제가 있었고
이를 적절하게 응용하지 못해 도메인만 많아진 상태가 되었다.

이에 도움을 요청하고자 READEME에 이와 같이 작성하게 되었다.
여기에 한 리뷰어 분께서

이와 같이 정말 좋은 말씀을 남겨주셨다.
개인적으로 학습하고자 했던 마음이 너무 앞서 놓쳤던 부분들을 말씀해주신 것 같아 감사했다.

이에 이와 같이 답장했다.
늘 리뷰할때마다 느끼는 부분들이지만 개발에서 중요한 대화나 소통을
리뷰어 분들께서 정말 잘해주시는 덕분에 리뷰를 할 때 행복하다고 많이 느끼는 것 같다.
한편으로는 4주차가 진행되는 지금,
나는 누군가에게 그런 리뷰어가 되어 주었었을까
하는 생각도 하게 되었다.
4주차가 끝나면
우리 새벽반 분들과 리뷰어 분들이 정말 그리워질 것 같다.😢😢
4주차는 지금까지의 성장처럼
피드백을 정리하여 새로운 것들을 목표로 두기 보다는
지금 내 성장에서, 내가 잘 아는 것들을 사용하여
우테코의 피드백과 1주차 부터 3주차까지의 리뷰어 분들의 피드백 을 바탕으로
내 속도에서의 최선의 결과물을 온전히 만들어내는 4주차를 목표로 두고 싶다!
당연히 한다. 피드백은... 피드백이니까
미션뿐만이 아닌 앞으로의 성장을 위해 정리하는 피드백!
method의 목표보다는 하는 일에 집중하는 시선으로 네이밍 짓기!while문 형식으로 에러 받기Constant 클래스를 따로 두는 것 고려해보기!다들 후기를 보니 나와 비슷한 생각을 가졌고,
비슷한 어려움을 가졌어서 공감되는 마음에 회고에 댓글을 많이 달게 되었었다.
단기간에 이렇게 멋진 분들과 온전히 뭔가에 몰입할 수 있어서 좋았고
그럴 환경이, 상황이 안될정도로 바쁜 분들도 계실텐데 그래도 꾸준히 열심히 달리시는 분들이
참 대단하고 어디가서도 잘하실 분들이라고 생각한다!
다들 3주차 고생하셨고 4주차도 화이팅입니다!!🥰🥰
우연히 보게 됐는데 프리코스 기간에 정성 회고를 남기는 것이 대단하시네요...!
화이팅입니다!