2024년 1월 넷째주
자동차 경주 게임을 타입스크립트 + 노드환경 기반으로 구현하면서 깨달은 이모저모 🕺
랜덤값에 대한 테스트는 어떻게 해야하나?
문제점
자동차 전진 조건이 '랜덤값이 몇 이상일 때' 전진한다.
였다. 그래서 처음에는 자동차 객체내부 메서드에서 랜덤값(조건)을 구하는 로직을 추가했다. 자동차 전진 조건은 당연히 자동차 객체가 가지고 있어야 한다고 생각했다. 하지만 이렇게하니 해당 기능에 대한 테스트를 진행 할 수 없었다.
해결방법
- 자동차의 전진 조건이 되는 랜덥값을 자동차 객체에서 직접 구하도록 하지 않고, 외부에서 매개변수로 주입받을 수 있도록 수정했다.
이 방법이 좋다고 생각한 이유
-
우선 랜덤값에 대한 경계값 테스트가 쉽게 가능하다.
-
‘4이상일 때 전진해야한다’라는 걸 테스트할때 중요한건 경계값 즉, 조건이 4와 3일 경우에 대한 기능 테스트라고 생각한다. 랜덤 숫자를 구하는 로직을 자동차 객체에게 위임하지 않고 외부에서 주입받게 함으로써 보다 테스트가 용이해졌다. 테스트가 용이해졌다는 것은 결국 자동차 객체의 책임이 어느정도 줄었다는 것을 의미하기도 한다고 생각한다.
-
그럼 자동차 객체의 책임이 줄어든것이 좋은걸까? 전진 조건을 구하는 것은 자동차 객체 자체의 역할이 되어야하는게 아닌가? 이렇게 생각 할 수도 있지만, 내 생각에는 전진 조건은 경주의 규칙마다 달라질 수 있다고 생각한다. 만약에 전진 조건이 랜덤값 0
9 사이가 아닌 05 사이가 되는 자동차 경주에 대한 요건이 새로 추가되었다고 생각해보자. 만약 위와 같이 자동차 객체에 랜덤값을 구하는 로직을 결합시킨채로 구현하게 된다면 이러한 조건 변경에 대해 대응 할 수 없어진다. 또 다른 자동차 객체를 만들어야한다. 이러한 관점에서 보았을 때 전진 조건인 랜덤값을 자동차 객체 자체의 책임에서 분리하여 외부에서 주입할 수 있도록 만드는 것이 보다 변경에 유연하게 대응 할 수 있을 것 같다.
DTO (Data Transfer Object) 추가
DTO (Data Transfer Object) 란~?
- 계층 간 데이터 교환을 위한 객체
- DB에서 데이터를 얻어서 Service 혹은 Controller등으로 보낼 때 사용하는 객체
- DTO 는 데이터가 네트워크를 통해 전송되는 방법을 정의하는 객체
- interface 혹은 class를 이용해서 정의 될 수 있다.
DTO를 사용하는 이유는?
- 매번 모든곳에 프로퍼티 타입을 정의해주어야하는 번거로움을 해소 할 수 있음
- 데이터 유효성 검사
- 더 안정적인 코드
DTO 도입 소감
class CarNameDto {
private carNameList: string[];
constructor(carNameList: string[]) {
this.carNameList = carNameList;
}
static from(carNameString: string) {
return new CarNameDto(carNameString.split(","));
}
getCarNameList() {
return this.carNameList;
}
}
export default CarNameDto;
사용처
// ...생략
async setupGame() {
const carNameResult = await this.inputView.inputCarNames();
const carNames = CarNameDto.from(carNameResult).getCarNameList();
carNames.map((car) => new Car(car));
// ...생략
}
-
dto 계층을 추가는 해봤는데, 제대로 한건지는 모르겠다. 일단 제일 간단한 자동차 이름에 대한 dto 만 추가했다. 사용자로부터 입력받은 자동차 이름을 주어진 요구사항에 맞게 배열형태로 가공한 객체를 만든다. 그리고 자동차 객체를 생성할 때는 해당 dto 로부터 만들어진 데이터 객체를 참조한다.
-
dto 가 왜 필요할까. 클래스에 데이터를 이동할 때 dto를 이동수단으로 사용하여 데이터를 옮기는 것 같다. 그러니까, 어떠한 값을 각 클래스에서 필요한 형태로 가공하여 전달해주는 계층이라고 이해했다.
-
그리고 특히나 백엔드에서는 특정 값을 DB 에 넣고 빼고하는 일을 하는데, 그 때 dto 가 요긴하게 사용 될 것 같긴하다. 아무튼..dto 계층은 데이터 가공 및 운반 수단이라고 생각하면 편할 것 같고, 자세한건 더 알아봐야 할 것 같다.
-
그나저나 dto를 정의 할 때는 dto 에 데이터를 등록(?)하는 함수를 정적 메서드로 선언해준다. 찾아보니 팩토리 메서드를 적용한거라고 한다. 당연히..dto 는 특정 형태의 데이터 값을 가지는 인스턴스 자체를 만든다. 따라서 가공된 형태로 인스턴스를 초기화해야하고, 따라서 정적 메서드를 사용하여 DTO의 인스턴스를 생성하는 팩토리 메서드를 만들어서 복잡한 초기화 로직이나 데이터 가공을 캡슐화한다.