๊ฐœ๋… ์ •๋ฆฌ ์ž‘์—…์‹ค/Kotlin

GraphQL๊ณผ Apollo ์—ด ์ผ๊ณฑ๋ฒˆ์งธ ์ด์•ผ๊ธฐ - Kotlin + Spring Boot์—์„œ GraphQL ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ - ์‹ค์Šต ํ•ด๋ณด๊ธฐ

์ฃผ๋‹ˆ์“ฐ๐Ÿง‘‍๐Ÿ’ป 2023. 12. 21. 15:53
728x90
๋ฐ˜์‘ํ˜•

 

 

 

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค

์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

qr.kakaopay.com

 

 

 

 

์ฝ”ํ‹€๋ฆฐ ์™„๋ฒฝ ๊ฐ€์ด๋“œ

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 ์—ด ์ผ๊ณฑ๋ฒˆ์งธ ์ด์•ผ๊ธฐ

    ๐Ÿ”ฝ  Kotlin + Spring Boot ์—์„œ GraphQL ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ - ์‹ค์Šต ํ•ด๋ณด๊ธฐ

        ๐Ÿ“ฆ ๊ฐœ์š”

์žํ”„๋ง(Java + Spring Boot), Nest.ts์—์„œ๋„ ๊ทธ๋žฌ๋“ฏ ์ง€๋‚œ ๊ธ€๊นŒ์ง€ ์ฝ”ํ”„๋ง(Kotlin + Spring Boot)๋ฅผ ์ด์šฉํ•˜์—ฌ GraphQL ํ™˜๊ฒฝ ๊ตฌ์„ฑ์„ ์œ„ํ•œ ์ž‘์—…์„ ์ง„ํ–‰ํ•ด ๋ณด์•˜์–ด์š”.

Nest.ts ๊ธ€๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‹ค์Šต์„ ์ง„ํ–‰ํ•ด ๋ณด๋„๋ก ํ• ๊ฒŒ์š”.

 

 

 

 

 

        ๐Ÿ“ฆ Overfetching

Overfetching ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋Š” ์žํ”„๋ง ์‹ค์Šต ๋•Œ ๋ณด๋‹ค ์ž์„ธํžˆ ์ด์•ผ๊ธฐ ํ•ด ๋ณด์•˜์–ด์š”.

์ฝ”ํ”„๋ง์˜ ๊ฒฝ์šฐ ์ด๋ฅผ ๋ชจ๋‘ ํ•ด๊ฒฐํ•ด์„œ ๊ตฌ์„ฑ์„ ํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์— ์žํ”„๋ง ๋‚ด์šฉ์„ ์ฐธ๊ณ ํ•ด ์ฃผ์‹œ๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”.

 

GraphQL๊ณผ Apollo ์—ด๋ฒˆ์งธ ์ด์•ผ๊ธฐ - Java + Spring Boot์—์„œ GraphQL ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ - ์‹ค์Šต ํ•ด๋ณด๊ธฐ

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ:์Šคํ”„๋ง ๋ฐ์ดํ„ฐ ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋กœ ๋ฐฐ์šฐ๋Š” ์ „์ž์ •๋ถ€ ํ‘œ์ค€ ๋ฐ์ดํ„ฐ๋ฒ ์ด COUPANG www.coupang.com "์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ

junyharang.tistory.com

 

 

 

 

 

 

        ๐Ÿ“ฆ Underfetching

์ด๋ฒˆ์—” Underfetching์— ๋Œ€ํ•ด ์‹ค์Šตํ•˜๋ฉด์„œ ๋ถ„์„ํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.

http://localhost:8080/graphiql?path=/graphql

