GraphQl로 api 커스텀하기

icebox127·2026년 4월 13일

졸프를 위해 사용자의 레포지토리 목록을 불러오는 api를 구현해야 했다.
https://docs.github.com/ko/rest/repos/repos#list-repositories-for-a-user

깃허브 api에 사용자의 레포지토리 목록을 불러오는게 있길래 연동해서 사용했는데 문제는 사용자가 생성하진 않았지만 기여한 레포지토리를 불러올 수 없었다.
(organization 등 협업을 위해 초대된 레포에서 작업한 경우)

처음 시도

그래서 다른 api 중 사용자의 organization 목록을 불러오는 것과, 해당 organization의 레포 목록을 불러오는 api가 있길래 이 2개를 추가해서 총 3번의 조회로 레포지토리 목록을 불러오게 코드를 작성했는데, 문제가 있다.

  • 웹 클라이언트

    
    @Component
    public class GithubClient {
        private final WebClient webClient;
    
        public GithubClient(WebClient.Builder builder) {
            this.webClient = builder
                    .baseUrl("https://api.github.com")
                    .build();
        }
    
        public List<GithubRepoResponse> getRepos(String token) {
    
            List<GithubRepoResponse> result = new ArrayList<>();
    
            // 1. 내 repo
            List<GithubRepoResponse> myRepos = webClient.get()
                    .uri("/user/repos?per_page=100")
                    .header("Authorization", "Bearer " + token)
                    .retrieve()
                    .bodyToFlux(GithubRepoResponse.class)
                    .collectList()
                    .block();
    
            if (myRepos != null) result.addAll(myRepos);
    
            // 2. org 목록
            List<GithubOrgResponse> orgs = webClient.get()
                    .uri("/user/memberships/orgs")
                    .header("Authorization", "Bearer " + token)
                    .retrieve()
                    .bodyToFlux(GithubOrgResponse.class)
                    .collectList()
                    .block();
            System.out.println("orgs: "+orgs);
    
            // 3. org repo들
            if (orgs != null) {
                for (GithubOrgResponse org : orgs) {
    
                    List<GithubRepoResponse> orgRepos = webClient.get()
                            .uri("/orgs/{org}/repos?per_page=100", org.getLogin())
                            .header("Authorization", "Bearer " + token)
                            .retrieve()
                            .bodyToFlux(GithubRepoResponse.class)
                            .collectList()
                            .block();
    
                    if (orgRepos != null) result.addAll(orgRepos);
                }
            }
    
            return result;
        }
    }
    
  • org 권한 문제로 내가 만든 레포만 불러와짐
    계속 org 목록이 []였다...

  • 여러 api 조합해서 요청해서 속도 느림
    된다 해도 문제인게, api 3개를 조회하는거라 매우 오래 걸릴 것이다

GraphQl

클라이언트가 서버에 필요한 데이터만 선택적으로 요청할 수 있는 쿼리 언어이자 런타임
기존 rest api는 서버에 구현된 내용대로 사용해야 작동하여, 원하는 데이터만 불러오는데 어려움이 있다.
GraphQl은 직접 쿼리문을 작성하여 서버에 요청하는 방식이라 더욱 유연한 사용이 가능하다.

GraphQl을 이용한 구현

query

 String query = """
            query {
              viewer {
                repositories(first: 100) {
                  nodes {
                    name
                    url
                    description
                  }
                }
                repositoriesContributedTo(first: 100, contributionTypes: [COMMIT, PULL_REQUEST], orderBy: {field: CREATED_AT, direction: DESC}%s) {
                  nodes {
                    name
                    url
                    description
                  }
                }
              }
            }
        """;
  • viewer: 현재 로그인한 github 사용자
  • repositories: 해당 사용자의 레포지토리
  • repositoriesContributedTo: 사용자가 기여한 레포지토리

api 호출

 Map<String, Object> response = restClient.post()
                .uri("https://api.github.com/graphql")
                .header("Authorization", "Bearer " + accessToken)
                .body(Map.of("query", query))
                .retrieve()
                .body(new ParameterizedTypeReference<>() {});

Map<String, Object> response: json 응답을 맵으로 받는다

profile
감자의 공부기록🥔

0개의 댓글