본문 바로가기
우아한테크코스

우테코 Level1 회고록

by CodingMasterLSW 2025. 4. 7.

우테코 시작한 지 엊그제 같은데 벌써 Level1 이 끝났다. 시간이 참 빨리 간다.

 

Level1을 진행하면서 참 많은 감정들을 느꼈다. 내가 느낀 감정들을 잊지 않기 위해 방학 기간 동안 회고록을 작성하기로 결정했다.


Level1, 어떤걸 배웠을까?

 

첫 번째 미션 (로또) 

 

학습 키워드

- 어떤 기술을 사용할 때, 나만의 근거를 가지고 사용하기 

- DTO란?

- Service 계층이란?

 

어떤 고민을 했었을까?

객체에게 적절한 책임을 부여하는 데에 많은 고민을 했다. 기존에는 조금 어려운 비즈니스 로직이 있으면 Service 계층에서 비즈니스 로직을 작성했다. 

public double calculateProfit
	(Map<Rank, Integer> rankResult, int purchaseAmount) {
        Profit profit = LottoCreator.createProfit(rankResult, purchaseAmount);
        return profit.getResult();
}

 

수익률을 계산하려면 우선 객체를 생성해야 했고,  이후에 계산 로직을 작성해야 했다. 내가 느끼기에 여러 도메인이 협력해야 한다고 느꼈고,  Service 계층을 통해 문제를 해결했다.

 

리뷰어는 Service계층이 필요한가? 에 대해 스스로 생각해 볼 만한 질문을 계속 던져줬다. 결론부터 말하자면 Service 계층은 필요 없었다. 서비스 계층은 '어려운 비즈니스 로직을 푸는 계층'이 아니었다. 객체에게 보다 명확한 책임을 부여하고, 서로 소통하도록 만들면 객체간의 협력을 통해 어려운 비즈니스 로직을 풀어낼 수 있다. 되돌아보면 Service 계층을 도입한 이유는 다른 사람들이 사용하니까 + 객체에게 적절한 책임을 주는 방법을 몰라서였던 것 같다. 

 

두 번째 미션 (출석)

학습 키워드

- TDD

- 함수형 인터페이스

- Stream

- Optional / Optional Parameter

- 불변

 

어떤 고민을 했었을까?

가장 많이 한 고민은, 제대로 TDD를 학습하고 있는것일까?였다. 초반에는 감이 잘 잡히지 않아 서적을 많이 참고했었다. 최범균 님의 '테스트주도 개발 시작하기' 서적을 많이 참고했다. 책을 읽어보니, TDD에 대한 감이 살짝 잡혔다. 

 

TDD를 학습하면서 크게 두 가지의 고민을 했다.

 

1) 리팩토링의 시점은 언제가 적절할까?

TDD는 크게 Red - Green- Refactor의 순서를 거친다. 학습 중 가장 고민한 부분은 리팩토링의 시점이었다. 리팩토링 시점에 대해 주변 크루들에게도 계속해서 물어보고, 혼자서도 많이 생각해 봤다. 너무 작은 단위로 리팩토링을 해버리면 개발 흐름이 끊기는 문제가 있었다. 

 

ex)  A를 리팩토링 하는 과정에서 B에 대한 테스트를 진행해야 하고, B에 대한 테스트를 진행하다보면 A에 대한 개발 흐름이 끊겨버림

 

이에 대해 답은 없지만, 기능명세서에 나눈 기능단위로 리팩토링을 하자고 개인적인 결론을 내렸다. 혹시 내 생각이 잘못되었을까 의심이 되어 리뷰어에게 확인을 받고 싶었다. 그래서 2단계를 진행할 때 TDD로 작성한 개발 단위를 전부 커밋했고, 이 흐름에 대해 피드백을 부탁드렸다.

필자가 생각하는 적절한 리팩토링 단위다.

 

2) 설계를 어디까지 해야할까?

기본적인 설계를 하지 않고 바로 TDD로 구현을 했더니 구조가 계속 바뀌는 경험을 했다. 이 때문에 열심히 작성한 테스트코드를 전부 삭제하기도 했다. TDD라고 설계가 필요하지 않은 게 아니라, 적절한 설계를 진행한 후에 코드 작성을 해야 한다는 것을 몸으로 느꼈다.

 

세 번째 미션 (블랙잭)

학습 키워드

- 상속 vs 합성

