[GraphQL][Express] CORS 설정하기 - apollo-server-express

koline·2023년 11월 17일
0

GraphQL

목록 보기
6/8

CORS


apollo-client를 세팅한 후 apollo-server로 요청을 보내보면 아마 CORS에 의해 막힐 것이다.

CORS란 브라우저가 보안적인 이유로 cross-origin HTTP 요청들을 제한하는 것이다. cross-origin 요청을 하려면 서버의 동의가 필요한데, 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 기본적으로는 브라우저에서 거절한다.

HTTP-header를 이용해서 이러한 허락을 구하고 거절하는 메커니즘을 실행하는데, 이를 CORS(Cross-Origin Resource Sharing)라고 부른다.

이게 브라우저별 cors 정책을 정확하게 모르겠는데 같은 cross-origin 요청도 어쩔 땐 될 때가 있고 그러다가 갑자기 안되기도 한다. 근데 특정 브라우저에서는 되는데 어떤 브라우저에서는 안되는 것 같지는 않은 걸로 봐서 공통된 CORS 조건 같은게 있는 듯하다. 하지만 API - client 구조로 나눠서 개발을 한다면 언젠가 CORS가 터지게 된다.




해결법


사실 해결법은 매우 간단하다. Server 측에서 허가를 해주면 되는데 우선 cors dependency를 추가해준다.

# npm 쓸 경우
npm i cors

# yarn 쓸 경우
yarn add cors

그리고 작성했던 server.tsexpress 서버에 적용해주면된다.

const app = express();
app.use(cors());

만약 특정 url에서만 cors요청을 허가하고 싶으면 option을 줄 수 있다.

const app = express();
app.use(cors({
  origin: ["http://localhost:5173"],
  credentials: true,
}))

option으로 credentials도 설정할 수 있는데, 일종의 인증서같은 개념으로, true로 설정하면 client-side 에서도 header와 http설정이 추가로 필요하다. 주로 인증이나 cookie 등 보안적으로 민감한 문제가 있을 때는 써주는게 좋다.

이 시리즈에서 작성한 apollo-client + react 서버를 예로 들면 `main.tsx에 아래의 설정을 추가한다.

const httpLink = createHttpLink({
  uri: 'http://localhost:4000/graphql',
  // credentials 설정 추가
  credentials: "include",
});

const authLink = setContext((_, { headers }) => {
  return {
    headers: {
      ...headers,
      // Header 설정 추가
      'Access-Control-Allow-Origin': 'http://localhost:4000',
      'Access-Control-Allow-Credentials': true,
    }
  }
});

const errorLink = onError((err: any) => {
  if (err.graphQLErrors) {
    handleGraphQLError(err);
  }
})

const link = ApolloLink.from([errorLink, authLink.concat(httpLink)])

여기서 include로 옵션을 줬는데 옵션 종류는 다음과 같다.

same-origin(기본값) : 같은 Origin 사이에만 인증 정보를 담는다.
include : 모든 요청에 인증 정보를 담는다.
omit : 모든 요청에 인증 정보를 담지 않는다.




apollo-server 설정


근데 여기서 문제가 발생했는데, 이 설정을 끝냈는데도 CORS가 해결이 안되는 것이다. 그래서 며칠동안 구글링하다가 한줄기 빛을 겨우 발견했다. 쉽게 말하면 apollo-server-express 자체가 express 서버에 미들웨어로 apollo-server를 얹은 형태라 두 개의 서버가 하나의 서버에서 돌아가고 있는 형태라는 것이다. 즉 한쪽에만 cors 설정을 해줘도 한쪽에서 막히기 때문에 cors에러가 해결이 안되는 것..

다시 돌아가서 server.tsapollo-server 설정 부분에 다음 설정을 추가해준다.

/**
 * Express app에 Apollo 연결 
 */
const con = async() => {
  await server.start();
  // cors 설정 추가
  server.applyMiddleware({ app, path: "/graphql", cors: { origin: 'http://localhost:5173', credentials: true } });
}
con();

그랬더니 바로 해결됬다.

이 위대하신 분 없었으면 진짜 얼마나 걸렸을 지 예상도 안된다. 알고보면 이유가 간단한데 그 전에는 설정을 다 했는데 왜 자꾸 CORS 에러가 뜨는지 멘탈이 여러번 날아갔다.

또 다른 나같은 분이 계시면 꼭 도움이 되면 좋겠다.




참조


[GraphQL] apollo-server 세팅하기 - NodeJS (apollo-server-express)

profile
개발공부를해보자

0개의 댓글

관련 채용 정보