GraphQL과 Apollo 열번째 이야기 - Java + Spring Boot에서 GraphQL 사용해 보기 - 실습 해보기

2023. 11. 26. 21:00Back-End 작업실/Spring Framework

728x90
반응형

 

 

 

카카오페이 | 마음 놓고 금융하다

여기를 눌러 링크를 확인하세요.

qr.kakaopay.com

 

 

 

 

자바 ORM 표준 JPA 프로그래밍:스프링 데이터 예제 프로젝트로 배우는 전자정부 표준 데이터베이

COUPANG

www.coupang.com

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

 

 

 




🗂 목차

✅ GraphQL과 Apollo 첫번째 이야기 - 개념 익히기
 GraphQL과 Apollo 두번째 이야기 - REST API란?
 GraphQL과 Apollo 세번째 이야기 - GraphQL의 정보 주고 받는 방식

 GraphQL과 Apollo 네번째 이야기 - Apollo란?
✅ GraphQL과 Apollo 다섯번째 이야기 - GraphQL을 간단하게 구현해 보아요 😀
 GraphQL과 Apollo 여섯번째 이야기 - GraphQL Module화에 대해 알아보아요 😀
 GraphQL과 Apollo 일곱번째 이야기 - GraphQL Data Type에 대해 알아보아요 😀
 GraphQL과 Apollo 여덟번째 이야기 - GraphQL Union과 Interface 그리고 인자와 인풋 타입에 대해 알아보아요 😀
 GraphQL과 Apollo 아홉번째 이야기 - Java + Spring Boot에서 GraphQL 사용해 보기 - 실습 환경 구성
 GraphQL과 Apollo 열번째 이야기 - Java + Spring Boot에서 GraphQL 사용해 보기 - 실습 해보기
✅ GraphQL과 Apollo 열 한번째 이야기 - TypeScript + Nest.js에서 GraphQL 사용해 보기 - 실습 환경 구성
✅ 
GraphQL과 Apollo 열 두번째 이야기 - TypeScript + Nest.js에서 GraphQL 사용해 보기 - 실습 환경 테스트
 GraphQL과 Apollo 열 세번째 이야기 - TypeScript + Nest에서 GraphQL 사용해 보기 - 실습 해보기
 
GraphQL과 Apollo 열 네번째 이야기 - React와 Apollo Client
 GraphQL과 Apollo 열다섯번째 이야기 - React와 Apollo Client - Query와 Mutation 사용하여 웹 페이지 만들기
 GraphQL과 Apollo 열 여섯번째 이야기 - Kotlin + Spring Boot에서 GraphQL 사용해 보기 - 실습 환경 구성
 GraphQL과 Apollo 열 일곱번째 이야기 - Kotlin + Spring Boot에서 GraphQL 사용해 보기 - 실습 해보기


🤔 내가 만난 문제

⚠️ [Nest.js] TypeORM Table 관계가 맺어졌을 때, Seeding (feat. Migration)
⚠️ [Spring Boot 3.0] Could not resolve org.springframework.boot:spring-boot-gradle-plugin
⚠️ [Spring Boot 3] Spring Doc(Swagger) White Label Error


📋 부록

🔍 [Nest.js] 초기 환경 구성 (feat. TypeORM, QueryBuilder, GraphQL, Apollo)
🔍 [SOLID][Nest.js][Java + Spring] Interface를 활용한 결합도 분리 (Interface를 이용한 Dependency Injection - DI)

 

 

 

 

 

GitHub - junyharang-coding-study/GraphQL-Study: GraphQL을 공부하고, 실습한 코드에요 😀

GraphQL을 공부하고, 실습한 코드에요 😀. Contribute to junyharang-coding-study/GraphQL-Study development by creating an account on GitHub.

github.com

 

 

 

 

 

🚀 GraphQL과 Apollo 열번째 이야기

    🔽 Java + Spring Boot에서 GraphQL 사용해 보기 - 실습 해보기

        📦 개요