- 인터페이스

- 추상클래스

- 방어적 복사

- Controller의 역할

 

어떤 고민을 했었을까?

인터페이스, 추상클래스를 사용한 나의 설계가 적절한가? 에 대해 고민해 본 시기였다. 공통으로 사용할 수 있는 메서드들이 존재했고, 이를 같이 사용하고 싶어 추상클래스를 처음으로 사용해 봤다. 개념적으로만 알고 있는 것과, 내가 직접 적용하는 건 큰  차이점이 있었다. 인터페이스와 추상클래스에 익숙해지고 싶어 의식적으로 인터페이스와 추상클래스를 사용하며 확장성을 열어보기도 했다.

 

해당 미션에서 크루들이 공통적으로 궁금해하던 질문은 공통 메서드 관리를 어떻게 할 수 있을까? 였다.

'어떻게 공통적으로 사용되는 메서드를 관리할 수 있을까?'에 대해 크루들과 이야기해 본 결과 '상속파'와 '합성파'로 나뉘는 걸 볼 수 있었다. 합성은 처음 들어보는 키워드였고, 이후에 상속과 합성의 장단점에 대해 공부를 했다.

 

https://codingmasterlsw.tistory.com/36

 

상속과 합성

우리는 공통 코드를 줄이기 위해 상속을 많이 사용한다. 하지만 상속에는 많은 단점들이 존재한다. 공통되는 로직을 줄이기 위해서 상속이 정말 좋은 방법일까? 상속을 사용하면 캡슐화가 깨

codingmasterlsw.tistory.com

 

또한 Controller의 책임에 대해서도 오랫동안 고민했다. 내가 생각하는 Controller는 View와 도메인 객체를 연결시켜 주는 계층이다. 도메인에서 값을 받아오면, 그 값을 View에 넘겨주는 역할인 것이다. 즉, Controller에서는 비즈니스 로직이 있어서는 안 된다고 생각하고 있었다.

 

(당시 Controller의 일부 코드)

 private void receiveExtraCardProcessOfPlayer
 	(Participants participants, CardDeck cardDeck) {
        	participants.getParticipants().stream()
            .filter(Participant::isPlayer)
            .forEach(participant -> inputAskReceiveExtraCard(participant, cardDeck));
}

private void receiveCardProcessOfParticipants
	(Participants participants, CardDeck cardDeck) {
        for (Participant participant : participants.getParticipants()) {
            participant.addCard(cardDeck.getAndRemoveFrontCard());
            participant.addCard(cardDeck.getAndRemoveFrontCard());
        }
       	outputView.printInitialParticipantHands(participants.getParticipants());
}

 

Controller에서 비즈니스 로직을 작성하고 있다고 판단했다. 이때부터 Controller의 명확한 책임은 무엇일까? 도메인이 상위 계층에 노출되었을 때 발생할 수 있는 문제점에 대해 생각해 봤던 것 같다.

 

문제를 해결하기 위해 BlackJackGame이라는 전체적인 도메인 로직을 관리하는 새로운 객체를 생성했다. 이후 최상위 객체인 BlackJackGame만 Controller에 노출시켰다.

 

(수정 후의 일부 코드)

private static void processOfPrintGameResult(BlackJackGame blackJackGame) {
	ParticipantsResult participantsResult = blackJackGame.calculateParticipantsResult();
	outputView.printGameResult(participantsResult);
}

 

Controller의 역할이 무엇인지, 객체가 노출되었을 때 어떤 일이 발생할지 고민할 수 있는 시간이었다.

 

네 번째 미션 (장기)

학습 키워드

- DAO

- 필요한 정보만 전달해 주자

- 전략 패턴

- 상태 없이 행위만 제공하는 객체도 객체일까?

- view에서 도메인을 반환해 보자!

 

어떤 고민을 했었을까?

장기 미션은 고민을 제일 많이 했다. 1단계에서는 양방향 참조에 대해 고민했다. 어떤 문제였을까?

public final Map<Position, Piece> pieces;

 

객체들에 대해 간단하게 설명하자면, 

- Position: 위치 정보 (Column, Row)

- Piece: 기물 (차/ 포/ 마/ 상 등등...)

 

즉, 기물과 위치 정보를 Collection을 통해 관리하고 있었다.

 

