Skip to content

Commit b718da6

Browse files
authored
Merge pull request #3 from NBC-finalProject/dev
feat: CS25 프론트엔드 1차 배포
2 parents 199df29 + 4b91133 commit b718da6

60 files changed

Lines changed: 9136 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
node_modules
2+
npm-debug.log
3+
build
4+
.git
5+
.gitignore
6+
README.md
7+
.env
8+
.nyc_output
9+
coverage
10+
.vscode
11+
.idea

.github/workflows/deploy.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Frontend CD with Docker Hub
2+
on:
3+
push:
4+
branches:
5+
- dev # dev push되었을 때 yml 실행
6+
jobs:
7+
build:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Login to DockerHub
12+
uses: docker/login-action@v1
13+
with:
14+
username: ${{secrets.DOCKERHUB_USERNAME}} # 도커 허브 이름
15+
password: ${{secrets.DOCKERHUB_TOKEN}} # 도커 허브 access token
16+
- name: Build and Release
17+
run: |
18+
docker build \
19+
--build-arg VITE_API_URL=${{ secrets.VITE_API_URL }} \
20+
-t ${{secrets.DOCKERHUB_REPO}} .
21+
docker tag ${{secrets.DOCKERHUB_REPO}}:latest ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
22+
docker push ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
23+
- name: Deploy to server
24+
uses: appleboy/ssh-action@master
25+
id: deploy
26+
with:
27+
host: ${{ secrets.HOST }}
28+
username: ${{ secrets.USERNAME }}
29+
key: ${{ secrets.KEY }}
30+
script: |
31+
sudo docker rm -f $(docker ps -aqf "name=^${{secrets.DOCKERHUB_REPO}}")
32+
sudo docker pull ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
33+
sudo docker run \
34+
-e VITE_API_URL=${{ secrets.VITE_API_URL }} \
35+
-v /etc/letsencrypt:/etc/letsencrypt:ro \
36+
-d -p 80:80 -p 443:443 \
37+
--name ${{secrets.DOCKERHUB_REPO}} \
38+
${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
39+
sudo docker image prune -f

.gitignore

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# intellij
4+
/.idea
5+
6+
# claude
7+
/.claude
8+
9+
# dependencies
10+
/node_modules
11+
/.pnp
12+
.pnp.js
13+
14+
# testing
15+
/coverage
16+
17+
# production
18+
/build
19+
20+
# misc
21+
.DS_Store
22+
.env
23+
.env.local
24+
.env.development.local
25+
.env.test.local
26+
.env.production.local
27+
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*

Dockerfile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# 멀티 스테이지 빌드
2+
# 1단계: 빌드 스테이지
3+
FROM node:20-alpine AS builder
4+
5+
WORKDIR /app
6+
7+
# package.json과 package-lock.json 복사
8+
COPY package*.json ./
9+
10+
# 의존성 설치 (빌드에 필요한 devDependencies 포함)
11+
RUN npm ci
12+
13+
# 소스 코드 복사
14+
COPY . .
15+
16+
# build-time ARG 정의
17+
ARG VITE_API_URL
18+
ENV VITE_API_URL=$VITE_API_URL
19+
20+
# Vite로 빌드
21+
RUN echo "VITE_API_URL=$VITE_API_URL"
22+
RUN npm run build
23+
24+
# 2단계: 프로덕션 스테이지
25+
FROM nginx:alpine
26+
27+
# 기본 nginx 설정 제거
28+
RUN rm /etc/nginx/conf.d/default.conf
29+
30+
# nginx 템플릿 복사
31+
COPY nginx.conf.template /etc/nginx/templates/
32+
33+
# 빌드된 정적 파일 복사
34+
COPY --from=builder /app/build /usr/share/nginx/html
35+
36+
# 포트 80 노출
37+
EXPOSE 80
38+
39+
# nginx 실행
40+
CMD ["nginx", "-g", "daemon off;"]

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Getting Started with Create React App
2+
3+
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4+
5+
## Available Scripts
6+
7+
In the project directory, you can run:
8+
9+
### `npm start`
10+
11+
Runs the app in the development mode.\
12+
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13+
14+
The page will reload if you make edits.\
15+
You will also see any lint errors in the console.
16+
17+
### `npm test`
18+
19+
Launches the test runner in the interactive watch mode.\
20+
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21+
22+
### `npm run build`
23+
24+
Builds the app for production to the `build` folder.\
25+
It correctly bundles React in production mode and optimizes the build for the best performance.
26+
27+
The build is minified and the filenames include the hashes.\
28+
Your app is ready to be deployed!
29+
30+
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31+
32+
### `npm run eject`
33+
34+
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35+
36+
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37+
38+
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39+
40+
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41+
42+
## Learn More
43+
44+
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45+
46+
To learn React, check out the [React documentation](https://reactjs.org/).

docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: '3.8'
2+
3+
services:
4+
frontend:
5+
build: .
6+
ports:
7+
- "5173:80"
8+
networks:
9+
- app-network
10+
11+
networks:
12+
app-network:
13+
driver: bridge

index.html

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<!DOCTYPE html>
2+
<html lang="ko">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="CS 지식을 해설과 함께 전달하는 메일 서비스"
11+
/>
12+
<link rel="apple-touch-icon" href="/cs25.png" />
13+
<link rel="manifest" href="/manifest.json" />
14+
<link rel="preconnect" href="https://fonts.googleapis.com">
15+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
16+
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
17+
<link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.min.css" />
18+
<title>CS25 - 해설과 함께하는 CS 학습</title>
19+
</head>
20+
<body>
21+
<noscript>JavaScript를 활성화해주세요.</noscript>
22+
<div id="root"></div>
23+
<script type="module" src="/src/index.tsx"></script>
24+
</body>
25+
</html>

nginx.conf

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
server {
2+
listen 443 ssl;
3+
server_name cs25.co.kr www.cs25.co.kr;
4+
5+
ssl_certificate /etc/letsencrypt/live/cs25.co.kr/fullchain.pem;
6+
ssl_certificate_key /etc/letsencrypt/live/cs25.co.kr/privkey.pem;
7+
8+
root /usr/share/nginx/html;
9+
index index.html;
10+
11+
# React Router를 위한 설정
12+
location / {
13+
try_files $uri $uri/ /index.html;
14+
}
15+
16+
# API 요청 프록시
17+
location /api/ {
18+
rewrite ^/api/(.*)$ /$1 break; # /api 접두어 제거
19+
proxy_pass ${VITE_API_URL};
20+
proxy_set_header Host $host;
21+
proxy_set_header X-Real-IP $remote_addr;
22+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
23+
proxy_set_header X-Forwarded-Proto $scheme;
24+
25+
# CORS 설정
26+
add_header 'Access-Control-Allow-Origin' '*' always;
27+
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
28+
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
29+
30+
# OPTIONS 프리플라이트 응답
31+
if ($request_method = 'OPTIONS') {
32+
add_header 'Access-Control-Allow-Origin' '*' always;
33+
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
34+
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
35+
add_header 'Access-Control-Max-Age' 1728000 always;
36+
add_header 'Content-Type' 'text/plain; charset=utf-8';
37+
add_header 'Content-Length' 0;
38+
return 204;
39+
}
40+
}
41+
42+
# OAuth2 인증 프록시
43+
location /oauth2/ {
44+
proxy_pass proxy_pass ${VITE_API_URL};
45+
proxy_set_header Host $host;
46+
proxy_set_header X-Real-IP $remote_addr;
47+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
48+
proxy_set_header X-Forwarded-Proto $scheme;
49+
proxy_set_header X-Forwarded-Host $host;
50+
proxy_set_header X-Forwarded-Port $server_port;
51+
}
52+
53+
# 로그인 리다이렉트
54+
location /login/ {
55+
proxy_pass ${VITE_API_URL}/;
56+
proxy_set_header Host $host;
57+
proxy_set_header X-Real-IP $remote_addr;
58+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
59+
proxy_set_header X-Forwarded-Proto $scheme;
60+
proxy_set_header X-Forwarded-Host $host;
61+
proxy_set_header X-Forwarded-Port $server_port;
62+
}
63+
64+
# OAuth2 로그인 리다이렉트 처리 (Spring Security가 처리하는 기본 경로)
65+
location /login/oauth2/ {
66+
proxy_pass ${VITE_API_URL}/login/oauth2/;
67+
proxy_set_header Host $host;
68+
proxy_set_header X-Real-IP $remote_addr;
69+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
70+
proxy_set_header X-Forwarded-Proto $scheme;
71+
}
72+
73+
# 정적 자산 캐싱
74+
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
75+
expires 1y;
76+
add_header Cache-Control "public, max-age=31536000, immutable";
77+
}
78+
79+
# gzip 설정
80+
gzip on;
81+
gzip_vary on;
82+
gzip_min_length 1024;
83+
gzip_proxied expired no-cache no-store private auth;
84+
gzip_types
85+
text/plain
86+
text/css
87+
text/xml
88+
text/javascript
89+
application/x-javascript
90+
application/xml+rss
91+
application/javascript
92+
application/json;
93+
94+
}
95+
96+
server {
97+
listen 80;
98+
server_name cs25.co.kr www.cs25.co.kr;
99+
return 301 https://$host$request_uri;
100+
}

0 commit comments

Comments
 (0)