이 전 글에서 실습하기 위한 구성을 진행해 보았어요.

이제 본격적으로 자프링을 이용해서 실습해 보도록 할게요.

 

 

 

 

    🔽  세번째 이야기 실습

        📦 Overfetching

기본적으로 조회하고, 삽입, 삭제하는 건 이전 글에서 Equipment를 통해 해봤기 때문에 처음 실습은 OverfetchingUnderfetching으로 진행해 볼게요.

오늘의 첫번째 실습은 Overfetching에 대한 이야기로 시작해보려고 해요.

실습에 앞 써 강의와 다른 점에 대해 이야기 하고 싶어요.

강의에서는 데이터베이스에서 조회된 결과를 그대로 반환하는 방식으로 실습을 진행했었어요.
하지만, 주니는 실제 서비스를 만든다는 가정하에 실습 환경을 준비했고, 주니가 백엔드 코드를 구성할 때, 많이 사용하는 DefaultResponse라는 객체를 만들어 놓았어요.

이 객체는 반환할 때, HTTP Status Code, HTTP Status Message, Data를 묶어서 보낼 수 있도록 만든 객체에요.

이렇게 반환하는 이유는 프론트엔드에서 백엔드에 요청을 보내 반환 받을 때, 최초 해당 요청에 따른 응답 결과가 정상적인지 확인하고, 정상이면 받아온 데이터를 통해 화면 구성 코드를 구성할 것이고, 아니면 오류를 내 뱉어 주게 되는데, 이렇게 Parsing(파싱) 했을 때, 확인할 만한 값 없이 데이터만 딸랑 던져 버리면 프론트엔드에서 이 중, 삼 중으로 코드를 작성해야 하기 때문이에요.

우리 개발자는 협업이 핵심인 직업이니 다른 사람들도 고려하면서 코딩을 해 주면 더 좋겠죠?

이렇게 진행하게 되면 의문이 생기게 될 거에요.


위와 같이 Equipment에 대해 목록 조회를 했을 때, 반환값으로 HTTP Status Code와 HTTP Status Message 그리고 data List 객체, Paging 정보를 담은 pagination 객체가 전달 되는걸 확인할 수 있어요.

강의에서 들은대로 하자면 이 4가지 객체에서 필요 없는걸 제외할 수는 있어요.


위와 같이 HTTP Status Message를 제외하고, 값을 받을 수 있어요.
그치만 이게 Overfetching 문제를 완전히 해결한 것일까요?

우리가 배운 Overfetching 문제는 결국 data 객체의 값을 조절할 수 있어야 한다가 조건이기 때문에
이는 완벽한 해결 방법은 아니에요.

query.graphqls


Equipment 관련 스키마는 위와 같이 설정 되어 있어요.

schema.graphqls


data 필드를 보면 자료형 타입이 String이기 때문에 Overfetching 문제를 근본적으로 해결할 수 없어요.
이를 해결 하기 위해 아래와 같이 수정해 주어야 해요.

query.graphqls


최초 위와 같이 Root Query Schema에 반환값을 반환 받을 값에 맞는 타입으로 각각 만들어 주었어요.
반환 값에 객체 이름이 빨간색 표시가 되어 있으나, 주니가 실습해 본 결과 이는 무시해도 상관 없어요.

people.graphqls

728x90


그리고 위와 같이 DefaultListPeopleResponse Type과 DefaultPeopleResponse Type을 만들어 주었어요.
여기서 Equipment와 차이점을 보면 data를 String으로 받느냐 객체로 받느냐의 차이에요.

schema.graphqls


이렇게 설정을 해두고, 어떻게 쿼리를 날려주어야 할까요?


위와 같이 기존대로 쿼리를 날려주면 문제가 발생하는 걸 알 수 있어요.

왜냐하면 이제 data는 객체를 담고 있기 때문이에요.


위와 같이 쿼리를 날려주니 정확하게 답변이 오는걸 확인할 수 있어요.

