1. 개요
애플리케이션을 지원하기 위해 웹 서비스를 생성할 때 통신 패턴으로 REST 또는 GraphQL을 사용하도록 선택할 수 있습니다. 둘 다 HTTP를 통해 JSON을 사용할 가능성이 가장 높지만 서로 다른 장점과 단점이 있습니다.
이 예제에서는 GraphQL을 REST와 비교합니다. 제품 데이터베이스 예제를 생성하고 동일한 클라이언트 작업을 실행할 때 두 솔루션이 어떻게 다른지 비교합니다.
2. 예시 서비스
예제 서비스를 통해 다음을 수행할 수 있습니다.
- 초안 상태의 제품 만들기
- 제품 세부 정보 업데이트
- 제품 List 가져오기
- 주문과 함께 단일 제품의 세부 정보 가져오기
REST를 사용하여 애플리케이션을 생성하는 것부터 시작하겠습니다.
3. 휴식
REST(Representational State Transfer)는 분산 하이퍼미디어 시스템을 위한 아키텍처 스타일 입니다. REST의 기본 데이터 요소는 Resource 라고 합니다. 이 예에서 리소스는 "product" 입니다.
3.1. 제품 만들기
제품을 만들기 위해 API 에서 POST 메서드를 사용합니다.
curl --request POST 'http://localhost:8081/product' \
--header 'Content-Type: application/json' \
--data '{
"name": "Watch",
"description": "Special Swiss Watch",
"status": "Draft",
"currency": "USD",
"price": null,
"imageUrls": null,
"videoUrls": null,
"stock": null,
"averageRating": null
}'
결과적으로 시스템은 새 제품을 생성합니다.
3.2. 제품 업데이트
REST에서는 일반적으로 PUT 메서드를 사용하여 제품을 업데이트합니다.
curl --request PUT 'http://localhost:8081/product/{product-id}' \
--header 'Content-Type: application/json' \
--data '{
"name": "Watch",
"description": "Special Swiss Watch",
"status": "Draft",
"currency": "USD",
"price": 1200.0,
"imageUrls": [
"https://graphqlvsrest.com/imageurl/product-id"
],
"videoUrls": [
"https://graphqlvsrest.com/videourl/product-id"
],
"stock": 10,
"averageRating": 0.0
}'
결과적으로 {product-id} 객체에 대한 업데이트가 있을 것입니다.
3.3. 제품 List 가져오기
제품을 나열하는 것은 일반적으로 GET 작업이며 여기서 쿼리 문자열을 사용하여 페이지 매김을 지정할 수 있습니다.
curl --request GET 'http://localhost:8081/product?size=10&page=0'
첫 번째 응답 개체는 다음과 같습니다.
{
"id": 1,
"name": "T-Shirt",
"description": "Special beach T-Shirt",
"status": Published,
"currency": "USD",
"price": 30.0,
"imageUrls": ["https://graphqlvsrest.com/imageurl/1"],
"videoUrls": ["https://graphqlvsrest.com/videourl/1"],
"stock": 10,
"averageRating": 3.5
}
3.4. 주문으로 단일 제품 받기
제품 및 해당 주문을 가져오려면 일반적으로 이전 API를 사용하여 제품 List을 가져온 다음 주문 리소스를 호출하여 관련 주문 을 찾을 수 있습니다.
curl --request GET 'localhost:8081/order?product-id=1'
첫 번째 응답 개체는 다음과 같습니다.
{
"id": 1,
"productId": 1,
"customerId": "de68a771-2fcc-4e6b-a05d-e30a8dd0d756",
"status": "Delivered",
"address": "43-F 12th Street",
"creationDate": "Mon Jan 17 01:00:18 GST 2022"
}
product-id 로 주문을 쿼리할 때 id를 GET 작업 에 대한 쿼리 매개 변수로 제공하는 것이 좋습니다 . 그러나 모든 제품을 가져오는 원래 작업 외에 관심 있는 각 제품에 대해 이 작업을 한 번씩 실행해야 한다는 점에 유의해야 합니다. 이것은 N+1 선택 문제 와 관련이 있습니다.
4. 그래프QL
GraphQL 은 기존 데이터 서비스를 사용하여 이러한 쿼리를 수행하기 위한 프레임워크와 함께 제공되는 API용 쿼리 언어입니다.
GraphQL의 빌딩 블록은 쿼리와 변형 입니다. 쿼리는 데이터 가져오기를 담당하고 변형은 생성 및 업데이트에 사용됩니다.
쿼리와 변형 모두 스키마 를 정의합니다 . 스키마는 가능한 클라이언트 요청 및 응답을 정의합니다.
GraphQL 서버 를 사용하여 예제를 다시 구현해 보겠습니다 .
4.1. 제품 만들기
saveProduct 라는 변이를 사용해 봅시다 .
curl --request POST 'http://localhost:8081/graphql' \
--header 'Content-Type: application/json' \
--data \
'{
"query": "mutation {saveProduct (
product: {
name: \"Bed-Side Lamp\",
price: 24.0,
status: \"Draft\",
currency: \"USD\"
}){ id name currency price status}
}"
}'
이 saveProduct 함수에서 둥근 괄호 안의 모든 항목은 입력 유형 schema 입니다. 이 뒤의 중괄호 는 서버에서 반환 할 필드 를 설명합니다.
변형을 실행할 때 선택한 필드에 대한 응답을 예상해야 합니다.
{
"data": {
"saveProduct": {
"id": "12",
"name": "Bed-Side Lamp",
"currency": "USD",
"price": 24.0,
"status": "Draft"
}
}
}
이 요청은 REST 버전으로 만든 POST 요청과 매우 유사하지만 이제 응답을 약간 사용자 지정할 수 있습니다.
4.2. 제품 업데이트
마찬가지로 updateProduct 라는 다른 변형을 사용 하여 제품을 수정할 수 있습니다.
curl --request POST 'http://localhost:8081/graphql' \
--header 'Content-Type: application/json' \
--data \
'{"query": "mutation {updateProduct(
id: 11
product: {
price: 14.0,
status: \"Publish\"
}){ id name currency price status }
}","variables":{}}'
응답에서 선택한 필드를 받습니다.
{
"data": {
"updateProduct": {
"id": "12",
"name": "Bed-Side Lamp",
"currency": "USD",
"price": 14.0,
"status": "Published"
}
}
}
보시다시피 GraphQL은 응답 형식에 대한 유연성을 제공합니다 .
4.3. 제품 List 가져오기
서버에서 데이터를 가져오기 위해 쿼리를 사용합니다.
curl --request POST 'http://localhost:8081/graphql' \
--header 'Content-Type: application/json' \
--data \
'{
"query": "query {products(size:10,page:0){id name status}}"
}'
여기에서 보고자 하는 결과 페이Map 설명했습니다.
{
"data": {
"products": [
{
"id": "1",
"name": "T-Shirt",
"status": "Published"
},
...
]
}
}
4.4. 주문으로 단일 제품 받기
GraphQL을 사용하면 GraphQL 서버에 제품과 주문을 결합하도록 요청할 수 있습니다.
curl --request POST 'http://localhost:8081/graphql' \
--header 'Content-Type: application/json' \
--data \
'{
"query": "query {product(id:1){ id name orders{customerId address status creationDate}}}"
}'
이 쿼리에서는 주문과 함께 ID 가 1인 제품을 가져옵니다. 이를 통해 단일 작업으로 요청을 할 수 있습니다. 응답을 확인하겠습니다.
{
"data": {
"product": {
"id": "1",
"name": "T-Shirt",
"orders": [
{
"customerId": "de68a771-2fcc-4e6b-a05d-e30a8dd0d756",
"status": "Delivered",
"address": "43-F 12th Street",
"creationDate": "Mon Jan 17 01:00:18 GST 2022"
},
...
]
}
}
}
여기에서 볼 수 있듯이 응답에는 제품 세부 정보와 해당 주문이 있습니다.
REST로 이를 달성하기 위해 우리는 몇 가지 요청을 보내야 했습니다. 첫 번째는 제품을 가져오고 두 번째는 각 주문을 가져오는 것입니다.
5. 비교
이 예제는 GraphQL을 사용하여 클라이언트와 서버 간의 트래픽 양을 줄이고 클라이언트가 응답에 대한 일부 서식 규칙을 제공할 수 있도록 하는 방법을 보여줍니다.
이러한 API 이면의 데이터 소스는 여전히 데이터를 수정하거나 가져오기 위해 동일한 작업을 실행해야 할 수 있지만 클라이언트와 서버 간의 인터페이스가 풍부하여 클라이언트가 GraphQL로 작업을 덜 수행할 수 있습니다.
두 가지 접근 방식을 더 자세히 비교해 보겠습니다.
5.1. 유연하고 역동적인
GraphQL은 유연하고 동적인 쿼리를 허용합니다.
- 클라이언트 측 애플리케이션은 필수 필드만 요청할 수 있습니다.
- 사용자 지정 키가 있는 필드를 요청하는 데 별칭 을 사용할 수 있습니다.
- 클라이언트는 쿼리를 사용하여 결과 순서를 관리할 수 있습니다.
- 따라야 할 응답 개체 구조의 단일 버전이 없으므로 클라이언트는 API의 모든 변경 사항에서 더 잘 분리될 수 있습니다.
5.2. 비용이 적게 드는 작업
모든 서버 요청에는 왕복 시간과 페이로드 크기의 가격이 있습니다.
REST에서는 필요한 기능을 달성하기 위해 여러 요청을 보내게 될 수 있습니다. 이러한 여러 요청은 비용이 많이 드는 작업입니다. 또한 응답 페이로드에는 클라이언트 측 애플리케이션에 필요하지 않을 수 있는 불필요한 데이터가 있을 수 있습니다.
GraphQL은 비용이 많이 드는 작업을 피하는 경향이 있습니다. 우리는 종종 GraphQL을 사용하여 단일 요청으로 필요한 모든 데이터를 가져올 수 있습니다 .
5.3. REST를 언제 사용합니까?
GraphQL은 REST를 대체하지 않습니다. 둘 다 동일한 애플리케이션에 공존할 수도 있습니다. 사용 사례에 따라 GraphQL 엔드포인트 호스팅의 복잡성 증가는 그만한 가치가 있을 수 있습니다.
다음과 같은 경우 REST를 선호할 수 있습니다.
- 우리의 애플리케이션은 기본적으로 리소스 중심이며 작업은 개별 리소스 엔터티와 매우 직접적이고 완전히 연결됩니다.
- GraphQL은 기본적으로 웹 캐싱을 지원하지 않으므로 웹 캐싱이 필요합니다.
- GraphQL은 기본적으로 파일 업로드를 지원하지 않으므로 파일 업로드가 필요합니다.
6. 결론
이 기사에서는 실제 예제를 사용하여 REST와 GraphQL을 비교했습니다.
우리는 배운 각 접근 방식을 전통적으로 어떻게 사용할 수 있는지 보았습니다.
그런 다음 두 접근 방식이 다른 접근 방식에 비해 어떻게 명확한 이점이 없는지 논의했습니다. 우리의 요구 사항은 그 중에서 선택하는 원동력이 될 것입니다. 경우에 따라 둘 다 공존할 수도 있습니다.
항상 그렇듯이 이 기사의 예제 코드는 GitHub에서 사용할 수 있습니다 .