๐Ÿš€ GraphQL APIs ์„ค๋ช… (์‹ค์ œ Node.js ์˜ˆ์ œ์™€ ํ•จ๊ป˜)

๋ฐœํ–‰: (2025๋…„ 12์›” 25์ผ ์˜คํ›„ 02:33 GMT+9)
7 ๋ถ„ ์†Œ์š”
์›๋ฌธ: Dev.to

Source: Dev.to

REST๋Š” ์–ด๋””์—๋‚˜ ์กด์žฌํ•˜์ง€๋งŒ, GraphQL์€ ํ˜„๋Œ€ API๊ฐ€ ๊ตฌ์ถ•๋˜๋Š” ๋ฐฉ์‹์„ ๋ฐ”๊พธ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ ๋ฐฐ์šฐ๊ฒŒ ๋  ๋‚ด์šฉ:

  • GraphQL์ด ์‹ค์ œ๋กœ ๋ฌด์—‡์ธ์ง€
  • ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ (์ „๋ฌธ ์šฉ์–ด ์—†์ด)
  • ์‹ค์ œ Node.js GraphQL API ์˜ˆ์ œ
  • ์žฅ์ ๊ณผ ๋‹จ์  (๋งˆ์ผ€ํŒ… ๊ณผ๋Œ€๊ด‘๊ณ  ์—†์ด)
  • NOT ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒฝ์šฐ

๐Ÿค” GraphQL์ด๋ž€?

GraphQL์€ API๋ฅผ ์œ„ํ•œ ์ฟผ๋ฆฌ ์–ธ์–ด์ด๋ฉฐ, ํ•ด๋‹น ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋Ÿฐํƒ€์ž„์ž…๋‹ˆ๋‹ค.
REST์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹ , GraphQL์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ •ํ™•ํžˆ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ผ ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค โ€” ๋” ๋งŽ์ง€๋„, ์ ์ง€๋„ ์•Š๊ฒŒ.

REST ์˜ˆ์‹œ

GET /users/1
GET /users/1/posts
GET /users/1/followers

GraphQL ์˜ˆ์‹œ

query {
  user(id: 1) {
    name
    posts {
      title
    }
    followers {
      name
    }
  }
}

ํ•˜๋‚˜์˜ ์š”์ฒญ. ํ•˜๋‚˜์˜ ์‘๋‹ต. ์ •ํ™•ํ•œ ๋ฐ์ดํ„ฐ.

๐Ÿง  GraphQL์ด ์ธ๊ธฐ๋ฅผ ๋ˆ ์ด์œ 

์ „ํ†ต์ ์ธ REST API๋Š” ์˜ค๋ฒ„ํŒจ์นญ(๋ฐ ์–ธ๋”ํŒจ์นญ) ๋ฌธ์ œ๋ฅผ ๊ฒช์Šต๋‹ˆ๋‹ค. GraphQL์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‘๋‹ต ํ˜•ํƒœ๋ฅผ ์ œ์–ดํ•˜๋„๋ก ํ•จ์œผ๋กœ์จ ์ด๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

โš™๏ธ GraphQL ์ž‘๋™ ๋ฐฉ์‹ (๊ฐ„๋‹จ ์„ค๋ช…)

GraphQL์—๋Š” ์„ธ ๊ฐ€์ง€ ํ•ต์‹ฌ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  1. Schema โ€“ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค (๊ณ„์•ฝ)
  2. Queries / Mutations โ€“ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
  3. Resolvers โ€“ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜

๐Ÿงฉ GraphQL vsโ€ฏREST (๋น ๋ฅธ ๋น„๊ต)

FeatureGraphQLREST
Endpoint countSingle endpointMultiple endpoints
Data fetchingClientโ€‘specified shapeFixed responses per endpoint
Over/underโ€‘fetchingEliminatedCommon issue
Tooling & typingStrongly typed schema, autoโ€‘completeVaries per implementation

Source:

๐Ÿงช ์‹ค์ œ GraphQL API ์˜ˆ์ œ (Node.js)

๐Ÿ“ฆ ์˜์กด์„ฑ ์„ค์น˜

npm init -y
npm install @apollo/server graphql

๐Ÿ—‚๏ธ index.js ๋งŒ๋“ค๊ธฐ

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

const users = [
  { id: "1", name: "Anshul", role: "Full Stack Developer" },
  { id: "2", name: "Rohit", role: "Backend Developer" }
];

// 1๏ธโƒฃ ์Šคํ‚ค๋งˆ
const typeDefs = `#graphql
  type User {
    id: ID!
    name: String!
    role: String!
  }

  type Query {
    users: [User]
    user(id: ID!): User
  }
`;

// 2๏ธโƒฃ ๋ฆฌ์กธ๋ฒ„
const resolvers = {
  Query: {
    users: () => users,
    user: (_, { id }) => users.find(u => u.id === id)
  }
};

// 3๏ธโƒฃ ์„œ๋ฒ„
const server = new ApolloServer({
  typeDefs,
  resolvers
});

const { url } = await startStandaloneServer(server, {
  listen: { port: 4000 }
});