728x90
query getEquipmentsAndSupplies {
  getEquipmentList(
    pageRequestDto: {
      currentPage: 1,
      perPageSize: 10
      orderBy: true
    },
  ){
    statusCode,
    message,
    data {
      equipmentId,
      usedBy,
      count,
      newOrUsed
    },
    pagination {
      perPageSize,
      totalElementCount,
      totalPage
    }
  }

  getSupplyList(
  # teamId: 2,
  pageRequestDto: {
    currentPage: 1,
    perPageSize: 10,
    orderBy: true
  }) {
    statusCode,
    message,
    data {
      supplyId,
      teamId
    },
    pagination {
      perPageSize,
      totalElementCount,
      totalPage,
      orderBy
    }
  }
}
{
  "data": {
    "getEquipmentList": {
      "statusCode": 200,
      "message": "OK",
      "data": [
        {
          "equipmentId": "whiteboard",
          "usedBy": "planner",
          "count": 12,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "sketchb",
          "usedBy": "designer",
          "count": 48,
          "newOrUsed": "new"
        },
        {
          "equipmentId": "pen tablet",
          "usedBy": "developer",
          "count": 15,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "notebook",
          "usedBy": "planner",
          "count": 37,
          "newOrUsed": "new"
        },
        {
          "equipmentId": "machanical keyboard",
          "usedBy": "developer",
          "count": 24,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "ergonomic mouse",
          "usedBy": "designer",
          "count": 31,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "dual monitor",
          "usedBy": "developer",
          "count": 20,
          "newOrUsed": "used"
        }
      ],
      "pagination": {
        "perPageSize": 7,
        "totalElementCount": 7,
        "totalPage": 1
      }
    },
    "getSupplyList": {
      "statusCode": 200,
      "message": "OK",
      "data": [
        {
          "supplyId": "webcam",
          "teamId": "2"
        },
        {
          "supplyId": "usb hub",
          "teamId": "3"
        },
        {
          "supplyId": "t shirt",
          "teamId": "5"
        },
        {
          "supplyId": "stempler",
          "teamId": "4"
        },
        {
          "supplyId": "mug",
          "teamId": "1"
        },
        {
          "supplyId": "hoodie",
          "teamId": "2"
        },
        {
          "supplyId": "headphone",
          "teamId": "4"
        },
        {
          "supplyId": "ergonomic mouse",
          "teamId": "1"
        },
        {
          "supplyId": "chair",
          "teamId": "3"
        },
        {
          "supplyId": "calculator",
          "teamId": "5"
        }
      ],
      "pagination": {
        "perPageSize": 10,
        "totalElementCount": 10,
        "totalPage": 1,
        "orderBy": true
      }
    }
  }
}

 

์œ„ ๋‚ด์šฉ์„ ๋ณด๋ฉด ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋‚ด ๋‘ ๊ฐœ์˜ ๊ฐ๊ฐ ์›ํ•˜๋Š” ์‘๋‹ต๊ฐ’์„ ๋ฐ›์€ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.


resources/graphql/graphql/query.graphqls

 

resources/graphql/graphql/query.graphqls

 

์ด๋ ‡๊ฒŒ ๋‘ ๊ฐœ์˜ ์Šคํ‚ค๋งˆ์— ๋Œ€ํ•ด ์กฐํšŒ๋ฅผ ๋‚ ๋ฆฌ๋ฉด ํ•˜๋‚˜์˜ ์š”์ฒญ์œผ๋กœ ๋‘ ๊ฐœ์˜ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.
Join ์ด๋‚˜, ๋‹ค๋ฅธ ๊ฑธ ํ•˜์ง€ ์•Š๊ณ ๋„ ์ด๋ ‡๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์—์š”.

๊ทผ๋ฐ ์œ„์—์„œ Supply๋Š” Http Status Code์™€ Message๋ฅผ ๋ฐ›๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

http://localhost:8080/graphiql?path=/graphql

 

์œ„์™€ ๊ฐ™์ด ๋ฐ›๊ณ  ์‹ถ์ง€ ์•Š๋Š” Field๋ฅผ ์š”์ฒญ์— ๋ณด๋‚ด์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ๋‚ด์šฉ์€ ์‘๋‹ตํ•˜์ง€ ์•Š๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์–ด์š”.
์ด๋ ‡๊ฒŒ Overfetching ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ž์œ ๋กญ๊ฒŒ ์›ํ•˜๋Š” ๊ฐ’๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”.

 

