Back-End ์ž‘์—…์‹ค/Spring Framework

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

์ฃผ๋‹ˆ์“ฐ๐Ÿง‘‍๐Ÿ’ป 2023. 11. 26. 21:00
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๋ฅผ ํ†ตํ•ด ํ•ด๋ดค๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜์Œ ์‹ค์Šต์€ Overfetching๊ณผ Underfetching์œผ๋กœ ์ง„ํ–‰ํ•ด ๋ณผ๊ฒŒ์š”.

์˜ค๋Š˜์˜ ์ฒซ๋ฒˆ์งธ ์‹ค์Šต์€ 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๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ์–ด์š”!

๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ณ ๋ง™์Šต๋‹ˆ๋‹ค!

๋‹ค์Œ์—๋Š” TypeScript์™€ Nest.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
๋ฐ˜์‘ํ˜•