사전 지식
Apache Proxy
•
아파치 웹 서버를 사용하여 Client 요청을 중개하는 기능
•
ProxyPass [path] [url] : Client가 [path]로 요청을 한 경우에만 [url]로 요청을 보냅니다.
•
ProxyPassReverse [path] [url] : 백엔드[path]의 응답을 프록시 서버/[url]로 변환합니다.
AWS CloudFront
•
전세계에 Edge Server를 두고 Client에 가장 가까운 서버를 찾아 지연을 최소화하는 Content Delivery Server(CDN)으로 역할은 아래와 같습니다.
◦
캐싱 및 최적화 : 자체 캐싱
◦
보안 및 인증 : 요청 포워딩을 통해 사용자 제어
◦
라우팅 : 요청 포워딩을 사용하여 클라이언트 요청을 원본 서버로 라우팅
•
요청 포워딩
◦
클라이언트가 Cloudfront에게 요청한 원본 컨텐츠를 어떻게 전달할지 제어하는 메커니즘
S3
•
AWS에서 제공하는 스토리지로 데이터를 저장하고, 관리하는 클라우드 스토리지 솔루션입니다.
환경 이해하기
1.
기존 서버에 추가적인 페이지를 신규 서버로 구축
2.
URL은 ServiceURL/cms로 결정
3.
Apache Proxy, AWS Cloud Front, AWS S3 사용
아래에선 Sequence Diagram으로 설명을 합니다. 단 Return되어 오는 값의 경로는 생략해서 나타냈습니다.
Apache Proxy
기존에도 아파치의 경우 path에 따른 라우팅 처리가 있는 상태였습니다.
<VirtualHost *:80>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /file/ http://file_service.com/file/ ttl=60 disablereuse=on
ProxyPassReverse /file/ http://file_service.com/file/
ProxyPass / http://exist_service.com/ ttl=60 disablereuse=on
ProxyPassReverse / http://exist_service.com/
</VirtualHost>
Plain Text
복사
apache httpd.conf
필요한 서버로 라우팅해주는 코드들이 있어 신규 서버분기 처리를 DevOps팀에서 설정해준 상태였습니다.
<VirtualHost *:80>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /file/ http://file_service.com/file/ ttl=60 disablereuse=on
ProxyPassReverse /file/ http://file_service.com/file/
ProxyPass /cms/ http://cloudfront.net ttl=60 disablereuse=on
ProxyPassReverse /cms/ http://cloudfront.net
ProxyPass / http://exist_service.com/ ttl=60 disablereuse=on
ProxyPassReverse / http://exist_service.com/
</VirtualHost>
Plain Text
복사
apache httpd.conf
AWS Cloud Front
1.
들어온 요청들 중 특정 요청들을 S3 파일에 매핑해줍니다
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> A: service.com/cms/ A ->> CF: cloudfront.net CF ->> S3: S3/index.html S3 -->> C: index.html
Mermaid
복사
2.
만약 등록되지 않은 요청의 경우, S3에서 해당 동일한 경로를 탐색합니다.
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> A: service.com/cms/assets/index.css A ->> CF: cloudfront.net/assets/index.css CF ->> S3: S3/assets/index.css S3 -->> C: index.css
Mermaid
복사
3.
일치하는 경로가 없는 이외의 요청(ex. SPA Router에 등록한 URL)은 Error를 띄우고, 이를 특정 파일로 요청을 보냅니다.
ServiceUrl/cms/list → S3/cms/list → 403, 404 →
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> A: service.com/cms/list A ->> CF: cloudfront.net/list CF ->> S3: S3/list S3 -->> CF: [404] CF ->> S3: S3/index.html S3 -->> C: index.html C ->> C: /cms/list
Mermaid
복사
AWS S3
Vite의 기본 설정으론 아래와 같이 빌드됩니다.
S3
•
index.html
•
assets
◦
index.js
◦
index.css
경로 맞추기
Apache Proxy → … → S3 경로 맞추기
문제
index.html은 정상적으로 호출하는 하지만, .js .css파일을 제대로 못 불러오는 문제가 발생했습니다.
원인은 아무 설정 없이 빌드 시 html에서 assets로 매핑되기 때문에 엉뚱한 곳으로 proxy되기 때문이 였습니다.
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>title</title>
<script type="module" crossorigin src="/assets/index-039d9ea0.js"></script>
<script type="module" crossorigin src="/assets/index-0g459wc1.css"></script>
</head>
JavaScript
복사
dist/index.html
위와 같이 호출하게 될 시 아래와 같은 경로로 호출됩니다.
sequenceDiagram participant C as Client participant A as Apache Proxy participant ES as Exist Service C ->> A: service.com/assets/index.js A ->> ES: service.com/assets/index.js ES -->> C: 404.html
Mermaid
복사
해결
vite.config.js에서 base옵션을 통해 /cms/가 접두에 붙도록 설정했습니다.
export default defineConfig({
plugins: [react()],
...
},
base: '/cms/'
});
JavaScript
복사
vite.config.js
설정을 이렇게 변경해주니 ServiceURL에서 정상적으로 호출이 되었습니다.
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>title</title>
<script type="module" crossorigin src="/cms/assets/index-039d9ea0.js"></script>
<script type="module" crossorigin src="/cms/assets/index-0g459wc1.css"></script>
</head>
JavaScript
복사
index.html
위와 같이 호출하게 될 시 아래와 같은 경로로 호출되어 문제가 해결됩니다.
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> A: service.com/cms/assets/index.js A ->> CF: cloudfront.net/assets/index.js CF ->> S3: S3/assets/index.js S3 -->> C: index.js
Mermaid
복사
AWS Cloud Front → … → S3 경로 맞추기
문제
하지만 cloudfront의 DNS를 통해서 접속했을 때 index.html에서 파일을 호출할 때 문제가 발생했습니다.
index.html의 경우 cloudfront.net/cms로 호출해도 에러 처리를 통해서 index.html로 redirect되었지만, assets/index.js 호출 또한 에러 처리로 index.html이 리턴되어 의도치 않은 결과가 나왔습니다.
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> CF: cloudfront.net/cms/assets/index.js CF ->> S3: cloudfront.net/cms/assets/index.js S3 -->> CF: [404] CF ->> S3: S3/index.html S3 -->> C: index.html
Mermaid
복사
해결
1.
service.com/cms의 경로를 cloudfront.net/cms로 변환되도록 https.conf를 변경해주었습니다.
ProxyPass /cms/ http://cloudfront.net ttl=60 disablereuse=on
> ProxyPass /cms/ http://cloudfront.net/cms ttl=60 disablereuse=on
ProxyPassReverse /cms/ http://cloudfront.net
> ProxyPassReverse /cms/ http://cloudfront.net/cms
Plain Text
복사
apache httpd.conf
2.
vite.config.js의 base: /cms/를 제거 후 build 파일의 이름을 assets에서 cms로 변경해주었습니다.
export default defineConfig({
...
base: '/cms/'
> build: {
assetsDir: 'cms',
},
});
JavaScript
복사
vite.config.js
해당 옵션을 통해 아래와 같이 빌드파일 이름이 바뀌게 됩니다.
S3
•
index.html
•
cms
◦
index.js
◦
index.css
작업 결과 플로우
S3 구조
S3
•
index.html
•
cms
◦
index.js
◦
index.css
dist/index.html
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>title</title>
<script type="module" crossorigin src="/cms/index-039d9ea0.js"></script>
<script type="module" crossorigin src="/cms/index-0g459wc1.css"></script>
</head>
JavaScript
복사
index.html
service.com/cms/list 페이지 진입
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> A: service.com/cms/list A ->> CF: cloudfront.net/cms/list CF ->> S3: S3/cms/list S3 -->> CF: [404] CF ->> S3: S3/index.html S3 -->> C: index.html C ->> C: /cms/list
Mermaid
복사
service.com/cms/index.js 호출
sequenceDiagram participant C as Client participant A as Apache Proxy participant CF as AWS CloudFront participant S3 as AWS S3 C ->> A: service.com/cms/index.js A ->> CF: cloudfront.net/cms/index.js CF ->> S3: S3/cms/index.js S3 -->> C: index.js
Mermaid
복사
cloudfront.net 페이지 진입
sequenceDiagram participant C as Client participant CF as AWS CloudFront participant S3 as AWS S3 C ->> CF: cloudfront.net CF ->> S3: S3 S3 -->> C: index.html
Mermaid
복사
cloudfront.net/cms/list 페이지 진입
sequenceDiagram participant C as Client participant CF as AWS CloudFront participant S3 as AWS S3 C ->> CF: cloudfront.net/cms/list CF ->> S3: S3/cms/list S3 -->> CF: [404] CF ->> S3: S3/index.html S3 -->> C: index.html C ->> C: /cms/list
Mermaid
복사
cloudfront.net/cms/index.js 호출
sequenceDiagram participant C as Client participant CF as AWS CloudFront participant S3 as AWS S3 C ->> CF: cloudfront.net/cms/index.js CF ->> S3: S3/cms/index.js S3 -->> C: index.js
Mermaid
복사