그리고 위와 같이 Overfetching 문제가 해결된 모습을 확인할 수 있어요.

참고로 코드를 보면 .graphqls가 각각 나뉘어 진 걸 확인할 수 있어요.
이는 Spring For GraphQL 형식에 맞게

 

GraphQL과 Apollo 여섯번째 이야기 - GraphQL Module화에 대해 알아보아요 😀

GraphQL과 타입스크립트로 개발하는 웹 서비스:설계부터 개발·배포까지 따라 하며 완성하는 웹 풀 COUPANG www.coupang.com "이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를

junyharang.tistory.com


이 글에서 공부했던 Module 화를 구성한 것이에요.

 

 

        📦 Underfetching

이번엔 Underfetching에 대해 실습하면서 분석해 보려고 해요.

query getEquipmentsAndSupplies {
  getEquipmentList(
    page: 1,
    size: 3
  ) {
    statusCode,
    message,
    data,
    pagination
  }
  
  getSupplyList(
    page: 1,
    size: 5
  ) {
    statusCode,
    message,
    data,
    pagination
  }
}


위 내용을 보면 하나의 쿼리를 보내 두 개의 각각의 원하는 응답값을 받은 걸 확인할 수 있어요.

query.graphqls

 

query.graphqls

 


위의 Overfetching에서 설명한 것과 다르게 아직 data 부분이 아직 수정되지 않았어요.
이 점 참고 부탁드립니다.

이렇게 두 개의 스키마에 대해 조회를 날리게 되면 하나의 요청으로 두 개의 값을 얻을 수 있는 걸 확인할 수 있어요.

Join 이나, 다른 걸 하지 않고도 이렇게 얻을 수 있는 것이에요.

이를 통해 Underfetching 문제가 해결 되는 걸 알 수 있어요.

 

 

 

 

 

 

        📦 두 번의 데이터 베이스 조회 - REST API도 구성해 보기

비즈니스 로직에서 두 번의 데이터베이스 조회를 통해 한번에 값을 반환 받는 방법에 대해 이야기 해보려 해요.

주니는 teamId를 이용해서 Team과 People 정보를 가져올 수 있게 구성해 보려고 해요.

TeamResolver - getTeamByTeamId


위 Resolver(리졸버)는 teamId를 받아 정보를 반환할 수 있는 Router에요.

TeamServicempl - getTeamByTeamId


비즈니스 로직은 위와 같이 되어 있는데, 103번째 줄에 Spring Data JPA를 통해
teamId를 이용하여 Team 정보를 조회하도록 하였어요.

그런 뒤 105 ~ 120번째 줄까지 teamId를 통해 People 정보를 조회하는데, Team에 소속된 사람은 여러명이기 때문에 List로 반환되게 하였고, 이를 반복문을 통해 돌리면서 filter를 이용하여 Null인지를 확인하고, Null이 아니면 Map을 이용하여 Spring Data JPA를 통해 데이터베이스에서 조회된 People Entity를 Builder를 이용하여 PeopleResponseDto로 변환한 뒤 이를 다시 List에 담도록 해 준 내용이에요.

TemResolverImpl - getTeamByTeamId

반응형


이렇게 담은 각각의 객체들을 하나의 List에 담아주어야 하기 때문에
122번째 줄에 조회된 값들이 비어 있지 않은지 확인하고,

123번째 줄에 Optional로 감싸 나온 Team Entity 객체를 풀어준 뒤 DefaultResponse 객체에 담아 주는데,

TeamAndMemberResponseDto에 Builder Pattern(패턴)을 이용하여 담길 수 있게 해 주었어요.

TeamAndMemberResponseDto.java


DTO는 위와 같이 구성 되어 있는데, 23번째 줄과 같이 한 개의 팀에 소속된 여러 사람을 받기 위해 멤버 변수를 List로 하여 PeopleResponseDto가 담길 수 있도록 선언해 주었고,

