graphql.org/

 

GraphQL | A query language for your API

Evolve your APIwithout versions Add new fields and types to your GraphQL API without impacting existing queries. Aging fields can be deprecated and hidden from tools. By using a single evolving version, GraphQL APIs give apps continuous access to new featu

graphql.org

 

⭐ GraphQL을 시작하면서

처음에 GraphQL을 말로만 많이 들었지 잘 몰랐었는데 이번 사이드 프로젝트를 하면서 백엔드분이 GraphQL 도입하자고 하셔서 이 기회에 GraphQL에 대해서 공부해보았다. 원래는 FN 개발자 입장으로써 GraphQL에 API 연동해주는 Apollo만 사용해보려 했으나 API를 직접 만들어보는 것도 좋은 경험이니 도전해봤다. GraphQL을 단번에 이해시켜주는데 도움이 컸던 노마드코더 니꼴라스님의 영상을 보며 GraphQL API를 직접 따라 구현해보니 정말 매력적이라고 느꼈다. 👀

 

nomadcoders.co/graphql-for-beginners/lobby

이 영상보면서 영화 REST API를 GraphQL API로 감싸는 작업(Wrappering)까지 수월하게 할 수 있었다.

 


⭐ GraphQL이란 ?

GraphQL은 페이스북에서 만든 API를 위한 쿼리 언어이다. 그리고 GraphQL이 REST보다 API 만드는 것에 훨씬 더 간편하다. 그만큼 백엔드 개발을 쉽게 만들어 준다. GraphQL API를 만들기 위해서는 node와 자바스크립트 백엔드에 익숙해야 한다.

이게 바로 Query 언어입니다

 

 

⭐️ GraphQL  API의 장점

 

GraphQL은 번거로운 오버패치와 언더패치의 단점들을 해결해준다. 즉, GraphQL은 Over-fetching 없이 코드를 짤 수 있고 개발자가 어떤 정보를 원하는지에 대해 통제할 수도 있다. 그리고 Under-fetching을 겪을 필요도 없다. 한 쿼리에 내가 정확하게 원하는 정보만 받을 수 있다. 백엔드 개발자는 API 만들기에 쉽고 프론트엔드 개발자는 구체적이고 정확하게 받아오고 싶은 데이터들만 뽑아 써먹을 수 있음으로 백엔드와 프론트 개발자 모두에게 편리한 라이브러리 인 듯. 

  • Over-fetching : 내가 요청한 영역의 정보보다 더 많은 정보를 서버에서 받는다. 즉, 쓸모없는 정보들도 받게된다. 이는 비효율적이고 개발자들이 뭘 받았는지 모르게 된다.
  • Under-fetching : 어떤 하나를 완성하기위해 다른 요청들을 해야할 때 발생한다. 예를들어 인스타를 만들면 페이지의 피드를 받고 알림도 받고 사용자 프로필도 받게된다. 앱을 처음 시작하려면 이 세가지 요청을 해야 함 ! 즉 3가지 요청이 3번 오고가야 앱이 시작된다는 것이다. 이처럼 REST에서 하나를 완성하려고 많은 소스를 요청하는 것이 Under-fetching이다.

 

⭐️ GraphQL 구조

  • Query (쿼리 = 데이터)
  • Mutation (변형)
  • Subscription (설명)

Query 는 객체 구조로 표현한다. Query는 읽기를 요청하는 구문이고 Mutation은 수정을 요청하는 구문이다. Mutation을 통해 쿼리들을 추가 할 수도 삭제 할 수도 있다. GraphQL 서버에서는 정적인 타입 시스템을 사용해 데이터를 표현하는 Schema가 존재하고, 각 타입의 필드에 대한 함수로 구성된다. 그리고 하나의 EndPoint를 사용함으로써 RESTful API에서 생기는 많은 Enpoint의 복잡성을 줄여줄 수 있다. 이참에 RESTful API와 GraphQL API를 비교해보자

 

  1. RESTful API

    • Resource마다 Endpoint를 갖게 된다.
    • 클라이언트마다 필요한 데이터를 각 Resource 종류별로 요청해야 한다. (요청 횟수가 늘어날 수 있음)
    • Endpoint가 늘어날 수록 관리하기 힘들어진다.
    • 요청과 응답 구조가 미리 정의되어 있다. 때문에 HTTP에 대한 Caching이 가능한 것이 장점이다.
  2. GraphQL

  • HTTP 요청의 횟수를 줄일 수 있다. (원하는 정보를 하나의 쿼리에 모두 담아 요청 가능)
  • HTTP 응답의 사이즈를 줄일 수 있다. (필요한 정보만 부분적으로 요청가능)

 

이처럼 GraphQL은 REST API의 단점들을 보완해주는 역할을 하고 있는데 단점 또한 물론 갖고있다.

