요청 Environment 접근

이번에는 Spring Boot GraphQL 환경변수(쿼리명, 파라미터명, 값, 받고자하는 데이터명 등)들을 Controller에서 접근하는 방법을 포스팅하려고 한다.

보통 Rest한 서버의 Controller에서는 @PathVariable , @RequestBody 등과 같은 어노테이션을 이용해서 파라미터들에 접근할 수 있는데 요청자체가 body안에 json형태로 들어오는 graphQL은 위와 같은 어노테이션을 사용하기에 다소 무리가 있다.

그래서 지난번에 포스팅한 graphql-java 에서는 DataFetchingEnvironment라는 객체를 제공한다.

DataFetchingEnvironment는 쿼리의 필드, 필드의 인수, 타입, 쿼리 루트 객체, 쿼리 컨텍스트와 같은 정보를 포함하고 있는 객체이다.


1. 적용 예

query{
  getstaion(double x, double y, double distance){
    stationId
    stationName
    distance
    routes{
      routeId
      routeName
    }
  }
}
 @PreAuthorize("hasAuthority('user')")
    public List<RouteStation> getStations(Double x, Double y, Double distance, DataFetchingEnvironment environment) {
        List<Station> stations = stationService.getNearByStations(x, y, distance);
        List<RouteStation> routeStations = new ArrayList<>();

        if(environment.getSelectionSet().contains("routes")) {
            for (RouteStation routeStation : routeStationDtos) {
                List<RouteStation> routeStations = routeStationService.findByStationId(routeStation.getStationId());
                routeStation.setRoutes(routeGraphQLDtos);
            }
        }
        return routeStations;
    }

DataFetchingEnvironment를 사용하는 방법은 간단한데 기존에 존재하는 Resolver내의 메서드의 매개변수 인자로 주어주면 사용이 가능하다.

graphQL은 요청 파라미터에 따라 응답이 달라지게 되는데 routes정보를 뺀 getStations를 호출하게 되도 getStations메서드가 실행되면서 routes정보를 조회하는 쿼리가 실행되고 응답이 반환되게 된다. 이런 문제를 DataFetchingEnvironment를 이용해서 요청 파라미터에 있는지 확인을 먼저하여 성능향상을 꾀할 수 있게 된다.

요청 필드명을 DataFetchingFieldSelectionSet이라는 객체로 변환하여 맵핑시킨 environment.getSelectionSet() 을 이용해 요청 파라미터를 확인해볼 수 있다.



2. 제공 메서드들

getstaion(double x, double y, double distance){
  stationId
  stationName
  distance
  routes{
    routeId
    routeName
  }
}

다음과 같은 쿼리를 예시로 설명하겠다.

1) getField

쿼리명(getStation), 파라미터(x, y, distance), 요청 필드(stationId, stationName…)들을 담고있는 객체가 반환되어 이 객체에서 getArgument() , getSelectionSet() 과 같은 메서드로 변수들을 접근할 수 있다.


2) getArguments()

요청 필드(stationId, staionName …)들을 담고있는 Map을 반환 받고 Map이기 때문에 get() 메서드로 접근이 가능한데 getField().getArgument() 와 차이점은 getField의 getArgument는 List이기 때문에 index로만 접근이 가능하지만 getArguments() 는 Map이기 때문에 필드명으로 접근이 가능하다.


3) getContext()

현재 쿼리를 담당하는 Context를 반환하는 메서드로 DefaultGraphQLServletContext가 반환되고 GraphQLServeltContextBuilder 인터페이스를 상속받아 Custom Context를 만들어서 요청, 응답 헤더에 접근이 가능하다.

다음글로 CustomContext를 만드는 것을 포스팅 할 예정이다.


4) getSelectionSet()

DataFetchingFieldSelectionSet 이라는 객체로 반환이 되며 contains() / containsAnyOf() / containsAllOf() 메서드로 필드명이 존재하는 지 확인이 가능하고 getFields() 를 이용해 정규표현식에 부합한 필드를 반환받을 수도 있다.


5) getExecutionId()

각 쿼리 실행에 고유한 Id가 부여되고 이를 이용해서 각각의 쿼리에 대해 로그를 찍을때 태그를 지정할 수 있다.




Reference

https://www.graphql-java.com/documentation/v11/data-fetching/

Related Posts

인터페이스

인터페이스

  • Java
  • 2021년 12월 8일

1. 인터페이스란? 자바의 다형성을 극대화하여 개발코드 수정을 줄이고 유지보수를 용이하게 하기 위함 다형성? 동일한 메시지를 수신했을 때 객체의 타입에 따라 다르게 응답할 수 있는 능력 1) 추상클래스와 인터페이스 차이 추상메서드를 가짐으로써 다형성을 극대화하면서 어떤 역할을 구현하는 방법(객체들이 따라야 하는 책임의 집합을 서술한 것)이라는 공통점이 있다....

Read More
연산자

연산자

  • Java
  • 2021년 1월 23일

백기선님의 유튜브 로 진행하시는 스터디를 진행하며 올리는 정리 블로그입니다. 산술 연산자 두개의 피연산자를 갖는 이항 연산자로써, 기본적인 사칙연산을 다루는 연산자 ◾ 더하기 (+) 왼쪽의 피연산자에 오른쪽 피연산자를 더하는 연산자로 숫자+숫자, 문자열+문자열이 가능하고 문자열+숫자를 할 시 숫자를 자동으로 문자열로 변환하여 덧셈이 가능하다. 문자+숫자를 할 경우에는 아스키 코드를 이용하여 문자로 결과가 출력 된다. 문자에 맞는 아스키 코드값과 숫자를 더한 결과값에 해당하는 아스키코드를 return하기 때문이다....

Read More
DTO에 대하여

DTO에 대하여

Spring boot 공부하면서 DTO의 개념과 깔끔하게 관리하는 방법등 생각하게 되는 데 다른사람들의 의견도 듣고싶고 방법을 기록하기 위해 글을 작성한다. 1. 변환 수행 계층 Controller Service Repository 데이터의 전달을 수행하는 Controller단이 가장 일반적이고 적합하다고 생각이 들지만, 다른사람들의 글을 보면 Service나 Repository에서 수행하는 것을 보기도 했다.수정사항이 별로 없는 기능에 대해서는 Repository에서 바로 Dto를 이용한다면 별도의 Mapping이 필요없고 간단하다는 글을 어디서 봤는데 이는 계층의 영역을 침범하는 것 같고 수정사항이 생기면 수정이 힘들것 같다....

Read More