생성자를 이용해서 값이 담길 때, 35번째 줄에 값이 있으면 그 값을 그대로 members 변수에 담고,
없으면 List를 생성하여 Null이 담기지 않도록 조치해 주었어요.

 

PeopleRepository.java


Spring Data JPA를 사용하기 위해 위와 같이 findAllByTeamId()를 만들었는데,
JPQL을 이용하여 teamId를 조회한 뒤 나오는 모든 값을 List<People>에 담아 반환하도록 해 주었어요.

이렇게 하면 teamId를 이용하여 해당 Router가 호출될 때, Team 정보와 People 정보가 함께 담긴 DTO가 반환될 거에요.


query.graphqls


그리고 위와 같이 Query Schema를 구성해 주었어요.

team.graphqls


반환되는 Type은 위와 같이 구성해 주었고, data는 객체 혹은 객체 배열이 반환된다고 선언해 주었어요.

schema.graphqls


위와 같이 ResponseDTO를 선언해 주었는데, 여기서 주목해야 할 점은 110번째에요. 110번째 줄에 객체 이름과 

TeamAndMemberResponseDto.java


반환되는 DTO의 변수명이 일치해야 되기 때문이에요.
만약 다르면 Null이 담겨 나올거에요.

 

query getTeamAndPeopleByTeamId {
  getTeamByTeamId(teamId: 1) {
    statusCode,
    message,
    data {
      teamId,
      manager,
      office,
      extensionNumber,
      mascot

      members {
        peopleId,
        teamId,
        firstName,
        lastName,
        sex,
        bloodType,
        serveYears,
        role,
        hometown
      }
    }
  }
}


이렇게 쿼리를 날리면 teamId를 전달하여 Team 정보와 해당 Team에 소속된 사람들 정보를 받아오는 걸 확인할 수 있어요.

그리고 위 내용을 REST API로도 구성해 보려고 해요.

그 전에 보다 편리하게 API Docs를 확인할 수 있는 Swagger를 먼저 구성해 볼게요.

build.gradle

    //SpringDoc 의존성 추가
    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
    implementation 'org.springdoc:springdoc-openapi-ui:1.6.14'


위와 같이 Springdoc-openapi를 추가해 주었어요.


SwaggerConfig.java

 

application.yml



위와 같이 Swagger Config 코드도 만들어 주었어요.

TeamRestApiController - getTeamByTeamId


위와 같이 Controller Code를 생성해 주었어요.

http://localhost:8080/swagger-ui/index.html


이렇게 Swagger가 나온걸 확인할 수 있어요.

 

http://localhost:8080/swagger-ui/index.html#/Team%20%EA%B4%80%EB%A0%A8%20API/getTeamByTeamId

 

http://localhost:8080/swagger-ui/index.html#/Team%20%EA%B4%80%EB%A0%A8%20API/getTeamByTeamId

 

