원래 회사에서 REST API
를 통해서 클라이언트와 API 통신을 하고 있었는데 불필요한 join
문과 수시로 바뀌는 기획에 대응을 하기 위해서 클라이언트 입맛에 맞게 데이터를 조회할 수 있도록 GraphQL을
도입하기로 했다.
사용을 하면서 GraphQL로 file을 upload 하는 API를 개발할 때 2022년도에 구현을 하지 못해서 file
upload는 REST API
를 사용했던 경험이 있다.
하지만 이번에는 온전히 GraphQL
을 사용하면서 file upload 기능을 구현하고 싶어서 글을 정리하게 됐다.
먼저 GraphQL
에서 Mutation
을 이용하여 file upload를 구현 할 것이다. file을 upload를 하기 위해서 graphql-upload
라이브러리를 사용할 것이다.
> npm i graphql-upload
> npm i -D @types/graphql-upload
위 명령어를 통해서 graphql-upload
라이브러리를 설치해준다. (yarn
으로 설치해도 됨)
이때, nestjs src/main.ts
에서 graphql upload express를 활성화해줘야 한다.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(graphqlUploadExpress());
await app.listen(3000);
}
bootstrap();
이때, 주의사항은 import graphqluploadExpress from 'graphql-upload'
혹은
import { graphqlUploadExpress } from 'graphql-upload'
이렇게 import를 하게 되면 해당 모듈을 찾지 못하는 에러가 발생한다.
무조건 graphql-upload/graphqlUploadExpress.mjs
에서 import를 해야한다!
다음 단계는 이제 file을 upload 할 resolver
에서 파라미터 처리를 해줘야 하는데 기존제 REST API를 사용할 때 처럼 file과 관련된 데코레이터를 붙여줘야 한다.
import { Args, Mutation, Resolver } from '@nestjs/graphql'
import GraphqlUpload, { FileUpload } from 'graphql-upload/GraphQLUpload.mjs'
@Resolver()
export class UploadResolver {
constructor() {}
@Mutation(() => String)
async uploadFile(@Args('file', { type: () => GraphqlUpload }) file: FileUpload) {
console.log(file);
}
}
이렇게 앞서 src/main.ts
에서 import 한 거 처럼 특정 경로에서 import를 해준다.
위 예제 코드를 작성하고 playground
혹은 graphiql
이 곳에서 테스트를 할 수 없다.
왜냐하면 이 두 곳은 file upload를 지원하지 않는다.
그래서 찾은게 Altair
다. UI/UX가 훌륭하다. Altair
를 사용해서 file을 upload 하고,
schema를 작성해준다.
위에 이미지처럼 변수를 만들어서 사용해도 좋고 편한 방법이 있다면 편한 방법으로 하면된다.
이렇게 설정을 했으면 이제 server로 request를 해주면 console.log(file)
을 통해 터미널을 확인해보면
{
filename: string;
mimetype: string;
encoding: string;
}
이런식으로 file 정보를 얻을 수 있다. 이 값을 통해서 AWS S3 Bucket에 upload를 할 수 있다.
이처럼 GraphQL을 이용해서 file upload를 하는 방법에 대해서 알아봤다. 별거 아니지만 과거에 완료하지 못한 기능을 구현하게 돼서 REST API에 의존하지 않을 수 있었다.
과거에 구현하지 못한 GraphQL file upload를 구현해서 뿌듯함,,