객체지향적으로 보았을 때, 기물(Piece)을 움직이는 메서드는 Piece 내부에 있어야 적절하다. 기물이 움직이려면 다음과 같은 순서를 거쳐야 한다.

1) 이동 가능한 위치인지 검증한다.

2) 가는 길에 상대팀 / 같은 팀 기물이 있는지 판별한다.

3) 도착지에 같은 팀 기물 / 상대 팀 기물이 있는지 판별한다.

 

2,3번 로직을 거치기 위해서는 pieces의 정보가 필요하다. 즉, piece.move() 메서드를 만들기 위해서 pieces의 정보가 필요한 것이다.

pieces는 value 값으로 piece를 가지고 있기에 해당 객체들은 양방향으로 연결되어 있다. 양방향으로 연결되어 있을 경우, 문제점이 있을 것이라 판단해 양방향 연결 없이 검증할 수 있도록 코드를 수정했다. 하지만 move를 위한 검증의 책임은 piece 내부에서 하는 게 적절한 책임이라고 판단해 리뷰어인 이프에게 물어봤다.

이프는 최고의 리뷰어다... 진짜 최고임

 

이프의 리뷰를 보니, 양방향 참조에 대해 다시 고민해 봐야겠다는 생각을 했다.  반은 와닿고, 반은 와닿지 않는다. 나머지 절반은 내가 몸으로 느껴봐야 하는 부분이라고 생각한다. 기존 코드를 양방향으로 리팩토링 하면서, 코드가 어떻게 변하는지를 느껴봐야겠다. (아마 기존 코드에 비해 훨씬 응집도가 생기지 않을까...?)

 

2단계에서는 상태가 없이 행위만 제공하는 객체도 객체일까?라는 고민을 했다.

이프는 최고의 리뷰어다. 생각할 거리를 계속 던져주면서 나를 성장시켜준다..!!!

 

아직 이프가 던져준 질문에 답을 구하지 못했다. 회고록을 작성하고 천천히 답을 찾아봐야지...!!

 

또 소프트스킬적으로도 많은 성장을 했다. 페어와 잘 소통하는 방법, 페어의 의견을 존중하는 방법, 페어를 배려하는 방법 등을 배우며 '협업을 잘 하는 사람'으로 성장할 수 있었다. 아직은 한 명과 함께 협업하는 것이지만, 나중에는 이 경험을 기반으로 팀 단위에서 협업을 잘 할 수 있을 것 같다. 배운 부분이 정말 많지만 기존에 작성한 회고들(미션별 회고록)이 소프트스킬에 대한 회고였기에, 간략하게만 언급하고 넘어간다. 

 

공통적으로 미션을 하면서 끊임없이 고민해야 했던 부분은 '객체에게 적절한 책임 부여하기'였다. 한 달 동안 객체지향 공부하니까 객체지향을 마스터했냐? 절대 아니다... 공부를 하면 할수록 모르겠다;;;;;

 

객체지향은 참 신기한 영역이다. 계속해서 나만의 생각, 규칙을 만들어나가야지.


레벨인터뷰

각 레벨이 끝날 때쯤, 우테코에서는 레벨 인터뷰를 진행한다. 랜덤으로 배정되는 코치님 + 크루들과 함께하는 모의 면접 연습이라고 생각하면 될 것 같다. 레벨인터뷰를 하는 이유는

  • 레벨 1에서 학습한 내용에 대한 자신의 현재 상태를 파악한다.
  • 학습하고 경험한 내용을 말로 표현하는 연습을 통해 메타인지를 기른다.

+ 면접 연습이라고 생각하면 될 것 같다.

 

인터뷰를 하기 이틀 전까지, Level1에서 학습한 내용을 A4 한 페이지로 요약해 제출해야 한다. 내가 요약한 내용은 다음과 같다.

 

당시에 잘 알고 있는 내용도 있었고, 개념이 부족해 학습할 목적으로 적은 내용들도 있었다.

 

Level1에서는 '객체', '객체지향'에 대해 집중해서 배웠다. 이에 대한 내용은 해당 시트에서 찾아볼 수 없다. 물론 내가 잘 아는 내용들만 있는 건 아니지만 Exception에 대해서는 나만의 철학을 확고하게 가지고 있다. 운 좋게(?) 인터뷰는 Exception에 대해 깊이 있는 질문이 들어왔고, 많은 생각을 과거에 이미 거쳤기에 별문제 없이 잘 답변했다. 레벨 인터뷰는 성공적으로 마쳤다. 하지만 후회가 된다. 제대로 답하지 못할 것이라는 두려움에 앞서 자신 없는 내용은 스트립트에서 배제했다. ex) SOLID 원칙이라던지...

 