console.log(`๐Ÿš€ GraphQL Server ready at ${url}`);

๐Ÿ” API ์ฟผ๋ฆฌํ•˜๊ธฐ

๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:4000 ๋ฅผ ์—ด๊ณ  ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:

query {
  users {
    name
    role
  }
}

๊ฒฐ๊ณผ: ์š”์ฒญํ•œ ํ•„๋“œ๋งŒ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹คโ€”์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ๋Š” ์—†์Šต๋‹ˆ๋‹ค.

โœ๏ธ ๋ฎคํ…Œ์ด์…˜ (๋ฐ์ดํ„ฐ ์ƒ์„ฑ / ์—…๋ฐ์ดํŠธ)

mutation {
  createUser(name: "Amit", role: "Frontend Dev") {
    id
    name
  }
}

๋ฎคํ…Œ์ด์…˜์€ GraphQL์—์„œ POST/PUT/DELETE์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ…ฐ๏ธ GraphQL with Angular (ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์‚ฌ๋ž‘ํ•˜๋Š” ์ด์œ )

  • ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ๊ฐ€์ ธ์˜ค๊ธฐ
  • API ํ˜ธ์ถœ ์ˆ˜ ๊ฐ์†Œ โ†’ UI ๋ Œ๋”๋ง ์†๋„ ํ–ฅ์ƒ
  • ๋ชจ๋ฐ”์ผ ์•ฑ ๋ฐ ๋ณต์žกํ•œ ๋Œ€์‹œ๋ณด๋“œ์— ์ด์ƒ์ 

์ธ๊ธฐ ์žˆ๋Š” Angular GraphQL ๋„๊ตฌ

  • Apollo Angular
  • GraphQL Code Generator
  • ๊ฐ•๋ ฅํ•œ TypeScript ์ง€์›

โœ… GraphQL์˜ ์žฅ์ 

  1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ œ์–ดํ•˜๋Š” ๋ฐ์ดํ„ฐ โ€“ ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ์ •ํ™•ํžˆ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  2. ๋‹จ์ผ ์—”๋“œํฌ์ธํŠธ โ€“ ์—”๋“œํฌ์ธํŠธ ํญ๋ฐœ์ด ์—†์Šต๋‹ˆ๋‹ค.
  3. ๊ฐ•๋ ฅํ•œ ํƒ€์ž… ์Šคํ‚ค๋งˆ โ€“ ์ž๋™ ์™„์„ฑ, ๊ฒ€์ฆ, ํ–ฅ์ƒ๋œ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜.
  4. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ ์†๋„ ํ–ฅ์ƒ โ€“ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  5. ๋ณต์žกํ•œ UI์— ์ตœ์  โ€“ ๋Œ€์‹œ๋ณด๋“œ, ๋ชจ๋ฐ”์ผ ์•ฑ, ์‹ค์‹œ๊ฐ„ ์‹œ์Šคํ…œ ๋“ฑ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

โŒ GraphQL์˜ ๋‹จ์  (์ค‘์š”!)

  1. ํ•™์Šต ๊ณก์„ ์ด ๊ฐ€ํŒŒ๋ฆ„ โ€“ ์Šคํ‚ค๋งˆ, ๋ฆฌ์กธ๋ฒ„, ์ฟผ๋ฆฌ ๋ฌธ๋ฒ•์ด ์ดˆ๋ณด์ž์—๊ฒŒ ์นœ์ˆ™ํ•˜์ง€ ์•Š์Œ.
  2. ์บ์‹ฑ์ด ์–ด๋ ค์›€ โ€“ REST๋Š” ๋‚ด์žฅ๋œ HTTP ์บ์‹ฑ์„ ํ™œ์šฉํ•˜์ง€๋งŒ, GraphQL์€ ๋งž์ถคํ˜• ์†”๋ฃจ์…˜์ด ํ•„์š”ํ•จ.
  3. ์ฟผ๋ฆฌ ๋ณต์žก๋„ โ€“ ๋ชจ๋‹ˆํ„ฐ๋ง๋˜์ง€ ์•Š์€ ์ž˜๋ชป๋œ ์ฟผ๋ฆฌ๋Š” ์„œ๋ฒ„์— ๊ณผ๋ถ€ํ•˜๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Œ.
  4. ๋‹จ์ˆœ CRUD API์— ์ ํ•ฉํ•˜์ง€ ์•Š์Œ โ€“ ๋‹จ์ˆœํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ๋Š” ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ด์ ์„ ์ƒ์‡„ํ•  ์ˆ˜ ์žˆ์Œ.

๐Ÿšซ GraphQL์„ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒฝ์šฐ

  • ๋งค์šฐ ๊ฐ„๋‹จํ•œ CRUD API
  • HTTP ์บ์‹œ ์˜์กด๋„๊ฐ€ ๋†’์€ ๊ฒฝ์šฐ
  • ๊ทœ๋ชจ๊ฐ€ ์ž‘๊ฑฐ๋‚˜ ๊ฒฝํ—˜์ด ๋ถ€์กฑํ•œ ํŒ€
  • ๋ณต์žกํ•œ ํด๋ผ์ด์–ธํŠธโ€‘์‚ฌ์ด๋“œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ์ด ์—†๋Š” ๊ฒฝ์šฐ