⭐ GraphQL의 단점

  • 재귀적인 쿼리가 불가능하다. 결과에 따라 응답의 깊이가 얼마든지 깊어질 수 있는 API를 만들 수 없음
  • 고정된 요청과 응답만 필요한 경우 쿼리로 인해 요청의 크기가 REST API의 경우보다 더 커진다고 한다.

단점에 대한 정보 출처(velog.io/@djaxornwkd12/REST-API-vs-GraphQL-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0)


⭐ GraphQL  API 생성하는데 필요한 것

백엔드가 기존에 API를 만들기 위해서는 장고나 express를 사용하며 데이터를 받아오기까지 각종 프레임워크를 사용하고 작업시간이 오래걸린다고 하는데 그에 비해 GraphQL은 정말 간단명료하게 만들 수 있다. 바로 이 4개의 파일들만 있으면 가능하다.

  • index
  • schema
  • resolvers
  • db

 

- index



가장먼저 해줘야 될 것이 index 작업이다. graphql 세팅해주는 작업이고, 먼저 graphql-yoga 패키지를 설치해줘야 한다. 이걸 설치하는 이유는 그래프큐엘 요가에서 제공해주는 플레이그라운드로 데이터들을 불러오기 때문이다. 그리고 서버명과 resolver를 불러오고 서버가 실행되면 커맨드창에 표시되게 해주자

 

- 스키마 [schema.graphql]

schema.graphql

이제 스키마를 짜줘야한다. graphql은 정적인 타입 시스템을 사용해 데이터를 표현한다. 스키마 Movie에 들어갈 데이터들의 타입들을 정의해주는데, 여기서 쓰인 ! 느낌표는 서비스가 항상 값을 제공하겠다는 약속이다. 그리고 스키마를 짜주면서 동시에 resolvers도 같이 해줘야 한다.

 

- [resolvers.js]

resolvers란?

Query를 해결해준다는 뜻이다. Query는 우리가 가진 데이터베이스에 문제같은 것이다. 그래서 우린 이 Query를 어떤 방식으로 해결(resolve)해야 한다. GraphQL에선 views나 urls같은건 없다. 오직 Query랑 resolvers만 있을 뿐이다. 그리고 resolvers를 내 원하는대로 프로그래밍 할 수 있다. DB로 갈 수도 있고 메모리로도 갈 수 있고 다른 API로도 갈 수 있다. 내 맘대로 가능하다 🙂

 

왼쪽 resolvers, 오른쪽 schema 데이터

 

- [db.js] 데이터베이스 관리하는 파일

 json 파일로 만들어진 영화 REST API를 graphQL로 랩핑 (wrapping) 해주는 과정이다. 이렇게 하고 http://localhost:4000/ 에 접속하면 GraphQL 플레이그라운드가 나온다.  

 

플레이그라운드

이처럼 플레이그라운드에서 쿼리로 movies 객체 안에 들어있는 데이터값들을 볼 수 있으며 mutations로 변형시킬 수도 있는 것을 DOCS에서 확인해볼 수 있다. Mutations으로 데이터를 추가할수도, 삭제도 가능하다.

 

안녕하세요~ 이번에는 바벨(Babel)에 대해 알아보려고 합니다. 😃

 

바벨은 크로스 브라우징의 혼란을 해결해 줄 수 있답니다. 모든 브라우저에서 동작하도록 호환성을 지켜주지요. 타입스크립트, JSX처럼 다른 언어로 분류되는 것도 포함입니다. 먼저 바벨을 사용하려면 패키지들을 설치해주어야 합니다.

 

설치명령어

$npm install @babel/core @babel/cli

@babel/cli는 바벨 터미널을 사용하기 위해 설치해요. 바벨 실행 할 때는 터미널창에

npx babel app.js

를 입력해서 실행하면 됩니다.

 

바벨은 세 단계로 빌드를 진행합니다 !

1. 파싱 : 단어들을 분해하는 과정이라고 보면 됩니다.

const alert = (msg) => window.alert(msg);

이 코드를 봤을 때 const 라는 토큰과 alert라는 토큰과 이렇게 일일이 분해해서 봅니다.

2. 변환 : ES6를 ES5로 변환해주고 마지막으로

3. 출력 해줍니다.

 

1. block-scoping

ES6 문법을 ES5 문법으로 변환해주는 것이 block-scoping 플러그인 입니다. const와 let 처럼 블록 스코핑을 따르는 예약어를 함수 스코핑을 사용하는 var로 변경해줍니다.

$npm install -D @babel/plugin-transform-block-scoping

터미널창에  block-scoping를 설치하고

npx babel app.js --plugins @babel/plugin-transform-block-scoping

위 명령어를 입력하면 var alert = msg => window.alert(msg); 이렇게 출력되는 것을 확인해 볼 수 있습니다.

 

2. transform-arrow-functions