{
  "statusCode": 200,
  "message": "OK",
  "pagination": null,
  "data": {
    "teamId": 1,
    "manager": "Mandy Warren",
    "office": "101A",
    "extensionNumber": "#5709",
    "mascot": "Panda",
    "cleaningDuty": "Monday",
    "project": "Hyperion",
    "members": [
      {
        "peopleId": 3,
        "teamId": 1,
        "lastName": "Nathan",
        "firstName": "Jenkins",
        "sex": "male",
        "bloodType": "B",
        "serveYears": 1,
        "role": "planner",
        "hometown": "Texas"
      },
      {
        "peopleId": 9,
        "teamId": 1,
        "lastName": "Isabella",
        "firstName": "Martin",
        "sex": "female",
        "bloodType": "A",
        "serveYears": 3,
        "role": "developer",
        "hometown": "Georgia"
      },
      {
        "peopleId": 13,
        "teamId": 1,
        "lastName": "Kate",
        "firstName": "Owen",
        "sex": "female",
        "bloodType": "B",
        "serveYears": 2,
        "role": "developer",
        "hometown": "Maine"
      },
      {
        "peopleId": 16,
        "teamId": 1,
        "lastName": "Byron",
        "firstName": "Barnes",
        "sex": "male",
        "bloodType": "A",
        "serveYears": 3,
        "role": "designer",
        "hometown": "Idaho"
      },
      {
        "peopleId": 27,
        "teamId": 1,
        "lastName": "Brian",
        "firstName": "Hunt",
        "sex": "male",
        "bloodType": "B",
        "serveYears": 2,
        "role": "planner",
        "hometown": "Indiana"
      },
      {
        "peopleId": 29,
        "teamId": 1,
        "lastName": "Violet",
        "firstName": "Pearson",
        "sex": "female",
        "bloodType": "AB",
        "serveYears": 5,
        "role": "designer",
        "hometown": "Pennsylvania"
      },
      {
        "peopleId": 35,
        "teamId": 1,
        "lastName": "Sally",
        "firstName": "Fox",
        "sex": "female",
        "bloodType": "AB",
        "serveYears": 5,
        "role": "planner",
        "hometown": "Messachusetts"
      },
      {
        "peopleId": 42,
        "teamId": 1,
        "lastName": "Russ",
        "firstName": "Lawrence",
        "sex": "male",
        "bloodType": "O",
        "serveYears": 5,
        "role": "designer",
        "hometown": "New York"
      },
      {
        "peopleId": 47,
        "teamId": 1,
        "lastName": "Leroy",
        "firstName": "Elliott",
        "sex": "male",
        "bloodType": "AB",
        "serveYears": 2,
        "role": "developer",
        "hometown": "Indiana"
      },
      {
        "peopleId": 50,
        "teamId": 1,
        "lastName": "Ned",
        "firstName": "Butler",
        "sex": "male",
        "bloodType": "O",
        "serveYears": 2,
        "role": "planner",
        "hometown": "Messachusetts"
      }
    ]
  }
}


위와 같이 REST API를 이용해서 조회를 해도 반환 받는 값은 GraphQL과 동일한 것을 알 수 있어요.

 

 

 

 

        📦 Float, Boolean Type 가지고 놀기

이번에는 일곱번째 이야기에서 EquipmentsAdv를 만들어 Float와 Boolean 자료형을 구성하는 방법에 대해 실습해 보려고 해요.

 

GraphQL과 Apollo 일곱번째 이야기 - GraphQL Data Type에 대해 알아보아요 😀

GraphQL과 타입스크립트로 개발하는 웹 서비스:설계부터 개발·배포까지 따라 하며 완성하는 웹 풀 COUPANG www.coupang.com "이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를

junyharang.tistory.com

 

schema.graphqls

 

equipment.graphqls


위와 같이 EquipmentsAdvDto와 DefaultEquipmentsAdvResponse라는 Type을 명시해 주었어요.


query.graphqls


그리고 10 ~ 15번째 줄과 같이 쿼리 함수를 선언해 주었어요.



EquipmentResolver - getEquipmentsAdv()


리졸버 코드는 위와 같이 만들어 주었어요.



EquipmentServiceImpl - getEquipmentsAdv()


위와 같이 최초 QueryDsl을 이용하여 검색 키워드에 대한 검사와 페이징 처리를 하도록 해 두었어요.

이에 대한 자세한 내용은 이 전 글을 참고해 주세요.

 

GraphQL과 Apollo 아홉번째 이야기 - Java + Spring Boot에서 GraphQL 사용해 보기 - 실습 환경 구성

자바 ORM 표준 JPA 프로그래밍:스프링 데이터 예제 프로젝트로 배우는 전자정부 표준 데이터베이 COUPANG www.coupang.com "이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제

junyharang.tistory.com



equipments.js


해당 실습을 위해 일곱번째 이야기에서는 위와 같이 resolver를 작성해 주었었어요.
이를 Java Code로 변환해 볼게요.

EquipmentResolverImpl - getEquipmentsAdv()


위 코드를 분석해 볼게요.

