[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 Pre02

2023. 1. 2. 00:35WEB Dev/StudyNote

728x90


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

 

2023-01-01 21:00 2일차 대비


프로젝트 준비 과정

 

3장 프로젝트 준비

 

3.1 프로젝트 소개

 

무료로 배포된 지브리의 명장면 사진, 포스터를 감상하고

장면에 대한 "좋아요" 및 감상평을 남길 수 있는 간단한 서비스 제작

 

 

기능 요구사항

 

- 회원가입과 로그인이 가능해야 합니다.

- 유저는 영화 목록을 확인할 수 있어야 합니다.

- 유저는 특정 영화의 명장면 목록을 확인할 수 있어야 합니다.

- 유저는 명장면에 "좋아요"를 누를 수 있고, 감상평을 남길 수 있어야 합니다. "좋아요" 누르기와 감상평 남기기는 로그인 상태에서만 가능해야 합니다.

- 유저는 프로필 사진을 업로드할 수 있어야 합니다.

- 알림 기능으로 특정 유저에게 알림을 실시간으로 보낼 수 있어야 합니다.

 

3.2 프로젝트 아키텍처

 

 

- 데이터베이스

(Node.js, MySQL, TypeORM, Redis, ioredis, Yarn)

프로젝트에서는 Nodejs 런타임에서 MySQL 데이터베이스에 연결하기 위해 TypeORM이라는 ORM 라이브러리를 사용

(TypeORM은 타입스크립트 클래스를 기반으로 테이블 및 컬럼을 생성하고, 데이터베이스 엔티티에 접근할 수 있는 방식을 제공)

 

로그인 기능과 관련된 토큰값을 저장하는 용도로 Redis를 사용

(Redis는 인-메모리 데이터베이스로, 디스크 상에 데이터가 저장되는 타 DB와는 다르게 매우 빠른 속도로 데이터를 열람하고 저장)

 

 

 

- GraphQL 서버

(Apollo, TypeGraphQL, Express, DataLoader)

Apollo 서버를 사용

Apollo 서버는 코드 주도 방식과 스키마 주도 방식에 대한 문법과 기능을 모두 제공하고 있으나 코드 주도 접근 방식으로 예제를 구성할 예정으로 TypeGraphQL을 통해 매우 타입스크립트적인 방식으로 작업

 

Apollo는 GraphQL과 관련된 큰 커뮤니티이며 Apollo 서버, Apollo 클라이언트, Apollo Federation 등 GraphQL을 쉽게 활용할 수 있도록 하는 오픈소스 라이브러리를 제공

TypeGraphQL은 TypeORM과 문법적으로 동일하여 코드 관리 지점을 줄여줌

 

Apollo 서버는 Express, Koa, Hapi 등의 HTTP 웹 서버와 함께 사용할 수 있기 때문에 Express를 HTTP 서버로 사용

 

Apollo 서버와 GraphQL을 함께 사용하면서 쉽게 발생할 수 있는 문제인 N+1 문제를 해결하기 위해 DataLoader를 사용

 

 

 

- 프런트엔드

(React, Typescript, Chakra-ui, Apollo Client, GraphQL Code Generator, React-hook-form)

 

React를 사용

Chakra-ui를 사용해 화면 UI를 구성

 

GraphQL 클라이언트로 Apollo 클라이언트를 사용

Apollo 클라이언트는 GraphQL을 통해 서버와 통신하는 프런트엔드 앱을 구성하기 위해 필요한 대부분의 기능을 제공

GraphQL Code Generator로 Apollo-style의 React 훅과 타입 정의 및 관련 변수를 자동으로 생성

 

React-hook-form 라이브러리를 사용하여 form 관련 로직과 렌더링을 최소한으로 줄여 최적화

 

 

 

 

3.3 개발 환경 구성

 

- Nodejs 환경 구성

운영체제에 따른 환경 구성

 

▫️ Windows

 

1. Nodejs LTS 14.17.3 설치 권장

2. 터미널(or PowerShell or 명령프롬프트)에 npm -v과 node -v 입력하고 버전이 정상적으로 표시되는지 확인

3. npm 글로벌 설치를 통해 패키지 매니저로 Yarn을 설치한다. (터미널에 npm install -g yarn)

 

🔊 내 경우엔 이미 Node와 yarn이 깔려 있는 상태여서 별도로 설치 진행하지는 않음

 

 

 

 

▫️ Mac

 

1. Homebrew 패키지 매니저를 설치한다. (터미널에 아래 코드 입력)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

2. 터미널에 brew install node@14 를 입력하고 설치를 진행한다.

3. 환경변수 설정 오류로 버전 확인이 안되는 경우 brew link node@14 를 터미널에서 실행해준다.

4. brew install yarn 을 실행하여 yarn 패키지 매니저를 설치한다.

 

 

- Docker 설치

 

Docker는 소프트웨어를 빌드하고 배포하거나 개발 환경을 구성하는 플랫폼으로 "컨테이너"라는 단위의 시스템 환경을 구성하거나 공유할 수 있다. 컨테이너는 이미지로 캡처될 수 있고, 이미지는 배포가 가능하여 공유하거나 원격 저장소에 저장할 수 있다.

 

Docker의 기본 개념

 

- 컨테이너Container

서버 환경에서 애플리케이션 로직과 OS, 시스템 도구 등을 하나로 묶어놓은 격리된 환경을 의미

Docker의 기본적인 단위로 애플리케이션과 구동 환경에 대한 정보까지 모두 포함되어 있어 매우 독립적이며 특정 OS에 종속되지 않아 구동 조건만 갖춰지면 언제나 동일하게 애플리케이션을 실행할 수 있다.

 

- 컨테이너 이미지Container Image

컨테이너의 특정 시점을 캡쳐한 정보로 컨테이너를 실행할 수 있는 환경 설정 및 실행 파일 등에 대한 정보를 가지고 있다.

Docker 서비스 또는 타사(ex AWS ECR, Azure Container Registry 등) 서비스를 통해 배포가 가능하다

 

- 컨테이너 특징

  1) 높은 이식성과 독립성

  하나의 이미지를 가지고 동일한 컨테이너를 여러개 실행할 수 있다.

  그러나 컨테이너는 독립적이기 때문에 예를 들어 MySQL 데이터베이스가 컨테이너에 있고 이 컨테이너를 5개 다운 받아 각각 실행한다면 5개의 MySQL 데이터베이스가 설치된다.

  쿠버네티스Kubernetes 같은 기술은 Docker 컨테이너를 통합적으로 관리하고 클러스터 단위로 묶어 활용할 수 있도록 해 규모 있는 서비스 운영을 돕는다.

 

  2) 영속성persistence 없음

  컨테이너 하나를 제거하면 해당 컨테이너 안에 있던 로그, 데이터등은 모두 없어진다.

  따라서 데이터베이스와 같이 영속성이 중요한 요소는 별도의 데이터 볼륨을 두어 유지하는 것이 바람직하다.  

 

 