{
  "data": {
    "getEquipmentList": {
      "statusCode": 200,
      "message": "OK",
      "data": [
        {
          "equipmentId": "whiteboard",
          "usedBy": "planner",
          "count": 12,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "sketchb",
          "usedBy": "designer",
          "count": 48,
          "newOrUsed": "new"
        },
        {
          "equipmentId": "pen tablet",
          "usedBy": "developer",
          "count": 15,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "notebook",
          "usedBy": "planner",
          "count": 37,
          "newOrUsed": "new"
        },
        {
          "equipmentId": "machanical keyboard",
          "usedBy": "developer",
          "count": 24,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "ergonomic mouse",
          "usedBy": "designer",
          "count": 31,
          "newOrUsed": "used"
        },
        {
          "equipmentId": "dual monitor",
          "usedBy": "developer",
          "count": 20,
          "newOrUsed": "used"
        }
      ],
      "pagination": {
        "perPageSize": 7,
        "totalElementCount": 7,
        "totalPage": 1
      }
    },
    "getSupplyList": {
      "data": [
        {
          "supplyId": "webcam",
          "teamId": "2"
        },
        {
          "supplyId": "usb hub",
          "teamId": "3"
        },
        {
          "supplyId": "t shirt",
          "teamId": "5"
        },
        {
          "supplyId": "stempler",
          "teamId": "4"
        },
        {
          "supplyId": "mug",
          "teamId": "1"
        },
        {
          "supplyId": "hoodie",
          "teamId": "2"
        },
        {
          "supplyId": "headphone",
          "teamId": "4"
        },
        {
          "supplyId": "ergonomic mouse",
          "teamId": "1"
        },
        {
          "supplyId": "chair",
          "teamId": "3"
        },
        {
          "supplyId": "calculator",
          "teamId": "5"
        }
      ],
      "pagination": {
        "perPageSize": 10,
        "totalElementCount": 10,
        "totalPage": 1,
        "orderBy": true
      }
    }
  }
}

 

์œ„์˜ ์‹ค์Šต์„ ํ†ตํ•ด Underfetching ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ ๋˜๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.

 

 

 

 

 

 

        ๐Ÿ“ฆ ๋‘ ๋ฒˆ์˜ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์กฐํšŒ - REST API๋„ ๊ตฌ์„ฑํ•ด ๋ณด๊ธฐ

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ๋‘ ๋ฒˆ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ๋ฅผ ํ†ตํ•ด ํ•œ๋ฒˆ์— ๊ฐ’์„ ๋ฐ˜ํ™˜ ๋ฐ›๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ ํ•ด๋ณด๋ ค ํ•ด์š”.

์ฃผ๋‹ˆ๋Š” teamId๋ฅผ ์ด์šฉํ•ด์„œ Team๊ณผ People ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌ์„ฑํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.

kotlin/com/junyharangstudy/kotlingraphqltest/api/team/resolver/TeamResolver.kt


์œ„ Resolver(๋ฆฌ์กธ๋ฒ„)๋Š” 
teamId๋ฅผ ๋ฐ›์•„ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” Router์—์š”.


kotlin/com/junyharangstudy/kotlingraphqltest/api/team/service/TeamService.kt


๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์œ„์™€ ๊ฐ™์ด ๋˜์–ด ์žˆ๋Š”๋ฐ, 72๋ฒˆ์งธ ์ค„์—์„œ JPA์˜ findById()๋ฅผ ํ†ตํ•ด team ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋„๋กํ•˜์˜€์–ด์š”.



kotlin/com/junyharangstudy/kotlingraphqltest/api/people/repository/PeopleRepository.kt


๊ทธ๋Ÿฐ ๋’ค 78๋ฒˆ์งธ ์ค„์— JPA findAllByTeamId()๋ฅผ ๋งŒ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ teamId๋ฅผ ์ „๋‹ฌํ•˜๊ณ , ์†Œ์† ์‚ฌ๋žŒ๋“ค ์ •๋ณด๋ฅผ ๋ชจ๋‘ ์กฐํšŒํ•˜์—ฌ List์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•˜์˜€์–ด์š”.

