본문 바로가기
개발 공부

원티드x위코드 프리온보딩 네번째 기업과제 (에잇퍼센트) 회고록

by 부지런한 배짱이 2021. 11. 15.

✔️ API 목록

  • 거래내역 조회 API
  • 입금 API
  • 출금 API

✔️ 주요 고려 사항은 다음과 같습니다.

  • 계좌의 잔액을 별도로 관리해야 하며, 계좌의 잔액과 거래내역의 잔액의 무결성의 보장
  • DB를 설계 할때 각 칼럼의 타입과 제약
  • 거래내역이 1억건을 넘어갈 때에 대한 고려

 

 

이번 과제에서 우리는 서기를 뽑아서 회의를 진행했다.

우리 팀 조장 바다님이 정리를 아주 잘 해주셨다 :D

 

기록하며 회의를 해서 생각을 정리하기 쉽고
의견을 빠뜨리지 않으며 하나씩 차근차근 논의를 하게되어 좋았다.

 

회의에서 호기심이 생겼던 부분은 거래내역 조회를 입금과 출금 둘로 나눌것인지에 대한 논의였다.

호기심이 갔던 이유는, 사실 데이터베이스에 대해서 아직 집중적으로 공부해보지 않았기 때문에

작업을 할 때 어떤 고민을 하고 어떤 과정을 겪는지, 전반적인 과정이 궁금했다.

하지만 나는 내역 조회 기능 구현에 참여하지 못했다 😅

회의록

 

 

그리고 우리는 도메인 주도 설계를 시도해보았다.

 

마인드맵에 모여 스티커를 하나씩 붙여보았다.

우리는 각 기능등을 어디에 둬야할지, 뭐를 써야할지, 쉽게 결정하지 못하고 있었는데

 

동균님이 쉽게 생각하자며 혼자서 척척 만들고 계셨다.

자연스럽게 우리 모두 동균님에게 합류하여 도메인 주도 설계를 완성해 나갔다.

 

사실 이 부분은 내가 해보고 싶어서 제안 했던 것인데,

다들 어려워하는거같고 나도 잘 모르는 상태라서

진행이 잘 되지 않아 미안한 마음이 드는 와중이어서 동균님께 감사한 순간이었다 ㅎㅎ

 

처음에는 이게 뭔가 싶었는데, 하다보니 무언가 만들어 졌다는 것에 우리 모두 신기해 했다.

과정도 재미있었다. 😄

 

완벽하지 않을 수 있지만 다른 사람들과 함께 만들어 봤다는 것이 의미가 있는 작업이었다.

 

쉽게 생각하고 여러번 만들어보며 익숙해지는 경험을 해볼 수 있어 좋았다.

어차피 뭐든 처음부터 완벽하게 할 수는 없기에

 

 

혼자 공부했으면 어렵고 느렸을 DDD 경험

쉽게 생각하고 일단 가볍게 시도해보는 것도 필요하다.

 

위코드 대표님이 하셨던 말씀 중 기억에 남는 것이 있는데

모든 프레임워크나 개발 도구들은 어차피 사용자를 위해 만들어졌기 때문에

사용하지 못할 것은 없다는 것이었다.

 

프리온보딩 과정의 경험들로

프로그래밍에 대해 조금은 더 열린 마음(?)으로 접근 할 수 있을 것 같다.

 

 

나와 희진님 계좌 관련 API 구현을 담당하게 되었다.

구현 기능은 계좌 생성과 삭제뿐이어서 ( 처음엔 여기서 많은 것을 배우게 되리라는 것을 알지 못했다 🤭 )

빨리 끝내고 거래내역 조회 구현에 합류하고 싶어 속도를 붙였다.

 

여러 프로젝트를 진행하며

프레임 워크에 익숙하지 않은 분들도 척척 도와줄 수 있을만큼

기본적인 사용법에는 익숙해졌다 :)

 

모듈에 대한 이해를 키울수 있었던 두번째 기업 과제

 

이제 IoC 설정은 익숙해졌다구

 

그리고 우리는 포스트맨 대신 e2e 테스트를 활용하는 시도를 해보았고 효율적이라는 것을 느꼈다.

(끝까지 이 방식으로 진행하지 못해 아쉽다. 🥺)

테스트 코드를 활용하여 개발 효율을 높였다?!

 

하지만 우리의 앞길을 방해하는 첫번째 프라블름이 있었는데

그것은 바로..

ㄴㅇㄱ

조회 내역에 많은 관심이 쏠려있던 우리는

회의 때 계좌API에 대한 언급을 거의 하지 않았는데

 

막상 구현을 해보니, 계좌번호는 사용자가 입력해서 생성하는 것이 아니라

자동으로 생성되어야 한다는 것을 깨닳았다. :O

 