이 플러그인은var alert = msg => window.alert(msg); 여기서 사용된 var는 브라우저 익스플로어에서 인식을 해주는데 => 이 화살표 함수는 브라우저가 인식하지 못합니다. 이거를 변환시켜주는 플러그인이 바로 transform-arrow-functions 플러그인 입니다.

$npm install -D @babel/plugin-transform-arrow-functions

터미널창에 transform-arrow-functions를 설치하고

npx babel app.js --plugins @babel/plugin-transform-block-scoping --plugins @babel/plugin-transform-arrow-functions

위 명령어를 입력해보세요. 그리고 출력된 결과물을 보면

var alert = function (msg) {
  return window.alert(msg);
};

화살표 함수가 사라지고 ES6 문법으로 변환된 것을 확인 됩니다 !

 

 

3. strict-mode

안전하게 작업하려면 엄격모드를 사용해야 합니다. 'use strict' 구문을 추가해야 하므로 strict-mode 플러그인을 설치합시다. 

$npm install @babel/plugin-transform-strict-mode

플러그인이 설치되었다면

npx babel app.js --plugins @babel/plugin-transform-block-scoping --plugins @babel/plugin-transform-arrow-functions

위 명령어를 입력해보세요!

"use strict";

var alert = function (msg) {
  return window.alert(msg);
};

그럼 상단에  use strict가 찍히면서 엄격모드로 변환된 것이 나타납니다. 그리고 플러그인을 사용할 때 명령어들을 모두 사용하려다 보니 커맨드라인 명령어가 점점 길어지기 때문에 설정 파일로 분리하는 것이 좋습니다.

바벨 환경설정 파일인 [babel.config.js] 에서 설정해주시면 되는데요.

module.exports = {
  plugins: [
    "@babel/plugin-transform-block-scoping",
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-strict-mode",
  ],
};

이렇게 바벨 기본 설정파일에 그간 설치했던 플러그인들을 담아두면 커맨드 창에 npx babel app.js만 입력하여도 알아서 전부 동작됩니다.

또 다른 방법으로는 프리셋을 사용하시면 됩니다.

 

프리셋

목적에 맞게 여러가지 플러그인을 세트로 모아놓은 것을 프리셋이라고 합니다. [my-babel-preset.js] 라는 파일을 만들어 그동안 설치했던 플러그인들을 담아놓아요.

module.exports = function myBabelPreset() {
  return {
    Plugins: [
      "@babel/plugin-transform-block-scoping",
      "@babel/plugin-transform-arrow-functions",
      "@babel/plugin-transform-strict-mode",
    ],
  };
};

 

그리고 기존에 [babel.config.js] 파일에는

module.exports = {
  presets: ["./my-babel-preset.js"],
};

프리셋 파일을 불러와줍니다. 그럼 프리셋에 있는 모든 플러그인들이 실행 됩니다.

지금까지 했던 과정들은 바벨에 대한 이해를 돕기 위한 시행이었고 사실 이렇게 바벨을 사용하는 것은 실무에서는 잘 쓰이지 않습니다.

다음편에는 바벨을 실무로는 어떻게 사용하는지 알아보겠습니다 !! 😃

안녕하세요 오늘은 웹팩에서 자주 사용하는 플러그인에 대해서 알아보려고 합니다 ! 총 5가지가 있구요. 기능부터 알아봅시다 :)

 

  • 🐥 BannerPlugin : 번들링 된 결과물 상단에다가 빌드 정보를 추가하는 역할이다. 잘 배포 되었는지 확인해보는 용도
  • 🐥 DefinePlugin : API 서버 주소를 넣음 좋다.
  • 🐥 HtmlTemplatePlugin : 이 플러그인은 동적으로 생성되는 자바스크립트와 css 그리고 빌드 타임에 결정되는 값들을 템플릿 파일에 넣어서 html파일을 동적으로 만들어낸다.
  • 🐥 CleanWebpackPlugin : src 경로에 있던 파일들을 빌드하면 dist 폴더에 남는다. 근데 src 폴더에 있는 파일을 삭제해도 dist 폴더에 남아있다. 그래서 얘는 src폴더와 dist폴더에 있는 값들이 비례하게 빌드할 때마다 dist에 남아있는 파일이나 폴더들을 제거해주는 역할이다.
  • 🐥 MiniCssExtractPlugin : 번들된 자바스크립트 파일에서 css만 따로 뽑아내서 css파일만 만들어 내는 플러그인이다.

 


플러그인도 [webpack.config.js] 웹팩 환경설정 파일에 설정 할 수 있고, 로더처럼 사용하시면 됩니다. 

const path = require("path");
const webpack = require("webpack");
const childProcess = require("child_process");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

하지만 로더와 다른 점이 플러그인은 상단에 설치한 플러그인들을 import 해줘야 합니다.

 

