Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
5ac0bd6
feat: ClaudeCode 프론트 구축
wannabeing Jun 12, 2025
5513cea
feat: ReactQuery 적용 및 백엔드 연동
wannabeing Jun 12, 2025
a13dbbd
fix: periods 오타수정
Ksr-ccb Jun 12, 2025
d4e927c
feat: nginx 설정
wannabeing Jun 12, 2025
26f364b
feat: Docker, Nginx 설정
wannabeing Jun 12, 2025
d082529
feat: git actions 배포 설정
wannabeing Jun 12, 2025
454dffa
chore: 환경변수 설정
wannabeing Jun 13, 2025
7c1f449
chore: 환경변수 이름 변경
wannabeing Jun 13, 2025
4b91f06
Merge branch 'dev' of https://github.com/NBC-finalProject/CS25-FE int…
Ksr-ccb Jun 13, 2025
675cac4
chore: SSL 인증서 적용
Ksr-ccb Jun 13, 2025
d7c670a
Merge pull request #2 from NBC-finalProject/chore/1
Ksr-ccb Jun 13, 2025
5307f2b
chore: SSL 인증서 마운트
Ksr-ccb Jun 13, 2025
3918798
chore: https 포트번호 추가
Ksr-ccb Jun 13, 2025
0303856
fix: index 페이지 포워딩 문제
Ksr-ccb Jun 13, 2025
e6ba85f
chore: 환경변수 설정 변경
wannabeing Jun 13, 2025
0c45af4
chore: OAuth2 프록시 주소 수정
wannabeing Jun 13, 2025
55cdcd5
chore: HTTP 요청 URL 수정
wannabeing Jun 13, 2025
106f0b0
chore: BASE URL 수정
wannabeing Jun 13, 2025
8ea7532
chore: fetch 래퍼 수정
wannabeing Jun 13, 2025
cc00a40
feat: 오늘의 문제 템플릿 추가
wannabeing Jun 17, 2025
bf61642
fix: 빌드에러 수정
wannabeing Jun 17, 2025
7fd6ed2
chore: manifest 추가
wannabeing Jun 19, 2025
def1fd4
chore: 모달 자연스럽게 뜨도록 변경
wannabeing Jun 19, 2025
10e7124
chore: 연습문제 수정
wannabeing Jun 19, 2025
f71e636
refactor: 오늘의문제 가져오기&답안제출 기능 리팩토링
wannabeing Jun 19, 2025
c0ff10b
feat: 구독정보 수정 로직 추가
wannabeing Jun 19, 2025
4a6cf15
chore: 모달창 UX 개선
wannabeing Jun 20, 2025
7f915e6
chore: 예시 구독설정 버튼 비활성화
wannabeing Jun 20, 2025
7b3a62f
chore: 요청시 쿠키 담아서보내기
Ksr-ccb Jun 20, 2025
b4f0964
refactor: 오늘의 문제 리팩토링 및 메인 모바일버전 리팩토링
wannabeing Jun 20, 2025
2d7a9b6
chore: 오늘의문제 디자인 수정
wannabeing Jun 24, 2025
6461f5e
chore: CS25 로고 변경
wannabeing Jun 25, 2025
5516eb2
feat: 마이페이지 구현 및 로그인,로그아웃 기능 추가
wannabeing Jun 25, 2025
d84fd50
chore: 푸터, 예시메일 등 디자인 수정 및 빌드 에러 수정
wannabeing Jun 25, 2025
960c23c
chore: deploy.yml 필요없는 주석 삭제
wannabeing Jun 26, 2025
96a526b
chore: 파비콘 수정
wannabeing Jun 26, 2025
7daddb0
chore: 파비콘 에러 수정
wannabeing Jun 26, 2025
cf61c44
chore: 디버깅용 로그 삭제 및 주석처리
wannabeing Jun 26, 2025
98cb87b
chore: 필요없는 파일 삭제
wannabeing Jun 26, 2025
2b6a988
chore: 불필요한 이모티콘 삭제
wannabeing Jun 27, 2025
dec14be
refactor: api 호출시 nginx가 요청을 ec2->Ec2 형식으로 올리게 하기
Ksr-ccb Jun 27, 2025
6fcd90b
refactor: 브라우저 api호출을 프론트가 받아서 백으로 넘기게 설정
Ksr-ccb Jun 27, 2025
d8b732f
refactor: /api/ 접두어 제거안돼서 다시시도
Ksr-ccb Jun 27, 2025
826d466
refactor: oauth도 백엔드로 요청넘기게 바꿈
Ksr-ccb Jun 27, 2025
3ed305e
refactor: oauth 로그인이 프론트에서 작동하려고 한다...
Ksr-ccb Jun 27, 2025
da8449c
refactor: 오류떠서 롤백
Ksr-ccb Jun 27, 2025
886e3aa
refactor: 오류떠서 롤백
Ksr-ccb Jun 27, 2025
d814740
refactor: 로그인 리다이렉트 uri 조정
Ksr-ccb Jun 27, 2025
4b91133
refactor: 로그인 리다이렉트 uri 조정
Ksr-ccb Jun 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
npm-debug.log
build
.git
.gitignore
README.md
.env
.nyc_output
coverage
.vscode
.idea
39 changes: 39 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Frontend CD with Docker Hub
on:
push:
branches:
- dev # dev push되었을 때 yml 실행
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{secrets.DOCKERHUB_USERNAME}} # 도커 허브 이름
password: ${{secrets.DOCKERHUB_TOKEN}} # 도커 허브 access token
- name: Build and Release
run: |
docker build \
--build-arg VITE_API_URL=${{ secrets.VITE_API_URL }} \
-t ${{secrets.DOCKERHUB_REPO}} .
docker tag ${{secrets.DOCKERHUB_REPO}}:latest ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
docker push ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
- name: Deploy to server
uses: appleboy/ssh-action@master
id: deploy
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
sudo docker rm -f $(docker ps -aqf "name=^${{secrets.DOCKERHUB_REPO}}")
sudo docker pull ${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
sudo docker run \
-e VITE_API_URL=${{ secrets.VITE_API_URL }} \
-v /etc/letsencrypt:/etc/letsencrypt:ro \
-d -p 80:80 -p 443:443 \
--name ${{secrets.DOCKERHUB_REPO}} \
${{secrets.DOCKERHUB_USERNAME}}/${{secrets.DOCKERHUB_REPO}}:latest
sudo docker image prune -f
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# intellij
/.idea

# claude
/.claude

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
40 changes: 40 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 멀티 스테이지 빌드
# 1단계: 빌드 스테이지
FROM node:20-alpine AS builder

WORKDIR /app

# package.json과 package-lock.json 복사
COPY package*.json ./

# 의존성 설치 (빌드에 필요한 devDependencies 포함)
RUN npm ci

# 소스 코드 복사
COPY . .

# build-time ARG 정의
ARG VITE_API_URL
ENV VITE_API_URL=$VITE_API_URL

# Vite로 빌드
RUN echo "VITE_API_URL=$VITE_API_URL"
RUN npm run build

# 2단계: 프로덕션 스테이지
FROM nginx:alpine

# 기본 nginx 설정 제거
RUN rm /etc/nginx/conf.d/default.conf

# nginx 템플릿 복사
COPY nginx.conf.template /etc/nginx/templates/

# 빌드된 정적 파일 복사
COPY --from=builder /app/build /usr/share/nginx/html

# 포트 80 노출
EXPOSE 80

# nginx 실행
CMD ["nginx", "-g", "daemon off;"]
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Getting Started with Create React App

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

## Available Scripts

In the project directory, you can run:

### `npm start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.\
You will also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

### `npm run build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### `npm run eject`

**Note: this is a one-way operation. Once you `eject`, you can’t go back!**

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.

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.

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.

## Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: '3.8'

services:
frontend:
build: .
ports:
- "5173:80"
networks:
- app-network

networks:
app-network:
driver: bridge
25 changes: 25 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="CS 지식을 해설과 함께 전달하는 메일 서비스"
/>
<link rel="apple-touch-icon" href="/cs25.png" />
<link rel="manifest" href="/manifest.json" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.min.css" />
<title>CS25 - 해설과 함께하는 CS 학습</title>
</head>
<body>
<noscript>JavaScript를 활성화해주세요.</noscript>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
100 changes: 100 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
server {
listen 443 ssl;
server_name cs25.co.kr www.cs25.co.kr;

ssl_certificate /etc/letsencrypt/live/cs25.co.kr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cs25.co.kr/privkey.pem;

root /usr/share/nginx/html;
index index.html;

# React Router를 위한 설정
location / {
try_files $uri $uri/ /index.html;
}

# API 요청 프록시
location /api/ {
rewrite ^/api/(.*)$ /$1 break; # /api 접두어 제거
proxy_pass ${VITE_API_URL};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# CORS 설정
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;

# OPTIONS 프리플라이트 응답
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
}

# OAuth2 인증 프록시
location /oauth2/ {
proxy_pass proxy_pass ${VITE_API_URL};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}

# 로그인 리다이렉트
location /login/ {
proxy_pass ${VITE_API_URL}/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}

# OAuth2 로그인 리다이렉트 처리 (Spring Security가 처리하는 기본 경로)
location /login/oauth2/ {
proxy_pass ${VITE_API_URL}/login/oauth2/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# 정적 자산 캐싱
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}

# gzip 설정
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/x-javascript
application/xml+rss
application/javascript
application/json;

}

server {
listen 80;
server_name cs25.co.kr www.cs25.co.kr;
return 301 https://$host$request_uri;
}
Loading
Loading