이 비즈니스 로직은 GraphQL 응답을 처리하여 EquipmentsAdvResponseDto 객체 List(리스트)를 만들고,
이 리스트를 포함한 응답을 생성해 주는 로직이에요.

 

🔍 스트림 처리 및 매핑 코드

105 ~ 128번째 줄은 데이터베이스에서 조회된 결과값이 Page 객체에 담겨 나오는데, 이를 리스트로 변환한 뒤 반복문을 돌려 줍니다.

이 때, filter를 통해 Objects::nonNull을 사용하여 Null이 아닌 요소만 필터링을 해주었는데, 이는 개별 객체에 대한 매핑은 새로운 객체를 생성하고, 필요한 필드를 설정하기 위해서 해 주는 부분이에요.

QueryDsl은 이미 EquipmentResponseDto와 매핑이 되어 있는데, useRate와 isNew라는 필드를 추가해주어야 하고, 이는 데이터베이스에는 없는 값이기 때문에 새로운 ResponseDto를 만들고, map을 통해 데이터베이스에서 나온 값들을 반복할 때 마다 EquipmentsAdvResponseDto를 만들어 각각의 리스트에 담길 수 있게 만들어주고, Setter를 통해 EquipmentResponseDto에 담긴 값을 EquipmentsAdvResponseDto에 옮겨 담아 주었어요.

그리고, 115번째 줄 ~ 121번째 줄까지 EquipmentResponseDto에 담긴 usedBy 변수에 값이 developer라는 문자열인지를 확인하고, 맞다면 랜덤 숫자(소수점 2번째 자리까지)를 생성하여 담길 수 있도록 처리해 주었어요.

그리고, 123번째 줄은 역시 EquipmentResponseDto에 담긴 newOrUsed 변수에 값이 new라는 문자열인지 확인하고, 맞다면 True를 아니라면 False가 들어가게 해 주었고, 이를 반환하여 새 리스트 요소에 계속 담길 수 있도록 처리한 부분이에요.

 


이렇게해서 쿼리를 날려보면 정상적으로 Float와 Blooen이 생긴 객체를 받을 수 있답니다.

 

 

 

 

 

        📦 Enum Type

이번에는 일곱번째 이야기에서 공부해봤던 Enum Type에 대해 실습해 볼게요.

resources/graphql/enums.graphqls


위와 같이 Enum Type만 담을 수 있는 enums.graphqls를 만들어 주고, 그 안에 Enum Type들을 정의해 주었어요.


resources/graphql/schema.graphqls


그리고 위와 같이 ResponseDto Type에 자료형 타입을 각각 Enum Type으로 지정해 주었어요.
여기서도 마찬가지로 빨간줄이 가면서 문제가 있어 보이지만,



위와 같이 실습해 본 결과 아무 문제 없이 동작하는 걸 확인하였어요.



일곱번째 이야기에서는 List Type과 Objet Type에 대해서 공부하고, 실습해 보았는데,
이미 Dto 객체로 반환받는 방법과 List Type으로 받는 방법에 대해 이야기 해 보았기 때문에 따로 실습하진 않을게요.

 

 

 

        📦 Interface

이번에는 여덟번째 이야기에서 공부해 보았던 Interface(인터페이스)에 대해 실습해 보도록 할게요.

 

GraphQL과 Apollo 여덟번째 이야기 - GraphQL Union과 Interface 그리고 인자와 인풋 타입에 대해 알아보아

GraphQL과 타입스크립트로 개발하는 웹 서비스:설계부터 개발·배포까지 따라 하며 완성하는 웹 풀 COUPANG www.coupang.com "이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를

junyharang.tistory.com

 

실습하기 전에 여덟번째 이야기에선 Union에 대해서도 이야기를 해 보았어요.
하지만, 주니가 느꼈을 때, Union이라는 걸 실제 서비스에서 얼마나 많이 쓸까?가 의문이 들었어요.

