backend 기본 셋업 (3)
🍔 핵심 내용
🥑 아키텍처의 의미 (divide and Conquer)
쉽게 설명 하면, 같은 의미있는 것들끼리 묶어 두는 행위라고 보면 된다. ex) 비슷한 유형의 어플들끼리 같은 폴더로 묶어 관리하게 되면 나중에 재사용시, 혹은 변경 시 쉽게 접근 및 수정이 가능하다.
현재 server.js에는 typesDefs들과 resolvers(query, mutation), server실행 하는 로직 등이 짬뽕 되어 있다. 이를 분리해주자.
🥑 npm i graphql-tools 설치
graphql 필수 요소인, typesDefs와 resolvers들을 분리해놓게 되면 이를 다시 한 곳에 불러와야 하는데, 이 때 사용 될 도구 이다. 자세한 내용은 아래 코드 리뷰에서...!
🍔 코드 리뷰
🥑 client.js
import { PrismaClient } from "@prisma/client";
const client = new PrismaClient() // client 객체 생성
export default client;
cleint 파일 별도 분리
🥑 movies/movies.typeDefs.js
import { gql } from "apollo-server";
export default gql`
type Movie {
id: Int!
title: String!
year: Int!
genre: String
createdAt: String!
updatedAt: String!
}
type Query {
movies: [Movie]
movie(id:Int!): Movie
}
type Mutation {
createMovie(title: String!, year: Int!, genre: String): Movie
deleteMovie(id:Int!): Movie
updateMovie(id: Int!, year: Int!): Movie
}
`;
movies 폴더 생성 후, typeDefs파일 별도 생성. 추 후, User폴더, like 폴더 추가와 같이 divide and Conquer 해야 한다.
(export default를 해야 함)
🥑 movies/movies.queries.js
import client from "../client"
export default {
Query: {
movies: () => client.movie.findMany(), //여기서 movie는 prisma에서 정의한 schema (model) 테이블 값이다.
movie: (_, {id}) => client.movie.findUnique({where:{id}})
}
}
🥑 movies/movies.mutatios.js
import client from "../client"
export default {
Mutation: { //movie 테이블 값에 데이터를 추가해보자
createMovie: (_, { title, year, genre }) => client.movie.create({
data: {
title,
year,
genre,
}}),
deleteMovie: (_, { id }) => client.movie.delete({where: { id }}),
updateMovie: (_, { id, year }) => client.movie.update({where: { id }, data: { year }}),
}
};
🥑 schema.js
import { loadFilesSync, makeExecutableSchema, mergeResolvers, mergeTypeDefs } from "graphql-tools";
const loadedTypes = loadFilesSync(`${__dirname}/**/*.typeDefs.js`);
const loadedResolvers = loadFilesSync(`${__dirname}/**/*.{queries,mutations}.js`);
const typeDefs = mergeTypeDefs(loadedTypes);
const resolvers = mergeResolvers(loadedResolvers);
const schema = makeExecutableSchema({ typeDefs, resolvers });
export default schema;
위에, typeDefs와 resolvers 파일을 별도 생성 해 주었다. 이를 schema 파일안에 한번에 merge 해주기 위해서는, 앞서 말한 graphql-tools의 도움을 받으면 쉽게 진행 될 수 있다.
여기서, ${__dirname}/**/*.typeDefs.js 는 ${__dirname}/어느 폴더에서든/어느 파일명에서든.typeDefs.js로 끝나는 모든 걸 다 load 해온다. 라는 뜻이고, ${__dirname}/**/*.{queries,mutations}.js 는 ${__dirname}/어느 폴더에서든/어느 파일명에서든.{queries 혹은 mutations파일명이 들어간 }.js의 모든 파일을 load해온다라는 뜻으로 이해하면 된다.
그래서 movies.queires.js / movies.mutations.js로 파일명을 지은 것이다.
이렇게 schema라는 변수 명으로 typeDefs와 resolvers가 담겼고, 이를 server.js로 보내주기만 하면 된다.
🥑 server.js
import { ApolloServer } from "apollo-server";
import schema from "./schema"
const server = new ApolloServer({
schema,
});
server
.listen()
.then(() => console.log("Server is running http://localhost:4000/"));
불러 왔다. 이렇게 함으로써, server.js에 있던 모든 내용들이 총 5개로 각 성격별로 찢어 지게 되었다. 분리해서 정복하자!
🍔 핵심 내용
🥑 npm i dotenv 설치
.env 파일의 데이터를 가져 올 수 있는 모듈을 설치하자. .env에는 다른사람에게 노출되지 않을 정보들이 들어가 있어야 한다
🥑 기본 백엔드 셋팅 완료
이제 뼈대까지는 완성이다. 이제 prisma 폴더를 삭제해주고(movies로 만든거는 test용), movies 폴더도 삭제해주자. 그리고 db도 삭제 및 재생성해서 뼈대만 있는 상태에서 진행해보자.
🍔 코드 리뷰
🥑 server.js
require("dotenv").config(); // <-- 추가
import { ApolloServer } from "apollo-server";
import schema from "./schema"
const server = new ApolloServer({
schema,
});
const PORT = process.env.PORT;
server
.listen()
.then(() => console.log(`🚀 Server is running http://localhost:${PORT} ✅`));
dotenv 부분을 추가 해주었다. 이 부분을 추가함으로써, process.env.변수명을 가져다 쓸 수 있게 되었다.
🥑 .env (비공개)
PORT=4000
이렇게 함으로써, .env에 있는 데이터를 끌어다 쓸 수 있다.