포스트

[트러블 슈팅] 프론트 페이지에서 API요청, 페이지 요청 분리하기 (feat. Proxy)

1. 문제 상황

적은 학습, 빠른 결과물 출력을 위해 svelte를 도입해 간단한 프론트 페이지를 만들었다.

로컬에서는 원하는 기능이 모두 이루어졌지만, docker-compose를 통해 컨테이너를 만들어 프론트엔드 서버와 백엔드 서버가 서로 내부 통신을 하게 만들었더니 작동하지 않았다.

좀 더 구체적으로 문제 상황을 분석해보면

  1. 백엔드 서버에서 오류가 난 것이 아닌, 아예 통신하지 못함. (백엔드 서버 로그에 아무것도 뜨지 않았음.)
  2. CORS 관련 오류는 제외(이미 로컬에서 확인했음.) 여기에서 확인
  3. 로컬 → 도커서버로 올리면서 변경사항
    1. 백엔드 origin을 http://localhost:80 에서 http://backend:80 로 변경했음. (이 경우 내부 포트 설정 오류)
    2. Vite.config 설정에 아래와 같이 추가했음.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
       server: {
           host: '0.0.0.0',
           port: 5173,
           cors: true,
           proxy: {
             '/api': {
               target: process.env.VITE_API_BASE_URL,
               changeOrigin: true,
               rewrite: (path) => path.replace(/^\/api/, '/api/magical_shell')
             }
           }
         }
      

사실 이 코드는 제대로 알고 작성한 것은 아니고 검색해서 복사했다.(이게 큰 실수였다.)

2. 문제 해결

수많은 시행착오 끝에 위에서 복붙한 코드가 문제라고 생각해 결국 여러 개념들을 검색해봤다.

2.1 Proxy

영단어 Proxy는 대리자, 대리권(권리) 의 뜻을 가지며, 위 코드에서 쓰인 Proxy는 특정 경로로 들어오는 요청을 다른 서버로 중계해주는 역할을 한다.

이때 중계해주는 대상은 최종 사용자(client) 와 서버이다.

즉 위에 쓰인 코드의 뜻은 다음과 같다.

1
2
'/api': {
        target: process.env.VITE_API_BASE_URL,

/api로 시작하는 모든 요청을 .env에서 설정한 VITE_API_BASE_URL로 지정한 백엔드 서버에 전달한다.

1
changeOrigin: true,

프록시 요청을 보낼 때 원본(origin)을 변경해 백엔드 서버와 클라이언트를 분리한다.

1
rewrite: (path) => path.replace(/^\/api/, '/api/magical_shell')

요청 경로를 재작성한다.

프론트 서버에서 “/api” 로 시작하는 경로를 “/api/magical_shell”로 변경한다.

예를 들어 “/api/abcd” 로 요청이 들어온다면, 백엔드 서버에는 “/api/magical_shell/abcd”로 변경되어 전달한다.

즉, 실질적으로 요청을 보내고 받는 API 경로와, 단순 사용자가 페이지를 이동할때 사용하는 경로를 분리하기 위함이었다.

결국 문제는 프론트의 js코드에서 백엔드로 요청되는 경로들을 수정하여 해결했다.

근데, 굳이 이런 번거로운 설정을 거치는 이유가 뭘까?

2.2 경로 분리의 이유

  1. 명확한 경로 분리
    1. API의 엔드포인트와 프론트엔드의 경로를 명확히 구분해 사람이 유지보수하기 쉽게 한다.
    2. 경로가 중복되지 않도록 하여, /users 같은 경로가 단순 페이지 요청인지, API 요청인지 구분한다.
  2. 보안 및 접근 제어
    1. API 요청 혹은 페이지 요청에 대하여 각각 보안 설정을 해줄 수 있다.

얻은 교훈: 복붙할때는 코드의 뜻을 제대로 알고 하자…



이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.