Docker Desktop을 이용하여 Docker를 쉽게 설치하고 GUI로 환경을 관리할 수 있다.

 

 

▫️ Windows

1. WSL2 를 설치한다. 

2. Docker Desktop for Windows 설치한다.

 

🔊 

 

1-1) Windows PowerShell 창을 관리자로 실행한다.

 

 

우측의 '관리자로 실행' 또는 아이콘에서 우클릭하여 관리자로 실행한다.

 

 

 

1-2) wsl --install 명령어를 입력한다.

      기존 버전을 삭제하려면  WSL의 레거시 버전 제거 또는 Linux 배포판 등록 취소 또는 제거를 참조

 

 

 

WSL를 실행하고 Linux의 Ubuntu 배포를 설치하는데 필요한 기능을 사용하도록 설정

 

 

1-3) wsl -l -v 를 입력해 설치된 Linux 배포판 확인

       만약 우측 VERSION이 2가 아니고 1이라면 wsl --set-default-version 2 를 실행

 

 

 

 

 

2-1) Docker Desktop for Windows 버튼을 클릭하여 패키지 파일을 다운받아 실행

 

Windows용 Docker 데스크톱 다운로드

 

 

 

2-2) 설치 진행

 

 

Windows용 Docker 데스크톱 설치

 

 

 