์ด ๋•Œ, map์„ ์ด์šฉํ•˜์—ฌ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ฆฌ๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒ๋œ People Entity๋ฅผ PeopleResponseDto๋กœ ๋ณ€ํ™˜ํ•œ ๋’ค ์ด๋ฅผ ๋‹ค์‹œ List ์ƒ์ˆ˜ ๋ณ€์ˆ˜ findAllMemberByTeamId๋กœ ๋ฐ›๊ฒŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋Ÿฐ ๋’ค ์ •์ƒ ์กฐํšŒ๋œ ๋‚ด์šฉ์„ ์‘๋‹ตํ•˜๊ธฐ ์œ„ํ•ด 82๋ฒˆ์งธ ์ค„๊ณผ ๊ฐ™์ด ํ•ด์ฃผ๊ณ , ์‘๋‹ตํ•  ๋•Œ, Team ์ •๋ณด๋Š” ์•„์ง Entity์ด๊ธฐ ๋•Œ๋ฌธ์— TeamAndMemberResponseDto์— ๋งŒ๋“  entityToDto()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ TeamAndMemberResponseDto ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•œ ๋’ค ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.

kotlin/com/junyharangstudy/kotlingraphqltest/api/team/model/dto/response/TeamAndMemerResponseDto.kt


DTO๋Š” ์œ„์™€ ๊ฐ™์ด ๊ตฌ์„ฑ ๋˜์–ด ์žˆ๋Š”๋ฐ, 14๋ฒˆ์งธ members Property(ํ”„๋กœํผํ‹ฐ)๋Š” ํ•œ ๊ฐœ์˜ ํŒ€์— ์†Œ์†๋œ ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด members ๋ณ€์ˆ˜๋ฅผ List๋กœ ํ•˜์—ฌ PeopleResponseDto๊ฐ€ ๋‹ด๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ์„ ์–ธํ•ด ์ฃผ์—ˆ๊ณ , entityToDto()๋ฅผ ํ†ตํ•ด ๊ฐ’์ด ๋‹ด๊ธธ ๋•Œ, 26๋ฒˆ์งธ ์ค„๊ณผ ๊ฐ™์ด ํ”„๋กœํผํ‹ฐ์— ๋‹ด๊ธธ ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•ด ์ฃผ์—ˆ์–ด์š”.

19๋ฒˆ์งธ ์ค„ !!๊ฐ€ ์™œ ๋ถ™์—ˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค๋ฉด? ์ด ๊ณณ์— ๊ด€์‹ฌ์„ ์ฃผ์‹œ๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”.

 

GraphQL๊ณผ Apollo ์—ด ์—ฌ์„ฏ๋ฒˆ์งธ ์ด์•ผ๊ธฐ - Kotlin + Spring Boot์—์„œ GraphQL ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ - ์‹ค์Šต ํ™˜๊ฒฝ ๊ตฌ์„ฑ

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค ์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. qr.kakaopay.com ์ฝ”ํ‹€๋ฆฐ ์™„๋ฒฝ ๊ฐ€์ด๋“œ COUPANG www.coupang.com "์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ

junyharang.tistory.com

 

resources/graphql/graphql/query.graphqls


๊ทธ๋ฆฌ๊ณ  ์œ„ 48๋ฒˆ์งธ ์ค„๊ณผ ๊ฐ™์ด Query Schema(์ฟผ๋ฆฌ ์Šคํ‚ค๋งˆ)๋ฅผ ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

resources/graphql/graphql/other/teamAndMember.graphqls


๋ฐ˜ํ™˜๋˜๋Š” Type์€ ์œ„์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

