오히려 좋아..

상황이 나쁘게만 흘러가는 것 같을 때 외쳐보자.. .

궁금한 마음으로 포트폴리오 보기

Language/Javascript, typescript

[typescript] class-transformer, Object를 클래스로 클래스를 Object로! [1]

junha6316 2022. 4. 14. 20:26

 종종 개발을 하다보면 외부에서 들어온 JSON 응답을 내부 로직에 사용하거나 내부에 있는 데이터를 외부로 보내줘야할 때가 있다. 그럴때마다 들어온 JSON을 그대로 사용하거나 plain Object를 만들어 반환해줄 때가 있다. 하지만 이런 방식은 돌아가지만 좋은 방식은 아니다. 왜냐하면 외부의 세부 사항이 그대로 들어나 내부로직을 더럽히는 경우가 발생하기 때문이다. 즉 캡슐화가 제대로 되지 않는다는 의미이다.

 

예를 들어 클라이언트에서 서버응답을 받아 그대로 Object로 만들어 사용하는 경우를 생각해보자. 이 경우에는 서버의 필드 값이 변경되었을 때 해당 API를 사용하는 모든 컴포넌트에 변경이 필요하다.

 

그 뿐만 아니라 클래스로 변환하면서 해당 클래스에 관련된 로직을 구현할 수 있어서 오히려 코드에 냄새를 줄일 뿐만 아니라 오히려 다우니 향기를 더 해줄 수 있다. 오늘은 이를 해결하기 위한 방법으로 class-transformer를 사용하는 방법에 대해 이야기 해보자!

 

plainToClass

* plainToClass는 deprecated 됩니다. plainToInstance를 사용해주시길 바랍니다.

 

먼저 외부에서 들어온 응답을 클래스로 만들어주는 경우부터 생각해보자. 먼저 유저 API를 호출해 아래와 같은 JSON 응답을 받는다고 생각 해보자. 

{
    username: "junha park",
    birthDate: "1994-09-02"
}

이 경우에 유저의 나이를 알기 위해선 매번 다음과 같은 로직을 작성해줘야한다. 물론 이러한 방법이 기능상에 문제가 되는건 아니다. 하지만 나이를 계산하는 코드를 따로 분리해서 관리한다는게 코드에 냄새를 유발한다. 이런 경우에 plainToClass를 사용하면 된다.

function calculateAge(){
    var today = new Date();
    var birthDate = new Date(dateString);
    var age = today.getFullYear() - birthDate.getFullYear();
    var m = today.getMonth() - birthDate.getMonth();
    if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
        age--;
    }
    return age;
 }
 
 
calculateAge(apiResult.birthDate)

먼저 유저 API를 호출해 가져온 정보로 만들 클래스를 작성해주자.

class User{
    username: string
    birthDate: string
    
    // 나이를 계산하는 로직 
    get age() {
        var today = new Date();
        var birthDate = new Date(this.birthDate);
        var age = today.getFullYear() - birthDate.getFullYear();
        var m = today.getMonth() - birthDate.getMonth();
        if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
           age--;
        }
        return age;
    }
}

이제 plainToClass를 이용해 클래스로 만들어주면 다음과 같다.

import { plainToClass } from "class-transformer";

const user = plainToClass(User, apiResult);
console.log(user);
//User { username: 'junha park', birthDate: '1994-09-02' }

console.log(user.age);
//27

위와 같은 방식으로 캡슐화 할 수 있다. 자 이제 age라는 함수는 user의 것이 되었습니다. 한결 더 깔끔해보이지 않는가? 아니라면 댓글 부탁한다. 이와 반대되는 경우 없을까 있다. 바로 instanceToPlain이라는 함수다. 이건 다음시간에 알아보자!