2-3) 설치 완료 Close and log out 클릭하여 설치 종료 (!!Close and logout 클릭하면 윈도우가 로그아웃 되기 때문에 미리 저장할 것들을 저장하도록 합시다)

 

 

설치 완료

 

 

 

 

2-4) 로그아웃 후 재로그인 하면 이런 약관 동의 창이 나오고 Accept를 눌러준다.

 

 

Agreement 창

 

 

 

2-5) 터미널에서 docker -v를 치고 설치 버전을 확인한다.

 

 

 

 

 

▫️ MacOS

1. Docker Desktop for mac을 설치한다. 

2. 터미널에서 docker -v로 버전을 확인한다.

 

 

 

+) Docker 기본 명령어

 

docker pull

컨테이너 이미지를 로컬 컴퓨터로 다운로드 하는 명령어

 

docker images

로컬 컴퓨터에 다운로드된 이미지의 목록을 보여주는 명령어

 

docker ps

현재 실행되고 있는 컨테이너 목록을 보여주는 명령어 

 

docker run

특정 이미지로부터 컨테이너를 실행하는 명령어

 

docker stop

실행 중인 하나 이상의 컨테이너를 종료하는 명령어

 

docker start

종료되었던 컨테이너를 다시 실행하는 명령어

 

docker rm

하나 이상의 컨테이너를 제거하는 명령어

 

docker rmi

하나 이상의 이미지를 제거하는 명령어

 

 

 

- MySQL과 Redis 설치

 

▫️ MySQL 설치

 

1. 터미널에 docker pull ubuntu 을 입력

    이 명령어를 치고 error during connect: In the default daemon... 에러가 나왔다면 Docker Desktop이 실행되지 않고 있는 상태이니 시작 버튼을 누르고 Docker Desktop을 찾아서 관리자 권한으로 실행시켜주면 된다. 아래는 에러 전문

error during connect: In the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect.: Post "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/images/create?fromImage=ubuntu&tag=latest": open //./pipe/docker_engine: The system cannot find the file specified.

 

 

 

Docker Desktop 관리자로 실행

 

 

docker pull ubuntu

 

 

 

 

2. docker pull mysql:8 실행 

 

 

docker pull mysql:8

 

 

 

3. docker run --name mysql-container -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=qwer1234 mysql:8 입력

    이때 PASSWORD는 자신이 사용할 비밀번호로 변경해도 된다.

    방화벽 차단 허용이 뜨면 허용해준다.

    완료되면 docker ps를 이용해서 실행되고 있는지 확인한다.

 

 

 

docker run 및 docker ps 실행

 

 

 

4. 실행된 MySQL에 접근하기 위해 workbench등을 사용할 수 있고 CLI로 접속해볼 수 있다.

    docker exec -it mysql-container /bin/bash를 입력한다.

    

 

    bash에서 mysql -u root -p를 입력해서 Enter Password가 나오면 아까 PASSWORD로 입력한 비밀번호를 입력한다.

   

 

MySQL 접속

 

 

    mysql> 상태에서 SHOW DATABASES; 를 입력해 데이터베이스 목록을 불러올 수 있다.

 

 

SHOW DATABASES;

 

 

 

5. 사용할 데이터베이스를 생성하기 위해 CREATE DATABASE ghibli_graphql; 를 입력한다.

    이후에는 TypeORM으로 데이터베이스에 연결하기 때문에 직접 접속할 일은 크게 없다.

    ghibli_graphql 데이터베이스는 mysql-container 컨테이너 안의 ghibli_graphql 데이터베이스가 된다.

 

 

CREATE DATABASE ghibli_graphql;

 

 

SHOW DATABASES;

 

 

 