1. BannerPlugin

결과물에 빌드 정보나 커밋 버전 같은 걸 추가할 수 있어요. 배포 했을 때 배포가 잘 됐는지 이걸 통해 확인해요.

plugins: [
    new webpack.BannerPlugin({
      banner: `
      Build Date: ${new Date().toLocaleString()}
      Commit Version: ${childProcess.execSync("git rev-parse --short HEAD")}
      Author: 이현주(LeeHyunJu)
      `,
    }),
    ]

입력하고 빌드 했을 시 dist/main.js에 가면 banner 함수에 입력된 내용들이 나타납니다.

  •  Build Date: ${new Date().toLocaleString()}  👉🏻 오늘 날짜를 뽑아내줍니다.
  •  Commit Version: ${childProcess.execSync("git rev-parse --short HEAD")} 👉🏻 커밋 네임
  •  Author: 이현주(LeeHyunJu) 👉🏻 작성자

 

빌드 된 내용

 

2. DefinePlugin

어플리케이션은 개발환경과 운영환경으로 나눠서 운영됩니다. 환경에 따라 API 서버 주소가 다를 수 있어요. 같은 소스 코드를 두 환경에 배포하기 위해서 이런 환경 의존적인 정보를 소스가 아닌 곳에 관리하는 것이 좋습니다. 이러한 환경을 제공하기 위해 DefinePlugin를 제공합니다.

 new webpack.DefinePlugin({
      TWO: JSON.stringify("1+1"),
      "api.domain": JSON.stringify("http://dev.api.domain.com"),
    }),

 

api.domain을 문자열 넣고 싶을 때는 이렇게 출력합니다.

 

3. HtmlTemplatePlugin

html 파일을 후처리 하는데 사용합니다. 빌드 타임의 값을 넣거나 코드를 압축할 수 있습니다. 

npm install html-webpack-plugin
npm install html-webpack-plugin@4

이 플러그인은 웹팩의 기본 패키지가 아니라 따로 설치해 줘야합니다. 패키지 설치 후 버전이 안맞는다면 @4 이런식으로 버전을 맞춰 설치해주시면 됩니다. 얘를 사용하면 좀 더 유동적으로 html을 만들어 낼 수 있어요. 개발버전과 운영버전 두 가지 버전으로 관리가 가능하답니다.

    new HtmlWebpackPlugin({
      template: "./src/index.html",
      templateParameters: {
        env: process.env.NODE_ENV === "development" ? "(개발용)" : "",
      },
      //불필요한 용량들을 제거해주는거
      minify:
        process.env.NODE_ENV === "procution"
          ? {
              collapseWhitespace: true, //빈칸 제거
              removeComments: true, //주석 제거
            }
          : false,
    }),

 

html에는 title에 <title>Document <%=env %></title> 이렇게 ejs 문법을 사용하면 개발용인지 배포용인지 빌드를 통해 출력됩니다. 그리고  HtmlTemplatePlugin에는 minify 라는 속성도 제공해줘서 불필요한 용량들을 제거해 최소화 시켜줍니다. collapseWhitespace는 빈칸 제거를 의미하고 removeComments는 주석제거를 의미합니다.

 

4. CleanWebpackPlugin

빌드 결과물은 아웃풋 경로에 모이는데 과거 파일이 남아 있을 수 있습니다. 이전 빌드 내용이 덮어지면 상관 없지만 그렇지 않으면 아웃풋 폴더에 여전히 남아 있을 수 있습니다. 그래서 이 플러그인은 제거되고 사라진 과거 파일들을 빌드하면서 없애주는 역할을 합니다.

npm install html-webpack-plugin

 

이 플러그인은 다른 플러그인과 다르게 상단에 { } 중괄호를 넣어 가져와야 합니다.

const { CleanWebpackPlugin } = require("clean-webpack-plugin");

 

사용 법은 정말 간단해요 !

new CleanWebpackPlugin(),

이게 끝입니다 😄

 

4. MiniCssExtractPlugin

여러 CSS를 하나의 CSS로 만들어주는 플러그인 입니다. 그리고 이 플러그인은 다른 플러그인과 다르게 modules에서 loader도 설정해 주어야 합니다.

new MiniCssExtractPlugin({ filename: "[name].css" }),

플러그인 사용법

 

module: {
    rules: [
      {
        test: /\.css$/,
        👉🏻 use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      
 (...)

모듈에 플러그인 사용하기

 

 

그 외에도 

webpack.js.org/plugins/

 

Plugins | webpack

webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

webpack.js.org

웹팩 공식문서에 다양한 플러그인들이 제공되오니 사용하고 싶은 기능들을 잘 살펴보시고 사용하시길 바랍니다 ㅎㅎ

 

 

 

자주 사용하는 플러그인 종류에 대해서 마치겠습니다 ! 👻

 

+ Recent posts