시작하면서
지난 주 개선 사항은 다음과 같다.
테스트 네이밍 관련 내용 조사, 나만의 규칙 만들기- It Should, Given/When/Then, Describe/Context/It 등의 방식이 있다.
- 이번 테스트는 BDD 방법론 중 하나의 방법인 Given/When/Then 으로 작성하였다.
- 테스트 방식에 따라서 네이밍 체계 역시 달라지기 때문에, 방식을 먼저 정하고 규칙을 만드는 것이 좋을 것 같다.
주석으로 처리하는 대신 사용할 수 있는 skip() 활용하기에러 클래스 관리 관련 내용 학습- 1주차에서 커스텀 에러 클래스를 지정했었다. 2주차에는 공통 에러 헤더를 부모 클래스에서 관리하지 않고 각 자식 클래스에서 import 해오던 부분을 수정하였다. super() 을 조금 더 효율적으로 사용할 수 있었다.
- 또한 this.name = this.constructor.name; 으로, 각 자식 에러 클래스에서 이름을 지정하지 않아도 되게끔 작성하였다.
어떤 경우에 클래스가 필요한지 생각해보기- 지난 미션에서는 static 메서드들로만 이루어진 Input, Output 클래스를 사용했다.
- 그러나 클래스 내부에서 관리되는 상태가 없고, 상속 및 확장이 불필요하므로 객체 리터럴로 변경했다.
- 가비지 컬렉터의 동작도 차이가 없다고 해서, 위에서 언급한 사항 이외의 차이점이 있는지 더 알아보면 좋을 것 같다.
- TDD 관련 도서 남은 부분 읽고 정리하기
- BDD를 도입하면서 보류하였다.
잘 지킨 것 같아 뿌듯하다!
배경
DI 패턴으로 모듈들의 의존성을 관리하다가, 어떤 기준으로 모듈의 의존성을 묶을지에 대한 고민이 생겼다. 가장 먼저 떠오르는 것은 MVC 패턴이었다. 저번 기수 미션 당시에, MVC 패턴이 유행 아닌 유행(?) 이 되어있었기 때문이다. 그런데 근본적으로 이런 생각이 들었다. “왜 MVC 패턴을 써야 하지?” 그래서 우선 MVC 패턴을 직접 구현해보며 MVC 패턴이 무엇인지부터 다시 학습했다.
특히 헷갈렸던 부분은 아래와 같다.
MVC 패턴의 혼란스러운 지점들
1. 비즈니스 로직은 모델에서? 컨트롤러에서?
- 웹 표준 문서와, 원조 MVC 창시자 모두 모델 에서 처리한다고 명시하고 있다.
2. 데이터 변경 시 모델은 뷰에게 알릴까, 컨트롤러에게 알릴까?
- 일반적으로 뷰에게 알린다.
- 가끔 컨트롤러에게 알리기도 한다. (업데이트 된 뷰를 조절하기 위해 다른 로직이 필요한 경우)
Q. 아니 의도가 둘 간의 분리라면서 왜 모델이 뷰한테 알리는거임?
A. 둘 간의 분리가 무엇인지에 대해 잘 생각해보자.
뷰가 모델의 규칙을 몰라야 한다는 것이다. → 예를 들어 지금 Input 내에서 구현한 car.split(",")을 해서 return하는 방식은 올바른 구현일까? 오히려 이런 형식을 Input에서 알고 있다는 것이 분리가 덜 되었다는 뜻이다.
이와는 별개로 옵저버 패턴 등의 방법으로 변경 사항을 알리기 위한 방법을 구현해야 한다. → 메인 로직이 끝난 후 뷰에게 모델의 값을 넘겨주도록 했는데, 이 때문에 현재 상태에서는 메인 로직 중간에 뷰를 업데이트하는 것은 불가능하다.
또 중요한 문제점은 컨트롤러가 뷰를 직접 업데이트 했다는 것이었다. 제대로 된 MVC를 구현하지 못했다.
3. 유효성 검사는 어디서?
- 아무리 찾아봐도 정답은 없는 것 같아, 개인적인 기준을 세우기로 했다.
- 뷰에 과도한 비즈니스 로직이 들어가는 것이 고민이었다.
- 뷰에서는 callback 으로 넘겨받은 함수를 실행하고, App(컨트롤러라고 주장하는..)에서 유효성 검사 로직을 주입하여 해결할 수 있었다.
- 즉 관리는 컨트롤러에서, 실행은 뷰에서!
만들고 보니, 정작 MVC 패턴보다는 MVP 패턴에 가까웠다. App 의 코드가 늘어나는 것을 보면서, “아, 이래서 MVP 패턴은 어플리케이션이 복잡해질수록 뷰와 프레젠터의 의존성이 강해지는 것을 단점으로 꼽았구나.” 라는 생각을 했다. 다음 주에는 제대로 된 MVC/MVP 패턴을 구현하고, 2주차와 비교하여 장단점을 학습해봐야겠다.
그 외 새로 배운 내용
BDD 도입하기
미션 시작 후 코드를 열어봤을 때, 지난주와 다르게 given when then 주석을 발견할 수 있었다. 무슨 의미인지 궁금해서 검색해봤는데, BDD의 패턴 중 하나라는 것을 알 수 있었다. 그래서 BDD에 대해서 공부하고 적용해보았다.
JavaScript 의존성 관계 주입(Dependency Injection, DI)
DI에 대해서 공부하고, App - 메인로직 에서 강한 결합을 가지고 있던 코드를 DI 패턴 중 생성자 주입으로 수정했다. 추가적으로 메인로직 - 뷰 가 가진 강한 결합을 끊고 역시 DI 패턴을 적용해 주었다. 모듈 간의 인과관계를 알지 않아도 되므로 자연스럽게 테스트 역시 쉬워졌다.
그런데 슬프게도 PR 이후 App 생성자에 객체를 넘겨줄 수 없어 테스트가 실패한다는 것을 알게 되었다. 요구사항을 제대로 살펴보지 않은 잘못이었다. 따라서 임시로 생성자에서 외부 클래스의 인스턴스를 생성하여 멤버변수에 할당해 주었다. 또 다른 클래스를 만들어서 App 에서 새로 만든 클래스에 의존성을 주입해주는 식으로 수정할 수 있겠지만, 불필요한 뎁스가 더 생기는 것 같다는 판단에서였다. 더 좋은 방법이 있을지 다음주에 학습할 것이다.
전체 회고
잘한 부분
지난 미션을 방치하지 않고 잘 되돌아보고 2주차에 개선 사항을 반영한 것!
아쉬운 부분 / 남은 궁금증
- 행위 중심의 테스트에 집중하여, 모듈 테스트에서 부족한 부분이 많았다.
- App - 메인로직 에서 제어 역전(IoC)을 구현하지 못했다.
- 제대로 된 MVC 패턴을 구현하지 못했다.
- 정규식 패턴을 올바르지 않게 작성했다.
- 컨트롤러에서 뷰를 직접 업데이트 하고 있다.
어떻게 개선할 것인가?
- TDD와 BDD를 상호보완적으로 사용하기
- 제어 역전을 구현할 수 있는 다른 패턴들 공부하기
- MVC, MVP, MVVM, MVI, FLUX 등 다시 공부. 중간 객체를 어떻게 잘 활용할 수 있을지 생각해보고, 각 모듈의 역할에 대해서 고민하기
- 여러 예외 케이스를 생각해보고 정규식 검증하기
- 옵저버 패턴 이용하기
'프로젝트 > 우테코 프리코스' 카테고리의 다른 글
[우테코 프리코스 3주차 회고] 모델: 뷰야, 나 업데이트됐어! 새로 렌더링해조. (0) | 2024.11.06 |
---|---|
[우테코 프리코스 1주차 회고] 첫 TDD는 계획대로 되지 않아 (2) | 2024.10.21 |