레벨 인터뷰의 목적이 무엇이었을까? 면접 준비 목적도 있지만, 무엇보다 '레벨 1에서 학습한 내용에 대한 자신의 현재 상태를 파악한다'가 핵심이라고 생각한다.

 

객체에 대한 질문이 들어왔다면 자신 있게 답하지 못했을 것이다. 그 과정에서 어떤 부분을 추가로 공부해야 하고, 내가 어디까지 해당 개념에 대해 이해하고 있고, 나만의 생각을 가지고 있는지 확인하는 시간이다. 하지만 별문제 없이 모든 답변을 했기에 어느 부분을 추가로 공부해야 하고, 어떤 부분을 보충해야 하는지에 대한 답을 찾지 못했다.

 

내 질문에서는 답을 찾지 못했지만, 다행히도 다른 크루의 인터뷰에서 답을 찾을 수 있었다. 인터뷰를 관찰하면서 코치님의 질문에 대해 속으로 생각해 봤는데, 쉽게 답하지 못 한 질문들이 몇몇 있었다. 

절차지향과 객체지향의 차이점이 뭐예요? 왜 객체지향적으로 코드를 짜야해요?? 절차지향적으로 짜면 코드가 훨씬 더 깔끔해지고 이해하기 쉬운 거 아니에요?? 와 같은 질문들이었다.

 

해당 질문을 혼자서 속으로 생각해 봤지만, 답을 할 수 없었다. 그렇기에 방학 동안에 간단하게 객체지향의 패러다임에 대해 찾아볼 생각이다!

 

다음 레벨인터뷰에서는 답하기 힘든 질문들도 과감하게 스크립트에 적어야겠다. 대답 못 하는 걸 두려워하지 말자!


정규 미션 이외에 어떤 걸 했을까?

 

Effective Java Study

데일리 미팅 팀원들 3명(가이온, 돔푸,포라)과 함께 Effective Java 서적 스터디를 진행했다.

 

https://github.com/CodingMasterLSW/woowa-7-effective-java

 

GitHub - CodingMasterLSW/woowa-7-effective-java: effective 자바 스터디를 위한 repository

effective 자바 스터디를 위한 repository. Contribute to CodingMasterLSW/woowa-7-effective-java development by creating an account on GitHub.

github.com

 

Level1이 아니면 따로 Java를 공부할 시간이 없을 것 같았다. 혼자서 공부하기에는 책이 너무 어려웠고, 누군가 떠먹여 주면 좋겠다는 생각으로 스터디를 개최했다. 

 

책이 상당히 어려워 40% 정도밖에 이해를 못 했지만, 얻어가는 게 엄청 많은 스터디였다. 스터디는 월, 금 진행했고 item2개씩 발표하는 것을 목표로 했다. 발표를 맡은 파트는 확실하게 이해할 수 있었다. 더 나아가, 어떻게 하면 쉽게 설명할 수 있을까? 에 대해 고민을 하며 준비하다 보니 자연스럽게 발표 역량도 올라갔다고 생각한다. 잘 따라와 준 스터디원들에게 감사를 표한다ㅎ_ㅎ (수고하셨습니당)

 

놀러 다니기

데일리 미팅조와 놀러 다녔다. 갑자기 볼링을 치러 가기도 했고, 야구도 함께 보러 가고,  새벽 3시가 넘도록 함께 술을 마시기도 했다. 아직 말을 섞어보지 못 한 크루들도 많지만, 데일리 미팅 조원들과는 확실하게 친해졌다고 생각한다. Level2부터는 새로운 조가 꾸려질 텐데 기대되기도 하지만, 한편으로는 아쉽기도 하다.


Level1, 해보니까 어때?

과거 우테코는, 수료하면 서비스 기업에 갈 수 있는 마법의 교육 프로그램!이라고 생각했다ㅋㅋ

 

Level1을 마친 지금 시점에서 느낀 우아한 테크 코스는, 본인이 하는 만큼 배워갈 수 있는 공간이라고 생각한다. 일주일에 수업도 2~3시간 밖에 없고, 모든 게 다 자율이다. 점심시간도 자율이다. 졸리면 그냥 빈백에 누워서 자면 된다. 

 