๐Ÿง  When GraphQL Is the BEST Choice

  • ์—ฌ๋Ÿฌ ํ”„๋ก ํŠธ์—”๋“œ ํด๋ผ์ด์–ธํŠธ(์›น, ๋ชจ๋ฐ”์ผ ๋“ฑ)
  • ๋‹ค์–‘ํ•œ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ ์ง‘๊ณ„
  • ๋น ๋ฅธ UI ๊ฐœ๋ฐœ ํ•„์š”
  • ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ณ  ๋ฐ์ดํ„ฐ ์ง‘์•ฝ์ ์ธ ์‹œ์Šคํ…œ ๊ตฌ์ถ•

๐Ÿ”ฅ GraphQL + Node.js ์Šคํƒ (ํŠธ๋ Œ๋”ฉ)

  • Node.js + TypeScript
  • NestJS / Apollo Server
  • Angular / React ํ”„๋ก ํŠธ์—”๋“œ
  • GraphQL Code Generator ๋ฅผ ์‚ฌ์šฉํ•œ ํƒ€์ž… ์•ˆ์ „์„ฑ
  • JWT + ์—ญํ•  ๊ธฐ๋ฐ˜ ์ธ์ฆ

Source: Source on Medium

๐Ÿ ์ตœ์ข… ์ƒ๊ฐ

GraphQL์€ REST๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ๋‹ค์ˆ˜์˜ ์†Œ๋น„์ž๊ฐ€ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ ๋น›์„ ๋ฐœํ•˜๋Š” ๋ณด์™„์ ์ธ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์ „์ฒด ์Šคํƒ Angularโ€ฏ+โ€ฏNode.js ๊ฐœ๋ฐœ์ž๋ผ๋ฉด, ํˆดํ‚ท์— GraphQL์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด ๋ณด์„ธ์š”.

์ด ๊ธ€์ด ๋งˆ์Œ์— ๋“œ์…จ๋‹ค๋ฉด, ๋ฐ•์ˆ˜๋ฅผ ์น˜๊ฑฐ๋‚˜, ๊ณต์œ ํ•˜๊ฑฐ๋‚˜, โ€œGRAPHQLโ€์ด๋ผ๊ณ  ๋Œ“๊ธ€์„ ๋‹ฌ์•„ ์ฃผ์„ธ์š”. ๋” ๊นŠ์€ Angularโ€ฏ+โ€ฏGraphQL ํŠœํ† ๋ฆฌ์–ผ์„ ์ œ๊ณตํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป

2015๋…„์ฒ˜๋Ÿผ API๋ฅผ ์ž‘์„ฑํ•˜์ง€ ๋งˆ์„ธ์š”

์šฐ๋ฆฌ๋Š” 2025๋…„์— ์‚ด๊ณ  ์žˆ์œผ๋ฉฐ, ๋งŽ์€ ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ์—ฌ์ „ํžˆ API๋ฅผ ๋‹จ์ˆœํžˆ โ€œJSON์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—”๋“œํฌ์ธํŠธโ€๋กœ๋งŒ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. API ์„ค๊ณ„๊ฐ€ ๊ธฐ๋ณธ CRUD ๋ผ์šฐํŠธ๋ฅผ ๋„˜์–ด ๋ฐœ์ „ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ๋‹น์‹ ์€ sacrโ€ฆ

๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ 5๊ฐœ์›” ์ฐจ์— ๋น„์ „ํ†ต์ ์ธ ์›€์ง์ž„์„ ์‹œ๋„ํ•˜๊ธฐ

๋น„์ „ํ†ต์ ์ธ ๊ฒฐ์ •: ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•œ ์ง€ 5๊ฐœ์›” ๋œ ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ์ง๊ด€์— ๋ฐ˜ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ๋Š” ์›€์ง์ž„์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค: ์ €๋Š” ์ œ f๋ฅผ ๊ฐ•ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ๋Œ์•„๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Middleware-์™„๋ฒฝํ•œ-Symphony

GitHub Home https://github.com/hyperlane-dev/hyperlane ์†Œ๊ฐœ Middleware๋Š” ์›น ๊ฐœ๋ฐœ์—์„œ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ๋˜ํ•œ ๊ฐ€์žฅ โ€ฆ

Laravel 12์—์„œ ํ˜„๋Œ€์ ์ธ API ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์™„์ „ ๊ฐ€์ด๋“œ

์†Œ๊ฐœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ทœ๋ชจ๋ฅผ ํ™•๋Œ€ํ•จ์— ๋”ฐ๋ผ ๊ฒฌ๊ณ ํ•˜๊ณ  ์•ˆ์ „ํ•˜๋ฉฐ ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ API์— ๋Œ€ํ•œ ํ•„์š”์„ฑ์ด ๊ธ‰๊ฒฉํžˆ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” Laravel 12๊ฐ€ ํŠน๋ณ„ํ•œ ์ด์œ ์™€โ€ฆ