6. 종료를 위해 exit를 입력하고 bash에서 나오기 위해 exit를 한 번 더 입력한다. 

 

 

exit

 

 

 

 

▫️ Redis 설치

 

 

1. docker pull redis:6.2 명령어로 Redis를 설치한다. (bash까지 빠져나왔는지 확인)

 

 

docker pull redis:6.

 

 

2. docker run -d --name redis-container -p 6379:6379 redis:6.2 명령어를 통해 컨테이너로 실행하고 docker ps를 이용해 실행 여부 확인

 

 

docker run -d --name redis-container -p 6379:6379 redis:6.2

 

 

 

 

3. docker logs redis-container로 커넥션을 받아들일 준비가 되어 있음을 확인할 수 있다.

 

 

docker logs redis-container

 

 

4. redis-cli에 접속하기 위해 docker network를 생성해준다. docker network create redis-network 를 입력한다. 

 

 

docker network create redis-network

 

 

5. 네트워크를 생성하고 redis-container를 네트워크에 연결해주는 아래 명령어를 실행한다.

    docker network connect redis-network redis-container

 

 

docker network connect redis-network redis-container

 

 

 

6. redis cli를 실행하기 위해 임시 컨테이너를 생성하여 redis-container 내 구동 중인 redis에 접속할 수 있다.

    docker run -it --network redis-network --rm redis redis-cli -h redis-container

    위 명령어를 실행한다. --rm 옵션으로 컨테이너가 작업 종료되면 삭제되도록 한다.

    MySQL과 같이 개발 중 Redis에 직접 접속할 일은 없다. Node 기반 Redis 클라이언트인 ioredis 패키지를 이용해 접속하고 데이터를 관리한다.

 

 

docker run -it --network redis-network --rm redis redis-cli -h redis-container

 

 

 

7. 동작 여부를 확인하기 위해 데이터를 삽입하고 조회해 볼 수 있다. 

    set testkey testvalue  를 입력해 redis에 데이터를 생성할 수 있다. 

 

 

set testkey testvalue

 

 

 

8. testkey의 값을 받아오고 *로 모든 key를 조회할 수 있다. 

    get testkey 또는 keys * 를 입력한다.

 

 

get testkey 또는 keys *

 

 

9. exit로 종료한다. 

 

 

 

 

 

 

▫️ VSCode 설치 및 세팅

 

1. VSCode를 설치한다. 

2. 확장 플러그인들을 설치해준다.

 

    - GraphQL

 

 

 

    - Material Icon Theme

    - Dotenv

 

   

 

    - Auto Rename Tag

    - Color Highlight

    - Docker

 

 

 

 

     - ESLint

 

 

 

     - indent-rainbow

 

 

 

 


3.4 프로젝트 구성

 

미리 구성된 프로젝트를 클론하기  -> 링크

 

직접 구성하기

 

1. 프로젝트를 진행할 폴더를 생성하고 폴더로 이동하기 위해 적절한 곳에서 폴더를 만든다.

 

mkdir graphql-book-fullstack-project

cd graphql-book-fullstack-project

 

 

 

2. github에 레포지토리를 만들고

 

git init

git remote add origin 저장소 url 

 

을 입력한다.

 

 

3. https://www.toptal.com/developers/gitignore 에서 gitignore 파일을 만든다.

     입력 창에 react, node를 입력한다.

 

 

https://www.toptal.com/developers/gitignore

 

 

4. 터미널에서 touch .gitignore 을 입력해 .gitignore 파일을 만든 후 gitignore.io에서 생성한 파일을 붙여넣기 한다.

 

 

 

 

 

5. yarn을 이용해 워크스페이스를 구성한다.

    yarn init -y -p 명령어를 통해 package.json을 구성한다.

    -y는 모든 설정에 대한 값을 y로 처리하는 옵션이고 -p는 package.json에 자동으로 private: true를 추가한다. private 설정은 작업 프로젝트를 npm에 배포하지 않음을 나타내는 옵션이다.

 

 

yarn init -y -p

 

 

 

