Seungwoo Hong
Front-end developer
Problems of schema based database
:Considerations for front-end
두 타입이 서로 참조 하고 있을 때 잠재적인 문제가 발생
Why?
악의적인 공격이 들어 올 때 무한 순회 필드에 대해 치명적인 장애가 발생
우리 서비스 사례
:Tip
순회 참조를 피할 수 있으면 좋지만 그럴 수 없는 케이스라면 graphql-depth-limit 사용하는 것을 추천한다. graphql-depth-limit 는 복잡한 쿼리 사용 시 필드의 깊이를 제한 할 수 있는 툴이다.
재고 이동 테이블 회사/브랜드 컬럼을 가져 왔다. 재고 이동을 한 회사 이름이 필요 할 뿐인데 6 depth 데이터를 참조해야 한다.
불필요한 쿼리 실행
GraphQL 리졸버는 루트 필드부터 쿼리의 마지막 depth의 필드까지 연쇄적으로 호출된다. 따라서 ORM을 사용하여 데이터를 쿼리하는 우리 케이스 같은 경우, DB 쿼리 실행 또한 불필요하게 많이 될 것이다.
의도되지 않은 자유
앞서 본 예시 코드에서 회사 이름을 얻기 위해 깊은 데이터 쿼리로 클라이언트에서 알아서 회사 이름을 가져 올 수 있었다. 하지만 이것은 어쩌다 걸린 케이스일 수 있다. "재고이동" 이라는 데이터 모델을 생각 했을 때 전혀 예측할 수 없는 모델에서 "회사 이름" 을 가져 왔다. 이런 의문이 들 수 있다.
재고 이동을 한 회사 이름인데 왜 상품 데이터 모델의 회사 이름을 가져오지?
나아가 로직에 대한 빠른 이해를 방해하는 요소가 될 수 있다.
:Tip
graphql-query-complexity 를 이용하면 쿼리의 복잡성을 분석하고 제어할 수 있다.
클라이언트에서 데이터는 디비에서 가져 오는 것은 맞지만 데이터 모델은 전혀 다르다.
Client
DB
데이터 모델을 만들기 위해 추가적인 가공 작업이 필요하다.
Client
DB
디비 모델이 곧 GraphQL 스키마 모델이 되다 보니 DB 구조, 컬럼명 변경이 일어나면 클라이언트의 변경 또한 필수적이다.
Case
B: 디비 송장 테이블에 printedAt 컬럼 추가 했으니 송장 리스트에서 출력 일자 컬럼 createdAt를 printedAt으로 바꿔주세요.
F: 난 그냥 출력일자를 받으면 되는건데..
비즈니스 모델과 디비 모델은 전혀 다르다. 하지만 디비 모델의 컬럼명과 타입을 따라가기 때문에 클라이언트에서 혼란이 생긴다.
Case 1
입고 query arguments 는 입고 데이터 타입을 따로 정의하고 결과 타입은 디비 모델의 타입을 사용하여 문제가 생김
Case 1
입고 query arguments 는 입고 데이터 타입을 따로 정의하고 결과 타입은 디비 모델의 타입을 사용하여 문제가 생김
디비 모델의 데이터 타입은 입고와 출고의 타입이 합쳐진 타입이다. 하지만 클라이언트에서 입고 데이터는 입고 유형만 가져야한다. 입고 타입을 TransactionType에 맞추려다 보니 에러발생, 이를 해결하기 위해 타입가드나 부정확한 타입 지정등 추가 코드 작성을 하여 타입 문제를 해결한다.
Case 2
Seller는 User 모델에서는 Nullable 타입이지만, "재고" 모델에서는 Required 타입니다.
Case 2
Seller는 User 모델에서는 Nullable 타입이지만, "재고" 모델에서는 Required 타입니다.
유저는 초기 진입 시 소속된 셀러가 없어 null 이 될수 있다. 재고 데이터는 셀러의 재고를 가져오기 때문에 null이 될 수 없는 값이다. 재고 데이터에서도 null 타입의 seller 데이터를 받고 있다.
By Seungwoo Hong