Spring Boot · 2026-05-09

Spring Boot에서 GraphQL Subscriptions 구현

Spring Boot 환경에서 GraphQL Subscriptions를 WebSocket 기반으로 설정하고 메시지 발행·구독 흐름과 예제 코드를 정리한 실무 예제

작성일 : 2026-05-09 ㆍ 작성자 : 관리자
post
목차

소개

GraphQL Subscriptions는 서버에서 클라이언트로 실시간 이벤트를 푸시하는 기능이다. 채팅, 알림, 실시간 대시보드 같은 기능에 주로 사용된다. Spring Boot와 결합하면 기존 REST/API와 함께 실시간 통신을 손쉽게 추가할 수 있다. 이 글은 처음부터 구체적인 구현 예제를 통해 작동 원리, 필요한 설정, 코드 예시와 문제 해결 포인트를 설명한다.

전체 아키텍처 개요

구성은 간단하다. 서버는 이벤트 발생 시 내부 퍼블리셔에 메시지를 발행한다. 퍼블리셔는 Flux 스트림을 통해 구독자에게 전달한다. 클라이언트는 WebSocket으로 서버에 접속해 특정 Subscription을 구독한다.

주요 흐름

  • 클라이언트가 WebSocket으로 연결
  • 클라이언트가 Subscription 쿼리 전송
  • 서버가 내부 이벤트를 Flux로 노출
  • 이벤트 발생 시 서버가 구독자에게 푸시

필요한 라이브러리

일반적으로 다음 라이브러리를 사용하면 구현이 수월하다. GraphQL Java 기반의 스타터와 WebSocket 지원이 필요하다.

예시 pom.xml 의존성

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
  </dependency>
  <dependency>
    <groupId>com.graphql-java-kickstart</groupId>
    <artifactId>graphql-spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>com.graphql-java-kickstart</groupId>
    <artifactId>graphql-java-tools</artifactId>
  </dependency>
</dependencies>

위 조합은 WebSocket 기반의 Subscription을 지원하는 설정과 잘 맞는다. 특히 WebFlux를 사용하면 Reactor 기반 스트림을 바로 활용할 수 있다.

GraphQL 스키마

Subscription 타입을 정의한다. 간단한 메시지 푸시 예제를 보자.

type Message {
  id: ID!
  roomId: ID!
  content: String!
  createdAt: String!
}

type Subscription {
  messageSent(roomId: ID!): Message!
}

구현 단계

1) 이벤트 퍼블리셔

Reactor의 Sinks를 사용하면 내부에서 발생한 이벤트를 여러 구독자에게 브로드캐스트할 수 있다.

import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;

public class MessagePublisher {
  private final Sinks.Many<Message> sink = Sinks.many().multicast().onBackpressureBuffer();

  public void publish(Message msg) {
    sink.tryEmitNext(msg);
  }

  public Flux<Message> flux(String roomId) {
    return sink.asFlux().filter(m -> m.getRoomId().equals(roomId));
  }
}

2) Subscription Resolver

GraphQL Subscription 리졸버는 Flux<Message>를 반환한다. GraphQL Java Tools를 사용하면 인터페이스 구현으로 처리한다.

import com.coxautodev.graphql.tools.GraphQLSubscriptionResolver;
import reactor.core.publisher.Flux;
import org.springframework.stereotype.Component;

@Component
public class SubscriptionResolver implements GraphQLSubscriptionResolver {
  private final MessagePublisher publisher;

  public SubscriptionResolver(MessagePublisher publisher) {
    this.publisher = publisher;
  }

  public Flux<Message> messageSent(String roomId) {
    return publisher.flux(roomId);
  }
}

3) WebSocket 및 서버 설정

graphql-java-kickstart 스타터를 사용하면 별도의 복잡한 설정 없이 WebSocket을 활성화할 수 있다. application.yml에 관련 설정을 추가한다.

graphql:
  servlet:
    websocket:
      enabled: true
    mapping: /graphql
    enabled: true

이렇게 하면 /graphql 엔드포인트에서 websocket 기반의 subscription 프로토콜을 처리한다. 사용 환경에 따라 CORS, 보안 토큰 검증 등을 추가해야 한다.

4) 클라이언트 예제

브라우저에서는 Apollo Client의 subscriptions-transport-ws 또는 graphql-ws 클라이언트를 쓸 수 있다. 아래는 subscriptions-transport-ws 예시다.

import { SubscriptionClient } from 'subscriptions-transport-ws';
import { execute, subscribe } from 'graphql';

const client = new SubscriptionClient('ws://localhost:8080/graphql', {
  reconnect: true,
});

const query = `subscription($roomId: ID!) { messageSent(roomId: $roomId) { id content createdAt } }`;

const obs = client.request({ query, variables: { roomId: 'room1' } });
obs.subscribe({
  next(data) { console.log('new message', data); },
  error(err) { console.error(err); }
});

동작 원리와 검토 포인트

  • WebSocket 연결 유지: 네트워크 환경에서 연결이 끊길 수 있으므로 재연결 전략 필요
  • 백프레셔 처리: 다수 구독자가 동시에 연결되면 이벤트 누적 문제 발생 가능
  • 보안: 토큰 기반 인증을 WebSocket 연결 시 검증해야 함
  • 스케일링: 멀티 인스턴스 환경에서는 중앙 이벤트 브로커(Redis, Kafka 등)가 필요

문제 해결 체크리스트

  • 클라이언트가 WebSocket 프로토콜을 사용해서 연결하는지 확인
  • 서버 로그에서 subscription 연결 성공 여부 확인
  • Publisher가 실제로 이벤트를 emit 하는지 단위 테스트로 검증
  • 멀티 노드 환경에서 동일한 이벤트가 모든 노드로 전파되는지 확인

마무리

Spring Boot에서 GraphQL Subscriptions는 WebSocket을 통해 실시간 기능을 추가하는 실용적인 방법이다. 핵심은 안정적인 이벤트 퍼블리싱과 구독 스트림을 유지하는 구조 설계다. 위 예제는 기본 플로우를 이해하기 위한 출발점이다. 실제 운영 환경에서는 인증, 백프레셔, 스케일링을 함께 고려해야 한다.

spring boot graphql subscriptions graphql subscription spring boot example websocket graphql spring boot graphql java spring reactor subscriptions graphql-subscriptions graphql-java-kickstart spring boot websocket