6. graphql-book-fullstack-project 폴더 안에 project라는 폴더를 만든다.

 

 

 

 

 

7.  project 폴더 안으로 들어와서 web이라는 폴더 안에 create-react-app으로 리액트 프로젝트를 생성하고 chakra-ui 라이브러리 템플릿을 구성해준다. 

 

 

cd project

yarn create react-app --template @chakra-ui/typescript web

 

happy hacking!이 뜨면 완료다.

 

 

yarn create react-app --template @chakra-ui/typescript web

 

 

8. web 폴더 안에서 react 앱을 실행시켜 볼 수 있다.

 

cd web

yarn start

 

yarn start

 

localhost:3000 에서 chakra-ui로 생성된 create-react-app 을 열 수 있다.

 

 

9. 서버 구성은 스타터패키지 없이 구성한다.

    project 폴더로 다시 나와서 server 폴더를 만들어주고 server 폴더로 들어가서 yarn init 을 이용해 package.json을 생성한다.

 

cd ..

mkdir server

cd server

yarn init -y -p

 

 

yarn init -y- p

 

 

 

10. apollo-server-express와 express, graphql, typescript 등의 의존 모듈을 설치한다.

 

yarn add express apollo-server-express graphql reflect-metadata typescript apollo-server-core

 

 

yarn add express apollo-server-express graphql reflect-metadata typescript apollo-server-core

 

 

 

11. server 폴더로 내에 src 폴더를 생성한 후 src 폴더 안에 index.ts 파일을 생성한다. index.ts에는 express와 apollo-server-express를 이용한 서버 엔트리 파일을 구성한다.

 

mkdir src

cd src

touch index.ts

 

 

 

 

12. 타입스크립트 코드로 작성된 파일을 실행하기 위해 ts-node 를 설치한다. ts-node는 기존 자바스크립트 파일을 노드로 실행하는 것과 동일하게 ts-node index.ts와 같이 타입스크립트 파일을 실행시켜준다.

 

server 폴더 내로 이동하기 위해 cd .. 해주고

 

yarn add ts-node

 

 

 

yarn add ts-node

 

 

13. 그리고 server 폴더 안의 package.json에 ts-node 이용 시작 스크립트를 추가한다.

 

  "scripts": {
    "start": "ts-node src/index.ts"
  },

 

 

 

 

 

14. 서버를 시작하기 위해서 server 폴더 안에서 yarn start를 실행한다.

 

 

 

 

15. graphql 로 끝나는 url 로 이동하면 Apollo Studio 안내 화면이 나오고 hello 쿼리를 실행해 볼 수 있다.

 

 

http://localhost:4000/graphql

 

 

http://localhost:4000/graphql

 

 

 

16. 터미널에서 curl 요청을 보낼 수도 있다.

 

curl --request POST

--header 'content-type: applicaion/json'

--url http://localhost:4000/graphql

--data '{"query":"query { hello }"}'

 

 

17. 코드에 변경 사항을 반영하기 위해 서버를 껐다 켜야 하는 번거로움을 줄이기 위해 server 폴더에 nodemon을 설치한다.  

 

yarn add --dev nodemon

 

yarn add --dev nodemon

 

 

 

18. server 폴더 내의 package.json 파일에서 아까 작성한 시작 스크립트에 dev를 추가해준다. 

 

 

"dev": "nodemon --watch *.ts --exec ts-node src/index.ts"

 

 

"dev": "nodemon --watch *.ts --exec ts-node src/index.ts"

 

 

19. yarn dev 명령어를 통해 코드가 변경되면 자동으로 재시작되는 개발용 서버를 시작할 수 있다.

 

 

yarn dev

 

코딩 스타일 및 규칙 적용

 

코드 스타일을 인관되게 유지하여 에러 및 버그를 예방하거나 이해를 도울 수 있다.

ESLint로 코딩 규칙을 정의하고 에러를 찾아낼 수 있는데 이런 작업을 Linting이라고 한다.

 