우테코에서 제시하는 수료조건은 '미션 완성'이다. 사실 미션 완성에 초점을 두면 그리 어렵지 않다. 단순히 우테코에서 제시해 주는 미션 완성에 초점을 맞추면 안 된다. 물론 미션 완성에 초점을 맞춰도 성장하겠지만, 많은 성장을 하지는 못 할 것이다. 어떤 개념을 배웠는데 이를 미션에 적용시켜 봐야겠다, 미션은 단순히 내가 공부한 내용을 적용할 수 있는 도구? 정도로 생각해야 된다.

 

잘하는 친구들이 참 많다. 다른 친구들의 코드를 구경하다가 내 코드를 보면 그렇게 초라해 보일 수가 없다. 남들과 비교하지 않으려고 해도 자꾸 비교하게 되고, 뒤처지는 느낌이 든다.

 

담당 코치인 리사가 해준 말이 기억에 많이 남는다.

Level1 제적 안 됐잖아요? 그럼 우테코에서 요구하는 역량을 충분히 달성한거예요. 그러니까 너무 조바심 내지 마요. 이미 우테코에서 제적 안 된 것 만으로도 대단한거에요. 프리코스를 기억해봐요. 몇 천명이 지원했는데 그걸 뚫고 들어오고, 그런 우테코에서 재적을 안 당해?? 이미 대단한 거에요.

 

멘탈적으로 많이 흔들릴 때, 리사가 해준 말을 되새겨야겠다. 나는 이미 대단하다!


Level1, 만족해?

솔직히 말하면 후회가 많이 남을 것 같다. 지금 시점에서는 후회가 들진 않지만 나중에, 우테코를 수료할 때쯤 조금 더 열심히 할걸...이라는 후회가 생길 것 같다.

 

열심히 했어?라는 질문에는 물론! 이라고 답할 수 있지만, 죽을만큼 열심히 했어? 라는 질문에는 아니...라고 할 것 같다. 다시 과거로 돌아간다면 더 열심히 할 수 있었을까?라는 질문에 "응, 더 열심히 할 수 있었을 것 같아"라는 답변이 나오는 시점에서 후회할 상황이 분명 생길 것 같다. 왜 후회할 만한 상황이 나왔을까?

 

우테코는 10개월이라는 장기간의 코스다. 체력 분배를 해야 된다는 소리를 들었고, Level1에서 체력분배를 했다. 이 부분이 후회할 여지가 남을 것 같다.

 

예전부터 우테코를 너무 하고 싶었다.  붙여준다면 진짜 죽도록 열심히 해야겠다는 생각을 가지고 있었다. Level1을 마친 시점에서 나는, 죽을 만큼 열심히 하진 않았다. 물론 열심히 했지만, 더 열심히 할 수 있었다.

 

지금까지 인생을 살면서 언제 제일 열심히 살았을까? 음... 쉽게 답할 수 없다. 어떤 목표를 가지고 쓰러질 정도로 열심히 살았던 적은 없다. 위 질문에 나는 1초의 고민도 없이, 우테코 시절이라고 답할 수 있는 사람이 되고 싶다. Level1을 마친 지금 시점에서 '우테코'라고 답하기엔 조금 애매하지 않나 싶다. 이런 이유로 수료할 때 후회를 할 것 같다ㅎ..


앞으로의 우테코 생활, 어떻게 할 건가요?

조금 더 적극적으로 우테코 생활에 임하려고 한다. Level2부터 진행하는 유강스 이끄미에도 지원했고, Delivery Hero에서 제공해 주는 영어 회화 수업에도 운 좋게 선정되었다. 또, 우테코 근로 학생에도 운 좋게 뽑혔다.

 

사실상 우테코에서 진행하는 모든 활동에 참여하는 것 같은데, 많이 힘들 것 같다. 힘들겠지만, 안 하면 후회할 것 같았다. 

 

Level2에서는 후회가 남지 않게 최선을 다 하려고 한다. 과거로 돌아간다 해도, 그때보다 더 열심히 할 수는 없겠다는 생각이 들도록 온 힘을 다 할 것이다. 할 일이 너무 많아 하루에 3~4시간밖에 못 잔다고 해도 상관없다. 8개월 그렇게 산다고 죽지는 않을 테니까...!