생각하지 못한 문제에 당황했지만.. 우리의 집단 지성 앞에서 그것은 아주 귀여운 문제였다.

두명의 집단 지성

 

우리는 계좌를 만드는 메소드 안에

랜덤 숫자 + 하이픈 추가 + 중복검사 기능을 넣었고

목요일 위코드 수업에서 들었던 재귀 함수 라는 것을 활용해 보았다 😙

 

코드가 한결 깔-끔 해졌다

 

계좌번호 자동 생성 e2e 테스트

 

사실 계좌 생성/삭제 기능을 구현하며

새로운 시도와 깨닳은 것들이 많이 있었는데

 

주로 리팩토링과 테스트코드에 대한 내용이며

글이 길어질 것 같아서 미리 정리해보자면

1. API구현 과정에서 e2e 테스트를 활용하는 시도를 했다.
2. 자연스럽게 유닛 테스트를 어떻게 작성 해야 할지 감이 잡혔다.
3. 유닛 테스트를 작성하며 어려웠던 부분이 해결되었다.
4. DTO를 활용하여 필요한 데이터만 제공

5. 기존의 서비스를 도메인 계층과 서비스 계층으로 나누었다.
지난 과제들에서 테스트코드를 작성했던 경험들이 의미 있었구나!

이번에 가장 많은 시간을 투자하고 배운 것이 많았던 과정은 리팩토링이었다.

그동안 학습한 것들을 실제로 응용해보는 시간이었다. 🙂

 

위의 코드도 나중에 많이 달라진다 :D

 

계좌번호 생성에 필요한 기능들을 하나씩 정의하며

테스트 코드에서 무엇을 테스트 해야할지 자연스럽게 감이 잡히는 경험을 하며

반복 학습의 효과를 느꼈다.

 

그리고 테스트 코드를 나중에 작성해도 의미가 있다고 느꼈다.

그래서 어느정도 기능이 구현되고, 다음 작업에 들어 가기전

유닛 테스트를 작성하기로 했다. (이전 과제에서는 몰아서 했었다 🤣)

 

하 지 만

 

mock 객체의 쓰임새를 제대로 이해하지 못했던 나는

그간 해결되지 않았던 문제에 다시 직면했다. 😇

리팩토링 하며 내부 구현된 로직을 어떻게 검증해야 하는 것인가 !!

 

반환 값으로 Account 객체 안에 자동 생성된 계좌번호가 포함되어 있어야 함을 검증하고 싶었다.

자동으로 생성되는 계좌번호를 하드코딩 해야 하는 걸까?
(여기 나오는 무의미한 검증과 비슷한 상황인 것 같다.)
내부구현된 메소드를 public으로 바꾸어야 하는 걸까?
(내부 구현은 검증하지 말라는데..)

위의 링크는 전역 변수 사용을 지양하고 테스트의 각 구문마다 검증값을 하드코딩해야 하는 이유를 이해하는데 도움이 될 것 같다.

 

고민 하며 테스트 코드를 테스트 해보고 있었다. (?)

 

그리고 마침내.. mock객체는 임의의 값을 반환하는 역할이 아니라

내부에서 사용되는 것을 그대로 시뮬레이션 해주는 역할이라는 것을 알게 되었다.

 

즉 실제로 서비스가 reposiry 메소드에 넣어주는 인자값을 mock객체에서 확인할 수 있다.

내부 메소드가 인자에 넣어주는 값을 확인할 수 있구나?

 

이로써 서비스의 기능을 모두 확인 할 수 있었다.

완성 된 테스트 코드

 

P.S. 하지만 다른사람을 이해시킬 만큼의 테스트 코드 작성법에 대한 이해와 경험이 스스로 부족함을 느꼈다.

그래두 내가 이해하고 있는 것은 다시 공유해야겠다 :)

 

 

그리고 코드 리뷰도 필요하다고 생각했다.

자기가 담당하지 않은 API에 대해서도 이해를 하고 있어야 한다고 생각하기 때문이다.

시간이 촉박해서 다 하진 못했지만

못다한 코드 리뷰는 다음 과제 시작 전에 해보기로 했다.

회원 API 코드 리뷰

바다님은 회원 기능 구현 후 합류하게 되었고

우리는 함께 머리를 맞대고 가독성 좋은 코드를 작성하기 위해 고민했다.

 

명확한 역할을 가진 메소드와

한눈에 이해되는 네이밍, 타입 명시를 꼼꼼히 하기 위해 애썼다.

이 코드는 이후에 다시 도메인과 서비스로 한번 더 나뉜다.

다시 보니 14번 18번 라인이 아쉬워 다시 커밋을 올렸다 😇

 

 

리팩토링 과정에서 DTO를 적극적으로 활용했다.

