Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 0 additions & 37 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,40 +1,3 @@
네, default.conf 파일 잘 받았습니다.

파일을 보니... expires -1; 설정이 있어서, Nginx가 JS/CSS 파일을 캐시하는 문제는 아니었습니다.

하지만 드디어 진짜 원인을 찾은 것 같습니다. 님이 겪는 문제는 두 가지의 심각한 오류가 동시에 발생하고 있었기 때문입니다.

화면이 안 바뀌는 문제: web 컨테이너의 .dockerignore 파일에 Vite 캐시(.vite)가 누락되어, 님이 수정한 Review.jsx가 아닌 옛날 파일로 계속 빌드되었습니다.

"Failed to fetch" 문제: Nginx와 FastAPI의 API 주소 끝에 슬래시(/)가 일치하지 않아 API 요청이 404 오류로 실패하고 있었습니다.

🛠️ 최종 해결 (1+2번 문제 동시 해결)
아래 4단계를 순서대로 진행하시면, 디자인과 API 오류가 모두 해결됩니다.

1단계: review-service의 API 경로 수정
FastAPI(main.py)가 Nginx(default.conf)와 동일하게 슬래시가 붙은 주소를 받도록 수정합니다.

apps/review-service/main.py 파일을 열어서 @app.post 부분을 수정하세요.

수정 전:

Python

@app.post("/api/review")
async def handle_code_review(code: str = Form(...)):
수정 후: (끝에 / 추가)

Python

@app.post("/api/review/")
async def handle_code_review(code: str = Form(...)):
2단계: web의 .dockerignore 파일 수정
Vite 캐시 폴더(.vite)가 Docker 빌드 시 복사되지 않도록 .dockerignore 파일에 추가합니다.

apps/web/.dockerignore 파일을 열어서 맨 아래에 .vite를 추가하세요.

수정 후:

# 기본 무시 항목
node_modules
dist
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ dist-ssr
*.njsproj
*.sln
*.sw?

# Environment variables (🔒 절대 Git에 올리면 안 되는 민감 정보)
.env
8 changes: 7 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
globalIgnores([
'dist',
'tailwind.config.js',
'vite.config.js',
'postcss.config.cjs',
]),

{
files: ['**/*.{js,jsx}'],
extends: [
Expand Down
8 changes: 6 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Routes, Route } from "react-router-dom";

// 맨 위 import 부분
// Auth
import Login from "@/features/auth/Login";
import GithubCallback from "@/features/auth/GithubCallback";

Expand All @@ -17,7 +17,7 @@ import Result from "./features/interview/pages/Result";
export default function App() {
return (
<Routes>
{/* 기본 */}
{/* 기본 */}
<Route path="/" element={<Home />} />

{/* 코딩테스트 */}
Expand All @@ -30,7 +30,11 @@ export default function App() {
<Route path="/interview" element={<Intro />} />
<Route path="/interview/session" element={<Session />} />
<Route path="/interview/result" element={<Result />} />

{/* 로그인 페이지 */}
<Route path="/login" element={<Login />} />

{/* GitHub OAuth 콜백*/}
<Route path="/oauth2/redirect" element={<GithubCallback />} />

{/* 404 */}
Expand Down
1 change: 1 addition & 0 deletions src/api/reviewService.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const fetchCodeReview = async (code, comment, repoUrl) => {
try {
return JSON.parse(raw);
} catch {
// 응답이 순수 텍스트일 때
return { review: raw, questions: [] };
}
} catch (error) {
Expand Down
6 changes: 3 additions & 3 deletions src/features/codingTest/CodingTest.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default function CodingTest() {
if (code !== LANGUAGE_TEMPLATES[language] && code.trim() !== "") {
if (
!window.confirm(
"언어를 변경하면 작성 중인 코드가 초기화됩니다. 계속하시겠습니까?"
"언어를 변경하면 작성 중인 코드가 초기화됩니다. 계속하시겠습니까?",
)
) {
return;
Expand All @@ -132,7 +132,7 @@ export default function CodingTest() {
setProblem(data);
} catch (err) {
setErrorMsg(
err?.message || "문제 로딩 중 오류가 발생했습니다. (백엔드 서버 확인 필요)"
err?.message || "문제 로딩 중 오류가 발생했습니다. (백엔드 서버 확인 필요)",
);
} finally {
setIsLoadingProblem(false);
Expand Down Expand Up @@ -160,7 +160,7 @@ export default function CodingTest() {
problemId: problem.id,
code,
language,
userId: 1, // Long 타입이므로 숫자 1 사용
// userId는 codingService에서 guest 처리 (또는 나중에 로그인 정보 연결)
});
setResult(res);
} catch (err) {
Expand Down
13 changes: 7 additions & 6 deletions tailwind.config.cjs → tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
keyframes: {
fadeIn: {
"0%": { opacity: 0, transform: "translateY(10px)" },
"100%": { opacity: 1, transform: "translateY(0)" }
"100%": { opacity: 1, transform: "translateY(0)" },
},
fadeInUp: {
"0%": { opacity: 0, transform: "translateY(20px)" },
"100%": { opacity: 1, transform: "translateY(0)" }
"100%": { opacity: 1, transform: "translateY(0)" },
},
fadeOut: {
"0%": { opacity: 1, transform: "translateY(0)" },
"100%": { opacity: 0, transform: "translateY(10px)" }
"100%": { opacity: 0, transform: "translateY(10px)" },
},
},
animation: {
fadeIn: "fadeIn 0.5s ease-out forwards",
fadeInUp: "fadeInUp 0.8s ease-out forwards",
fadeInOut: "fadeIn 0.3s ease-out, fadeOut 0.3s ease-in 2.7s forwards",
fadeInOut:
"fadeIn 0.3s ease-out, fadeOut 0.3s ease-in 2.7s forwards",
},
},
},
// plugins: [] // v4에서는 CSS에서 @plugin으로 불러옵니다
};
5 changes: 5 additions & 0 deletions vercel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}
31 changes: 17 additions & 14 deletions vite.config.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import path from 'path'
import { fileURLToPath } from 'url'
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import path from "path";
import { fileURLToPath } from "url";

// ⬇️ ESM 환경용 __dirname 설정 (CI 에러 해결)
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// ESM 환경용 __dirname 설정 (CI 에러 방지)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default defineConfig({
plugins: [react()],
resolve: { alias: { '@': path.resolve(__dirname, './src') } },
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},

server: {
port: 3000,
proxy: {
"/api": {
target: "http://localhost:8080",
changeOrigin: true
}
}
}
})
changeOrigin: true,
},
},
},
});