요청 Environment 접근

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

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

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

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


적용 예

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()을 이용해 요청 파라미터를 확인해볼 수 있습니다.



제공 메서드들

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

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

◾ getField

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

◾ getArguments()

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

◾ getContext()

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

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

◾ getSelectionSet()

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

◾ getExecutionId()

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




Reference

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