어느 블로그에서 봤던 DTO 사용 방식을 직접 사용해보았다.

전달받은 객체를 DTO에 담아 필요한 데이터만 간편한 방식으로 전달했다.

 

 

입출금 기능이 구현되고 나영님과 함께 코드 리팩토링을 해보았다.

사실 계좌와 입출금은 밀접한 관련이 있는 부분이었는데

어쩌다보니 따로 작업을 하게 되어 아쉬운 부분이었다. 😓

 

그래도 여기서도 많은걸 배웠다.

 

입출금 서비스에서는 거래내역과 계좌에 대한 정보가 필요하다.

그리고 각 Repository에게 전달받은

Account 혹은 History객체를 이용해서 유효성 검사나 업데이트를 하는데

이 과정에서 재사용 할 수 있는 코드들이 있었다.

transaction과 account는 똑같은 역할의 코드가 존재했다.

 

같은 기능을 하는 코드를 통일 시키시 위해서

transaction 서비스에 account 서비스를 주입해야 할지 고민이 되었지만

얼마전에 재복님을 통해 알게 된 MVC 패턴에서 데이터 흐름은 단방향 이어야한다는 사실때문에

서비스에서 서비스를 주입받는 다는게 뭔가 확신이 서지 않았다.

 

그렇다면 재사용 가능한 코드를 두고 중복 코드를 생성할 것이냐?

 

나는 어느 블로그에서 읽었던 도메인 계층과 서비스 계층에 대한 글을 떠올렸다.

 

그리고 이것을 정확히 어떻게 적용하는 것인지 당장 파악하기에 시간이 부족했고

우리는 일단 이것을 적용하는 방법이 옳든 틀리든

틀렸으면 다음에 잘하면 되지 라는 생각으로 일단 적용을 시켜보았다.

시간도 촉박했고 너무나 피곤했다 😇

+ (21.11.15) 빈약한 도메인 풍성한 도메인

틀려도 괜찮아

 

그렇게 우리는 Entity 안에서 account의 역할로 생각되는 메소드들을 추가했다.

Account Entity에 정의한 메소드

 

똑같은 기능을 하는 메소드를 중복 생성하지 않을 수 있었다.

각 서비스 안에서 account 객체는 자신의 역할을 스스로 책임지고 있다.

 

 

나영님과 나는 마침내 리팩토링을 통해 멋진 코드를 완성했다. :D

리팩토링 전

 

리팩토링 후

 

한가지 남은 궁금한 것은 DTO를 Repository에서부터 씌워도 되는 것인가다. 🤔

+ (21.11.15) DTO의 사용 범위에 대하여

 

이번 과제에서 아쉬웠던 것은

입출금 거래와 내역을 등록하는 과정에서 트랜잭션이 중요한 부분이라고 생각하고

NestJS에서 트랜잭션에 대한 내용을 찾아보았지만

데이터베이스 관련 작업에 확신이 없었기에 의견을 좀더 확실하게 내지 못했던 부분이다. 😓

1억건의 데이터 삽입시에도 DB에서 직접 반복문을 돌리면 어땠을까?

 

그래도 이 주제는 다음 코드 리뷰 시간에 한번 더 얘기해볼만한 것 같다.

 

틀려도 괜찮아

리드미에 작성할 것은 별로 없었지만

사실 참 많은 것을 경험하고 배운 시간이었다.

 

열심히 정리했지만 급하게 마무리 하는 느낌이다.

이유는.. 포스팅에 너무 시간을 많이 소비했기 때문이다. 🥲

그만큼 새로운 것을 많이 시도해봤다는 거겠지?

게다가 글을 완성하고서 두시간 전으로 돌아가는 대참사가 두번이나 벌어졌다. 😇

 

나중에 내가 이 글을 봤을 때 도움이 되길 바라며 나에게 심심한 위로를 보낸다.

 

 

결과물

https://github.com/preOnboarding-Team13/Assignment-4-8percent

 

GitHub - preOnboarding-Team13/Assignment-4-8percent

Contribute to preOnboarding-Team13/Assignment-4-8percent development by creating an account on GitHub.

github.com

 

숙제

더보기

트랜잭션 추가하기

1. 계좌 가져오는것도 트랜잭션에 포함해야한다

중간에 다른 리퀘스트라든지 이벤트가 일어날수있다.

Select for update

 

1억개의 내역 핸들링에 관하여 공부하기

 

 

P.S  블로그 이미지 편집기능을 사용할때 "저장이 실패되었습니다 네트워크 환경을 확인해주세요" 라는 알람이 뜨면 브라우저를 다시 켜서 작성해야한다.

두번 째 버그가 발생했을 때는 정말 때려치고 싶었지만 하루종일 쓰던 글이라 화를 참으며 글을 다시 완성했다.. 🥲