일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- SAGA 패턴
- CSR
- 세션스토리지
- Apollo Client
- scrollTo 안됨
- nvm
- restore scroll position
- 환경 레코드
- Next.js
- Architecture
- 마이크로 프론트엔드
- Typescript
- 변수 섀도잉
- useRef
- 식별자 결정
- ESLint
- Spa
- Webpack
- SSR
- graphql
- 스코프체이닝
- Apollo Server
- 무한 스크롤
- redux saga
- 비동기 처리
- 실행 컨텍스트
- Babel
- 타입스크립트
- task-definition
- NextJS
- Today
- Total
minguri brain is busy
Apollo Server 4로 마이그레이션(sandbox 랜딩페이지 플러그인 설정, health check 적용) 본문
현재 프로젝트에 사용 중인 Apollo Server 3에서 4 버전으로 마이그레이션을 진행했다.
마이그레이션 진행 이유
Apollor Server2와 3 버전이 2023년 10월 22일 부로 deprecated 된다는 소식을 접했다. 하지만 마이그레이션을 결심한 결정적 이유는 그것이 아니었다. 언젠가부터 Apollo Server의 sandbox가 보이지 않았고 어느 날 업무가 좀 여유로워서 그 부분을 해결하고자 했다. 그렇게 찾다 보니 Apollo Server3이 deprecated 된다는 것을 알았고 마이그레이션을 진행하기로 했다.
적용방법
- 현재 apollo-server 패키지를 사용하고 있다면 startStandaloneServer를 함수를 사용해야한다.
- 현재 apollo-server-express 패키지를 사용하고 있다면 expressMiddleware 함수를 사용한다.
- ApolloServer 생성자 대신 컨텍스트 초기화 함수를 프레임워크의 통합함수(ex: startStandaloneServer 또는 expressMiddleware)에 직접 전달할 수 있다.
적용하기
// index.ts
const server = new ApolloServer({
schema,
context: async ({ req }: { req: IncomingMessage }) => {
...
},
});
server.listen({ port: 80 }).then(({ url }) => {
console.log(`🚀 API ready at ${url}`);
});
위의 코드를 @apollo/server패키지를 새로 추가해서 ^4.9.1 버전이 설치한 후 아래 코드로 수정했다.
...
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { ApolloServerPluginLandingPageProductionDefault, ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
dotenv.config();
const server = new ApolloServer({
schema,
plugins: [
process.env.NODE_ENV === 'production'
? ApolloServerPluginLandingPageProductionDefault({
graphRef: 'my-graph-id@my-graph-variant',
footer: false,
})
: ApolloServerPluginLandingPageLocalDefault({ footer: false }),
],
});
startStandaloneServer(server, {
context: async ({ req }: { req: IncomingMessage }) => {
...
},
listen: { port: 80 },
}).then(({ url }) => {
console.log(`🚀 API ready at ${url}`);
});
여전히 기본랜딩페이지에서 sandox가 보이지 않아!
처음엔 plugin설정을 하지 않았었는데, 여전히 sandbox가 랜딩 되지 않았다. sandbox가 안 나오는 게 버전 문제가 아닌 것임을 알게 되었고 도큐먼트를 보던 중에 랜딩 페이지 설정을 하려면 ApolloServerPluginLandingPageLocalDefault, ApolloServerPluginLandingPageProductionDefault와 같은 인자를 지원하는 것을 알았다.
따로 분기하지 않고 ApolloServerPluginLandingPageLocalDefault로 설정해 봤을 때에도 해결되지 않아 로컬과 운영을 분리했더니 드디어 보였다! 그래서 기존버전에서도 랜딩페이지 운영환경분리를 하지 않아서 안나왔었던 걸까 하는 생각이 들었고 Apollo Server 3 버전으로 되돌려 랜딩페이지를 설정해서 테스트해 봤더니 잘나왔다.🤪
그렇다면, sandbox가 갑자기 나오지 않는다고 느꼈던 이유?
예전 작업했던 내용 중에 디버그 콘솔을 운영에서는 안 찍히게 하기 위해 빌드 스크립트에 NODE_ENV production과 development를 분리한 적이 있었다. production으로 서버가 뜰 경우 Apollo Server는 보안상 이유로 sandbox가 제공하지 않는다. 분리작업을 의식하지 않고 production으로 띄워서 확인해서 sandbox가 나오지 않았고 dev로 띄울 경우 잘 보였었던 사실;
이왕 이렇게 된 거,
어쨌든 버전 3은 deprecated 된다고 하니 Apollo Server 4로 마이그레이한 작업을 배포를 완료한 상태이다. 작업 시 주의할 점은 엔드포인트의 기본 url에 뒤에 붙던 /graphql이 없어졌다고 하니 Apollo Client에서 바라보는 엔드포인트가 수정되어야 된다는 점이다.
+ 배포 시 마주한 문제
배포 중 ECS의 task definition 부분에서 에러가 났다. 이유를 살펴보니 health-check가 되지 않고 있었다. 도큐먼트를 찾아보니 Apollo Server 4에서는 built-in health-check를 더 이상 지원하지 않는다고 했다. 그래서 health check 하는 방법으로 express app을 사용해서 우회적용을 진행했다. 그러기 위해서는 먼저 현재 startStandaloneServer로 실행되는 방식을 expressMiddleware 방식으로 swap 해야 했다.
body-parser, cors, express, @types/cors 패키지를 추가하고 아래 코드로 수정했다.
...
import express from 'express';
import http from 'http';
import { expressMiddleware } from '@apollo/server/express4';
import bodyParser from 'body-parser';
import cors from 'cors';
const app = express();
const httpServer = http.createServer(app);
const server = new ApolloServer({
schema,
plugins: [
process.env.NODE_ENV === 'production'
? ApolloServerPluginLandingPageProductionDefault({
graphRef: 'my-graph-id@my-graph-variant',
footer: false,
})
: ApolloServerPluginLandingPageLocalDefault({ footer: false }),
ApolloServerPluginDrainHttpServer({ httpServer }),
],
});
server.start().then(() => {
app.use(
'/',
cors<cors.CorsRequest>(),
bodyParser.json(),
expressMiddleware(server, {
context: async ({ req }: { req: IncomingMessage }) => {
...
},
})
);
});
new Promise<void>((resolve) => httpServer.listen({ port: 80 }, resolve)).then(() => {
console.log(`🚀 API ready`);
});
app.get('/.well-known/apollo/server-health', (_req, res) => {
res.status(200).send({ status: 'pass' });
});
기존의 health check url인 '/. well-known/apollo/server-health'을 맞춰서 설정해서 200 코드일 경우 pass json응답을 보여주는 페이지를 설정했고, health check가 정상 통과됐다.
'FE > 개발' 카테고리의 다른 글
웹페이지에 구조화된 데이터(JSON-LD) 추가하기 (0) | 2023.05.04 |
---|---|
TypeScript 5.1 베타 발표 살펴보기 (0) | 2023.04.19 |
무한스크롤 페이지에서 스크롤 위치 복원 (0) | 2022.12.23 |
Next.js의 SSR, CSR 기본개념알아보기 (0) | 2022.08.04 |
Saga패턴 vs Redux-Saga / 간단한 예제로 살펴보기 (0) | 2022.07.22 |