본 포스트는 공식 레퍼런스를 참고해 GraphQL을 공부하며 직접 작성한 가이드 입니다.
본 포스트는 2021년 7월 최신 버전인 v16.2를 기준으로 작성되어 있습니다.
prevent recursive gql api call
간단하게 쿼리를 정의함으로써 다양한 요청을 만들 수 있음을 확인했다. 만약에 (개발자의 실수든 뭐든..) 재귀적인 데이터가 생긴다면 어떻게 될까? 테스트를 위해 스키마에 Image
를 추가하자.
1 2 3 4 5 6 7 8 9 10 11
| type Image { thumbnail: String! imageList: [String] }
type WebToon { id: ID! webToonType: WebToonType title: String image: Image }
|
그리고 간단하게 요청을 보내보자.
1 2 3 4 5 6 7 8 9 10 11
| { getWebToon(id: "3568e088-ec83-11eb-9a03-0242ac130003") { id title webToonType image { thumbnail imageList } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "data": { "getWebToon": { "id": "3568e088-ec83-11eb-9a03-0242ac130003", "title": "여신강림", "webToonType": "Origianls", "image": { "thumbnail": "thumbnail URL", "imageList": [ "episode imgae1 URL" ] } } } }
|
웹툰에 이미지가 잘 들어가서 요청이 온다. 여기서 이제 버그를 만들어보자.
1 2 3 4 5
| type Image { thumbnail: String! imageList: [String] image: Image }
|
물론 스키마에 맞게 자바 코드 상에서도 버그를 만들어주자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Slf4j @Component public class WebToonResolver implements GraphQLQueryResolver { public WebToon getWebToon(UUID id) { log.info("getWebtoon request accepted id: {}", id);
Image image = Image.builder().thumbnail("thumbnail URL").imageList(Arrays.asList("episode imgae1 URL")).build();
Image bugImage = Image.builder().thumbnail("bug thumbnail URL").imageList(Arrays.asList("bug episode imgae1 URL")).build();
image.setImage(bugImage); bugImage.setImage(image);
return WebToon.builder().id(id).title("여신강림").webToonType(WebToonType.Origianls).image(image).build(); } }
|
그리고 버그를 호출해보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { getWebToon(id: "3568e088-ec83-11eb-9a03-0242ac130003") { id title webToonType image { thumbnail imageList image { thumbnail imageList image { thumbnail imageList image { thumbnail imageList image { thumbnail imageList } } } } } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| { "data": { "getWebToon": { "id": "3568e088-ec83-11eb-9a03-0242ac130003", "title": "여신강림", "webToonType": "Origianls", "image": { "thumbnail": "thumbnail URL", "imageList": [ "episode imgae1 URL" ], "image": { "thumbnail": "bug thumbnail URL", "imageList": [ "bug episode imgae1 URL" ], "image": { "thumbnail": "thumbnail URL", "imageList": [ "episode imgae1 URL" ], "image": { "thumbnail": "bug thumbnail URL", "imageList": [ "bug episode imgae1 URL" ], "image": { "thumbnail": "thumbnail URL", "imageList": [ "episode imgae1 URL" ] } } } } } } } }
|
버그가 예술적으로 호출된다. 지금이야 depth
가 얼마 되지 않아서 괜찮지만 더 깊어지면 메모리 부족으로 서버가 죽을수도 있다. 새벽 4시에 자다가 일어나서 죽은 서버를 띄우고.. 핫픽스 배포하고.. 끔찍한 일이 일어날 수 있다. 이제 이 끔찍한 일을 방지해보자.
gql 설정에서 max-depth
를 설정해줄 수 있다.
1 2 3
| graphql: servlet: max-query-depth: 4
|
그리고 같은 요청을 보내보면 요청이 reject된다.
1 2 3 4 5 6 7 8 9 10 11
| { "errors": [ { "message": "maximum query depth exceeded 7 > 4", "extensions": { "classification": "ExecutionAborted" } } ], "data": null }
|
물론 depth
를 줄이면 요청은 보내진다.
Repository
모든 가이드의 예제 코드는 SongHayoung/springboot-graphql-tutorial에서 확인할 수 있습니다.