하나의 List에 각기 다른 N개의 객체를 담아서 보내는 것은 이미 위에서 해 보았고, 어떤 조건이 주어졌을 때, 그 조건이 맞으면 A 객체를 아니면 B 객체를 주는 등의 사용을 하는데, 아직까지는 실제 필요하다고 느끼지 못해서 일단! 실습은 하지 않도록 할거에요.


resources/graphql/schema.graphqls

 

resources/graphql/schema.graphqls


여덟번째 이야기에서 이야기했던 대로 위 두 Type은 객체 이름 중 usedBy가 겹치는 걸 알 수 있어요.
참고로 여덟번째 이야기에서는 ID 객체 이름이 모두 id 였기 때문에 이것도 겹쳤지만, 주니는 유니크한 ID 이름을 부여하기 위해 위와 같이 이름을 정해주어서 겹치지 않는걸 알 수 있어요.


이 부분만 Interface로 따로 빼 볼게요.


resources/graphql/Interface/interface.graphqls


위와 같이 Interface를 만들어 주었어요.


resources/graphql/schema.graphqls

 

resources/graphql/schema.graphqls


그리고 위와 같이 각각의 Type 들이 Tool Interface(인터페이스)를 구현될 수 있도록 해주었어요.


 

query findeBygetEquipmentAndSoftwareListPagingUseByInterface {
  getEquipmentList(
    page: 1,
    size: 3
  ) {
    statusCode,
    message,
    data{ 
    	equipmentId,
      usedBy,
      count,
      newOrUsed
    },
    pagination
  }
  
  getSoftwareList(
    page: 1,
    size: 5
  ) {
    statusCode,
    message,
    data{
      softwareId,
      usedBy,
      developedBy,
      description
    },
    pagination
  }
}


위와 같이 결과값을 받는걸 확인할 수 있고, Equipmensts List와 Softwares List 객체가 반환된걸 확인할 수 있어요.

이렇게 해서 주요 실습을 모두 마쳤어요.

 

 

 

 









    🔽  실습 마무리

        📦 짧은 회고

강의와는 많이 다르게 구성하고, 실습해 보느라 다소 어려운 부분도 있었지만,
잘 해결하고 실습을 마칠 수 있어 너무 기분 좋아요!


이제 REST API도 사용할 수 있고, GraphQL도 사용할 수 있겠어요!

긴 글 읽어주셔서 고맙습니다!

다음에는 TypeScriptNest.js를 이용해서 동일하게 구성하고, 실습해 보도록 할게요!

아직 많이 안 써봐서 그런지 모르겠지만, REST API 보다 엄청 편리하고, 좋다라는 느낌은 크게 못 받았어요.
토이 프로젝트 등에서 계속 써 가면서 REST API와 계속 비교하면서 코딩해 보면 좋겠다라는 생각이에요.

하지만, 한가지 분명한 건 GraphQL을 썼을 때, URI 이름 짓는 것에 대한 어려움은 사라진다는 것이에요.

GitHub에 실습에서 사용한 코드를 그대로 올려 두었어요!

Lisense.md와 README.md를 꼭 읽어봐 주시고, 필요하시면 사용해 주시면 좋겠어요!

아참! GitHub에 ⭐️ 이거 눌러주시면 정말 고맙겠습니다 😀







 

 

GraphQL과 타입스크립트로 개발하는 웹 서비스:설계부터 개발·배포까지 따라 하며 완성하는 웹 풀

COUPANG

www.coupang.com

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

 

 

 

GitHub - junyharang-coding-study/GraphQL-Study: GraphQL을 공부하고, 실습한 코드에요 😀

GraphQL을 공부하고, 실습한 코드에요 😀. Contribute to junyharang-coding-study/GraphQL-Study development by creating an account on GitHub.

github.com

 

 

 

 

 

 

카카오페이 | 마음 놓고 금융하다

여기를 눌러 링크를 확인하세요.

qr.kakaopay.com

 

 

 

728x90
반응형