왜 GraphQL은 대중화에 어려움을 겪고 있을까? Under-Design인가 Over-Design인가?

발행: (2025년 12월 13일 오후 11:58 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

I. Simplifying GraphQL Service Development

Zhipu Qingyan AI에게 getBookById 함수를 이용한 GraphQL 예제를 작성해 달라고 하면 다음과 같은 코드를 생성합니다:

@Configuration
public class GraphQLConfig {

    @Bean
    public GraphQLSchema graphQLSchema() {
        String schema = "type Book { id: ID!, title: String, author: String }" +
                        "type Query { getBookById(id: ID!): Book }";
        SchemaParser schemaParser = new SchemaParser();
        TypeDefinitionRegistry typeDefinitionRegistry = schemaParser.parse(schema);

        RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
                .type("Query", builder ->
                   builder.dataFetcher("getBookById", environment -> {
                    String bookId = environment.getArgument("id");
                    // Add logic to fetch the book here; this is just an example
                    return Book.builder().id(bookId)
                        .title("Sample Book Name").author("Sample Author").build();
                }))
                .build();

        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(
                  typeDefinitionRegistry, runtimeWiring);
    }
}

보면 꽤 복잡해 보입니다. graphql-java 라이브러리는 스키마 파싱, 타입 정의 등록, 런타임 와이어링과 같은 개념을 도입합니다. 서비스 함수는 DataFetcher 로 작성하고 프론트엔드 파라미터는 DataFetchingEnvironment 로 받아야 합니다. 하지만 이러한 방식은 GraphQL 엔진의 내부 구현을 노출하고 다소 구식이라고 할 수 있습니다.

최신 Spring GraphQL 프레임워크에서는 몇 개의 간단한 어노테이션만 있으면 됩니다—프레임워크가 복잡성을 자동으로 처리합니다:

@Controller
public class BookController {

    @QueryMapping
    public Book getBookById(@Argument Long id) {
        // ...
    }
}

이와 같이 캡슐화하면 비즈니스 코드는 소수의 어노테이션과 POJO만 있으면 되고, 내부 graphql-java 인터페이스를 직접 사용할 필요가 거의 없습니다. 프레임워크가 Java 클래스 정의를 자동으로 분석해 GraphQL 타입 정의를 생성하므로 수동으로 스키마를 관리할 필요가 사라집니다.

Quarkus 프레임워크도 비슷하게 성숙한 GraphQL 지원을 제공하며 Spring보다 먼저 유사한 어노테이션 메커니즘을 도입했습니다:

@ApplicationScoped
@GraphQLApi
public class BookService {

    @Query("getBookById")
    public Book getBookById(@Name("id") Long id) {
        return ...
    }
}

Nop Platform의 NopGraphQL 프레임워크 역시 어노테이션을 사용해 서비스 함수를 표시합니다:

@BizModel("Book")
public class BookBizModel{
   @BizQuery
   public Book getBookById(@Name("id") Long id){
     ...
   }
}

기본 GraphQL 서비스 지원 위에 NopGraphQL은 CrudBizModel을 통해 NopORM 데이터 접근 엔진과 통합되어 일반적인 CRUD 작업(복잡한 페이지 쿼리, 서브 테이블 필터링, 마스터‑디테일 업데이트 등)을 추가 코드 없이 포괄적으로 지원합니다.

자세한 소개는 “Feature Comparison Between the Nop Platform and APIJSON” 글을 참고하세요.

GraphQL의 설계는 전통적인 웹 프레임워크보다 순수합니다. Request와 Response 같은 웹 런타임 환경에 묶인 개념을 도입하지 않아 완전한 POJO‑지향 캡슐화를 쉽게 구현할 수 있습니다. 다만 GraphQL은 고정된 JSON 형식만 반환하고 파일 업로드/다운로드 기능을 직접 구현할 수 없습니다. NopGraphQL은 이를 위해 /f/upload 확장을 추가해 의미를 보다 완전하게 만들었습니다.

Bilibili 영상도 참고하세요: “How the Nop Platform Adds File Upload/Download Support to GraphQL”.

II. Extending GraphQL to Return Status Codes

GraphQL 프로토콜 전체 설계는 꽤 완전하며, 많은 내장 확장성을 제공합니다. Nop Platform은 GraphQLResponseextensions 맵을 활용해 추가적인 반환 상태 코드를 저장합니다:

@DataBean
public class GraphQLResponseBean {
    List errors;
    Object data;
    Map extensions;

    @JsonIgnore
    public String getErrorCode() {
        return (String) getExtension("nop-error-code");
    }

    @JsonIgnore
    public int getStatus() {
        if (extensions == null)
            return 0;
        int defaultStatus = hasError() ? -1 : 0;
        return ConvertHelper.toPrimitiveInt(
            extensions.get("nop-status"),
            defaultStatus,
            NopException::new);
    }
}

GraphQL 디렉티브를 확장 메커니즘으로 활용하면서, NopGraphQL 프레임워크는 일반적인 애플리케이션 서비스를 단순화하는 여러 애플리케이션‑관련 기능도 도입했습니다. 자세한 내용은 “Nop Primer: How to Creatively Extend GraphQL”를 확인하세요.

III. The Equivalence of GraphQL and REST

표면적으로 GraphQL은 전통적인 REST 서비스보다 많은 고급 기능을 제공합니다. 흥미롭게도 엄밀한 이론 분석에 따르면 GraphQL은 결과 필드를 선택하기 위한 특수 @selection 파라미터를 추가한 기존 REST 서비스를 수학적으로 동일하게 만들 수 있습니다. Nop Platform은 GraphQL 요청과 REST 요청 사이에 다음과 같은 동등성을 설정하여 동일한 백엔드 서비스 함수를 두 프로토콜 모두에서 접근할 수 있게 합니다.

query{
  Book__get(id: 123) { name, title }
}

동등한 형태

/r/Book__get?id=123&@selection=name,title

이 관점에서 GraphQL은 단순히 풀‑모드 REST 호출에 불과합니다. Nop Platform 구현에서는 … (내용이 이어집니다).

Back to Blog

관련 글

더 보기 »

상위 6 API 아키텍처 스타일

아래는 권장 사용 사례와 함께하는 상위 6가지 API 아키텍처 스타일입니다: 1️⃣ SOAP Simple Object Access Protocol: SOAP은 엔터프라이즈 수준에 이상적입니다.