ESLint는 코딩 규칙을 정의하고, 정의된 규칙에 따라 코드를 정적으로 분석하여 문제를 찾아내거나 에러로 표시해준다. 

Prettier는 코드 포맷터로, 코드 스타일에 대한 몇 가지 규칙을 정한 뒤 코드를 자동으로 포맷팅해주는 플러그인이다. 

 

yarn 을 이용해서 eslint와 prettier를 설치할 수 있다.

 

graphql-book-fullstack-project로 올라가서 

yarn add eslint prettier 를 입력한다. 

 

 

 

yarn add eslint prettier

 

 

코딩 룰은 Airbnb의 자바스크립트 스타일 가이드 문서를 이용하거나 yarn 을 통해 의존 모듈로 받아 올 수 있다.

 

yarn add eslint-config-airbnb

 

또한 타입스크립트 파서Parser를 이용해 ESLint가 타입스크립트를 해석할 수 있도록 해준다.

 

yarn add @typescript-eslint/eslint-plugin @typescript-eslint/parser typescript

 

 

prettier의 코드 포매팅 기능을 위한 의존 모듈도 설치한다.

eslint-config-prettier은 Prettier에서 관리하는 스타일에 관한 ESLint 규칙을 비활성화 하고, eslint-plugin-prettier는 Prettier에서 인식하는 스타일 오류를 ESLint 오류로 출력해주는 플러그인이다.

 

yarn add eslint-config-prettier eslint-plugin-prettier

 

또한 import/export에서 생기는 이슈를 확인하기 위해 eslint-plugin-import 의존 모듈도 설치한다.

 

yarn add eslint-plugin-import

 

 

React와 관련된 플러그인을 설치해준다. eslint-plugin-react는 React와 관련된 기본적인 규칙을 검토하고, eslint-plugin-react-hooks React의 hook과 관련된 규칙을, eslint-plugin-jsx-a11y는 React의 접근성 관련 규칙을 검토하는 플러그인이다. 

 

yarn add eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y

 

 

 

 

플러그인을 설치한 후 .prettierrc과 .eslintrc.js 파일을 graphql-book-fullstack-project 폴더에 생성하고 설정해준다.

 

 

.eslintrc.js 파일 내의 rules 에서 특정 규칙을 끄거나 켤 수 있다. 

 

그리고 VSCode에서 코드 저장 시 자동으로 ESLint 룰에 따라 코드 변경을 적용하는 설정을 한다. 

VSCode 내에서 컨트롤 과 , 쉼표를 함께 눌러 설정을 열 수 있다.

 

 

상단의 문서 표시(Open Settings(JSON))을 눌러 settings.json 파일을 열어준다.

 

 

 

내부에 아래 코드를 추가해준다.

 

"editor.formatOnSave": true,
    // JS파일과 JSX파일의 에디터 기본 설정을 off 합니다.
    // 우리는 이 기능을 eslint를 통해 사용합니다.
    "[javascript]": {
        "editor.formatOnSave": false,
        "editor.defaultFormatter": "vscode.typescript-language-features",
        "editor.tabSize": 2
    },
    "[javascriptreact]": {
        "editor.formatOnSave": false,
        "editor.tabSize": 2
    },
    "[typescript]": {
        "editor.formatOnSave": false,
        "editor.tabSize": 2
    },
    "[typescriptreact]": {
        "editor.formatOnSave": false,
        "editor.tabSize": 2
    },
    "eslint.alwaysShowStatus": true,
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },

 

프로젝트 데이터 다운로드

프로젝트 시작 전 Ghibli Studio의 영화와 명장면 데이터를 다운로드 받는다.

파일은 자바스크립트 오브젝트로 .ts 파일이다. 다운로드 링크

 

graphql-book-fullstack-project 폴더 내 project/server/src 폴더에 data 폴더를 새로 생성하고 ghibli.ts 파일을 생성한 뒤 깃헙 내 파일 내용을 복사해 붙여넣는다. 아직 import 할 파일이 없어서 오류가 난다.

 

graphql-book-fullstack-project/project/server/src/data/ghibli.ts

 

728x90