data ํ•„๋“œ๋Š” ์œ„ DTO๋กœ ์ •์˜๋œ Type ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜๋˜๊ฒŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.
์—ฌ๊ธฐ์„œ ์ฃผ๋ชฉํ•ด์•ผ ํ•  ์ ์€ 16๋ฒˆ์งธ ์ค„์ด์—์š”. 16๋ฒˆ์งธ ์ค„์— ํ•„๋“œ ์ด๋ฆ„(members)์™€ 4๋ฒˆ์งธ ์ค„ ๋ฐ˜ํ™˜๋˜๋Š” DTO์˜ ๋ณ€์ˆ˜๋ช…์ด ์ผ์น˜ํ•ด์•ผ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”. ๋งŒ์•ฝ ๋‹ค๋ฅด๋ฉด Null์ด ๋‹ด๊ฒจ ๋‚˜์˜ฌ๊ฑฐ์—์š”.


query getTeamAndMemberByTeamId {
  getTeamAndMemberByTeamId(teamId: 1) {
    statusCode,
    message,
    data {
      teamId,
      manager,
      office,
      extensionNumber,
      mascot,
      cleaningDuty,
      project,

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


์ด๋ ‡๊ฒŒ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋ฉด teamId๋ฅผ ์ „๋‹ฌํ•˜์—ฌ Team ์ •๋ณด์™€ ํ•ด๋‹น Team์— ์†Œ์†๋œ ์‚ฌ๋žŒ๋“ค ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

๊ทธ๋ฆฌ๊ณ  ์œ„ ๋‚ด์šฉ์„ REST API๋กœ๋„ ๊ตฌ์„ฑํ•ด ๋ณด๋ ค๊ณ  ํ•ด์š”.

๊ทธ ์ „์— ๋ณด๋‹ค ํŽธ๋ฆฌํ•˜๊ฒŒ API Docs๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” Swagger๋ฅผ ๋จผ์ € ๊ตฌ์„ฑํ•ด ๋ณผ๊ฒŒ์š”.

build.gradle.kts

    //SpringDoc ์˜์กด์„ฑ ์ถ”๊ฐ€
    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui
    implementation 'org.springdoc:springdoc-openapi-ui:1.6.14'


์œ„์™€ ๊ฐ™์ด 
Springdoc-openapi๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์–ด์š”.


kotlin/com/junyharangstudy/kotlingraphqltest/common/config/SwaggerConfig.kt

 

resources/application.yml



์œ„์™€ ๊ฐ™์ด Swagger Config ์ฝ”๋“œ๋„ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์–ด์š”.


kotlin/com/junyharangstudy/kotlingraphqltest/api/team/resolver/TeamRestApiController.kt


์œ„์™€ ๊ฐ™์ด Controller Code๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ์—ˆ์–ด์š”.

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


์œ„์™€ ๊ฐ™์ด ์ ‘์†ํ•˜๋ ค๊ณ  ํ•˜๋ฉด Whitelabel Error๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋ ๊ฑฐ์—์š”.

๊ทธ ์ด์œ ๋Š” Spring Boot 3๋ถ€ํ„ฐ SpringDoc ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•์ด ๋ฐ”๋€Œ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.



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


์ด๋ ‡๊ฒŒ Swagger๊ฐ€ ๋‚˜์˜จ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.



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




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

 

{
  "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



resources/graphql/graphql/query.graphqls


7 ~ 12๋ฒˆ์งธ ์ค„๊ณผ ๊ฐ™์ด ์ฟผ๋ฆฌ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ด ์ฃผ์—ˆ์–ด์š”.

resources/graphql/graphql/equipment/equipment.graphqls



์œ„์™€ ๊ฐ™์ด EquipmentsAdvDto์™€ DefaultEquipmentsAdvResponse๋ผ๋Š” Type์„ ๋ช…์‹œํ•ด ์ฃผ์—ˆ์–ด์š”.


kotlin/com/junyharangstudy/kotlingraphqltest/api/equipment/resolver/EquipmentResolver.kt


๋ฆฌ์กธ๋ฒ„ ์ฝ”๋“œ๋Š” ์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์–ด์š”.


kotlin/com/junyharangstudy/kotlingraphqltest/api/equipment/service/EquipmentService.kt



kotlin/com/junyharangstudy/kotlingraphqltest/api/equipment/service/EquipmentService.kt


๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์œ„์™€ ๊ฐ™์ด ๋งŒ๋“ค์–ด ์ฃผ์—ˆ๋Š”๋ฐ, ๊ฒ€์ƒ‰์„ ํ•  ๊ฒƒ์ธ์ง€ Paging ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ๋ถ„๊ธฐํ•˜์—ฌ ์ƒํ™ฉ์— ๋งž๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

ํ•ด๋‹น ์ฒ˜๋ฆฌ์— ๋Œ€ํ•œ ์ƒ์„ธ ๋‚ด์šฉ์€ ์ด ๊ณณ์„ ์ฐธ๊ณ ํ•ด ์ฃผ์‹œ๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”.

 

GraphQL๊ณผ Apollo ์—ด ์—ฌ์„ฏ๋ฒˆ์งธ ์ด์•ผ๊ธฐ - Kotlin + Spring Boot์—์„œ GraphQL ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ - ์‹ค์Šต ํ™˜๊ฒฝ ๊ตฌ์„ฑ

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค ์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. qr.kakaopay.com ์ฝ”ํ‹€๋ฆฐ ์™„๋ฒฝ ๊ฐ€์ด๋“œ COUPANG www.coupang.com "์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ

junyharang.tistory.com

๋ฐ˜์‘ํ˜•

kotlin/com/junyharangstudy/kotlingraphqltest/api/equipment/service/EquipmentService.kt


์œ„ ์ฝ”๋“œ๋Š” Client์—์„œ ๊ฒ€์ƒ‰ ์กฐ๊ฑด๊ณผ Paging ์ฒ˜๋ฆฌ ์กฐ๊ฑด์„ ๋ณด๋ƒˆ์„ ๋•Œ, ํ˜ธ์ถœ๋˜๋Š” ๋ฉ”์„œ๋“œ์—์š”.
QueryDSL์„ ํ†ตํ•ด Paging ์ฒ˜๋ฆฌ์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฒ€์ƒ‰์ด ์ฒ˜๋ฆฌ๋˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งœ ๋ณด์•˜์–ด์š”.

QueryDSL์„ ์ด์šฉํ•˜์—ฌ ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•œ ๊ฒ€์‚ฌ์™€ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ ๋‚ด์šฉ์€ ์ด ๊ณณ์„ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

 

GraphQL๊ณผ Apollo ์—ด ์—ฌ์„ฏ๋ฒˆ์งธ ์ด์•ผ๊ธฐ - Kotlin + Spring Boot์—์„œ GraphQL ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ - ์‹ค์Šต ํ™˜๊ฒฝ ๊ตฌ์„ฑ

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค ์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. qr.kakaopay.com ์ฝ”ํ‹€๋ฆฐ ์™„๋ฒฝ ๊ฐ€์ด๋“œ COUPANG www.coupang.com "์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ

junyharang.tistory.com


185๋ฒˆ์งธ ์ค„์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒ๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ฆฌ๋ฉด์„œ Entity ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ map์„ ํ†ตํ•ด EquipmentAdvResponsDto๋กœ ๋ณ€ํ™˜ํ•ด ์ฃผ๋Š” ์ž‘์—…์„ ํ•ด์š”.

๊ทธ๋Ÿฐ ๋’ค 194๋ฒˆ์งธ ์ค„์— ์กฐํšŒ๋œ Entity ๊ฐ์ฒด์— usedBy ๊ฐ’์ด developer๋ผ๋ฉด ๋žœ๋ค ์ˆซ์ž(์†Œ์ˆ˜์  2๋ฒˆ์งธ ์ž๋ฆฌ๊นŒ์ง€)๋ฅผ ์ƒ์„ฑํ•˜์—ฌ DTO ๊ฐ์ฒด useRate ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์ด ๋‹ด๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.


๊ทธ๋Ÿฐ ๋’ค 198๋ฒˆ์งธ ์ค„์—์„œ Entity ๊ฐ์ฒด์— newOrUsed ๊ฐ’์ด new ๋ผ๋ฉด DTO ๊ฐ์ฒด isNew ํ”„๋กœํผํ‹ฐ์— ture๊ฐ€ ๋‹ด๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์—ˆ์–ด์š”.

์•„๋‹ˆ๋ผ๋ฉด? false๊ฐ€ ๋‹ด๊ธธ ๊ฑฐ์—์š”.

๊ทธ๋ฆฌ๊ณ , 200๋ฒˆ์งธ ์ค„์—์„œ ์ด๋ ‡๊ฒŒ ๋ฐ˜๋ณตํ•˜์—ฌ ์ฒ˜๋ฆฌ๋œ ๋‚ด์šฉ์„ ์ƒˆ๋กœ์šด List์— ๋‹ด๊ธธ ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•ด ์ค€ ๊ฑฐ์—์š”.

์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค์–ด์ง„ List๊ฐ€ ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๋น„์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด List๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋น„์–ด์žˆ๋‹ค๋ฉด ๋น„์–ด์žˆ๋Š” List๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ด ์ฃผ์—ˆ์–ด์š”.

kotlin/com/junyharangstudy/kotlingraphqltest/api/equipment/service/EquipmentService.kt

 

kotlin/com/junyharangstudy/kotlingraphqltest/api/equipment/service/EquipmentService.kt


๋‘ ๋ฉ”์„œ๋“œ๋„ ๋™์ž‘ํ•˜๋Š” ๋กœ์ง์€ ๊ฐ™์•„์š”.

 

http://localhost:8080/graphiql?path=/graphql


์ด๋ ‡๊ฒŒํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค๋ณด๋ฉด ์ •์ƒ์ ์œผ๋กœ Float์™€ Blooen์ด ์ƒ๊ธด ๊ฐ์ฒด๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

 

 

 

 

 

 

        ๐Ÿ“ฆ Enum Type

์ด๋ฒˆ์—๋Š” ์ผ๊ณฑ๋ฒˆ์งธ ์ด์•ผ๊ธฐ์—์„œ ๊ณต๋ถ€ํ•ด๋ดค๋˜ Enum Type์— ๋Œ€ํ•ด ์‹ค์Šตํ•ด ๋ณผ๊ฒŒ์š”.

resources/graphql/graphql/other/enums.graphqls


์œ„์™€ ๊ฐ™์ด Enum Type๋งŒ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” enums.graphqls๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๊ณ , ๊ทธ ์•ˆ์— Enum Type๋“ค์„ ์ •์˜ํ•ด ์ฃผ์—ˆ์–ด์š”.


resources/graphql/graphql/people/people.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/graphql/equipment/equipment.graphqls

 

resources/graphql/graphql/software/software.graphqls

 

์—ฌ๋Ÿ๋ฒˆ์งธ ์ด์•ผ๊ธฐ์—์„œ ์ด์•ผ๊ธฐํ–ˆ๋˜ ๋Œ€๋กœ ์œ„ ๋‘ Type์€ ๊ฐ์ฒด ์ด๋ฆ„ ์ค‘ usedBy๊ฐ€ ๊ฒน์น˜๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.
์ฐธ๊ณ ๋กœ ์—ฌ๋Ÿ๋ฒˆ์งธ ์ด์•ผ๊ธฐ์—์„œ๋Š” ID ๊ฐ์ฒด ์ด๋ฆ„์ด ๋ชจ๋‘ id ์˜€๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ๋„ ๊ฒน์ณค์ง€๋งŒ, ์ฃผ๋‹ˆ๋Š” ์œ ๋‹ˆํฌํ•œ ID ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๊ธฐ ์œ„ํ•ด ์œ„์™€ ๊ฐ™์ด ์ด๋ฆ„์„ ์ •ํ•ด์ฃผ์–ด์„œ ๊ฒน์น˜์ง€ ์•Š๋Š”๊ฑธ ์•Œ ์ˆ˜ ์žˆ์–ด์š”.


์ด ๋ถ€๋ถ„๋งŒ Interface๋กœ ๋”ฐ๋กœ ๋นผ ๋ณผ๊ฒŒ์š”.

resources/graphql/graphql/Interface/interface.graphqls

 

 

 

resources/graphql/graphql/equipment/equipment.graphqls



resources/graphql/graphql/software/software.graphqls

 

๊ทธ๋ฆฌ๊ณ  ์œ„์™€ ๊ฐ™์ด ๊ฐ๊ฐ์˜ Type ๋“ค์ด Tool Interface(์ธํ„ฐํŽ˜์ด์Šค)๋ฅผ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์—ˆ์–ด์š”.


http://localhost:8080/graphiql?path=/graphql

query findeBygetEquipmentAndSoftwareListPagingUseByInterface {
  getEquipmentList (
    pageRequestDto: {
      currentPage: 1,
      perPageSize: 10
      orderBy: true
    },
    equipmentSearchRequestDto: {
      usedBy: "developer"
    }
  ) {
    statusCode,
    message,
    data {
      equipmentId,
      usedBy,
      count,
      newOrUsed
    },
    pagination {
      perPageSize,
      totalElementCount,
      totalPage
    }
  }

  getSoftwareList(
    softwareSearchRequestDto: {
      # usedBy: "developed",
      # developedBy: "",
      # description: ""
    },

    pageRequestDto: {
      currentPage: 1,
      perPageSize: 10,
      orderBy: true
    }
  ) {
    statusCode,
    message,
    data {
      usedBy,
      developedBy,
      description
    },
    pagination {
      perPageSize,
      totalElementCount,
      totalPage,
      orderBy
    }
  }
}


์œ„์™€ ๊ฐ™์ด ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ›๋Š”๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , Equipmensts List์™€ Softwares List ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ด๋ ‡๊ฒŒ ํ•ด์„œ ์ฃผ์š” ์‹ค์Šต์„ ๋ชจ๋‘ ๋งˆ์ณค์–ด์š”.

 

 

 

    ๐Ÿ”ฝ  ์‹ค์Šต ๋งˆ๋ฌด๋ฆฌ

        ๐Ÿ“ฆ ์งง์€ ํšŒ๊ณ 

์žํ”„๋ง, Nest.ts ๊ทธ๋ฆฌ๊ณ , ์ฝ”ํ”„๋ง๊นŒ์ง€! ์ฃผ๋‹ˆ๊ฐ€ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์–ธ์–ด์™€ Framework๊ฐ€ ๋Š˜์–ด๋‚˜์„œ ๋„ˆ๋ฌด ๊ธฐ๋ถ„ ์ข‹์•„์š”.
๊ทธ๋ฆฌ๊ณ , GraphQL๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑด ๋ถ„๋ช… ๋„์›€์ด ๋งŽ์ด ๋  ๊ฑฐ์—์š”.

Spring Boot 3๋กœ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด์„œ Swagger, QueryDSL ์„ค์ • ๋“ฑ์ด ๋ณ€๊ฒฝ ๋˜์—ˆ์ง€๋งŒ, ์ด๋ ‡๊ฒŒ GraphQL ์ด๋ผ๋Š” ์ฃผ์ œ ํ•˜๋‚˜๋กœ ์—ฌ๋Ÿฌ๊ฐ€์ง€๋ฅผ ๊ณต๋ถ€ํ•˜๊ณ , ๊ฒฝํ—˜ํ•ด ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์†Œ์ค‘ํ•œ ์‹œ๊ฐ„์ด์˜€์–ด์š”.

 

 

 

์Šคํ”„๋ง ๋ถ€ํŠธ 3 ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž ๋˜๊ธฐ : ์ž๋ฐ” ํŽธ

COUPANG

www.coupang.com

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."

 

 

 

 

 

์นด์นด์˜คํŽ˜์ด | ๋งˆ์Œ ๋†“๊ณ  ๊ธˆ์œตํ•˜๋‹ค

์—ฌ๊ธฐ๋ฅผ ๋ˆŒ๋Ÿฌ ๋งํฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

qr.kakaopay.com

 

 

 

728x90
๋ฐ˜์‘ํ˜•