feat: Add CI/CD pipeline and code quality improvements
- Add GitHub Actions workflow for automated CI/CD - Configure Node.js 18.x and 20.x matrix testing - Add TypeScript type checking step - Add ESLint code quality checks with enhanced rules - Add Prettier formatting verification - Add production build validation - Upload build artifacts for deployment - Set up automated testing on push/PR - Replace console.log with environment-aware logger - Add pre-commit hooks for code quality - Exclude archive folder from linting 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
64
src/main.tsx
64
src/main.tsx
@@ -1,35 +1,39 @@
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import App from './App.tsx';
|
||||
import './index.css';
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { logger } from "@/utils/logger";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
|
||||
console.log('main.tsx loaded');
|
||||
logger.info("main.tsx loaded");
|
||||
|
||||
// iOS 안전 영역 메타 태그 추가
|
||||
const setViewportMetaTag = () => {
|
||||
// 기존 viewport 메타 태그 찾기
|
||||
let metaTag = document.querySelector('meta[name="viewport"]');
|
||||
|
||||
|
||||
// 없으면 새로 생성
|
||||
if (!metaTag) {
|
||||
metaTag = document.createElement('meta');
|
||||
metaTag.setAttribute('name', 'viewport');
|
||||
metaTag = document.createElement("meta");
|
||||
metaTag.setAttribute("name", "viewport");
|
||||
document.head.appendChild(metaTag);
|
||||
}
|
||||
|
||||
|
||||
// content 속성 설정 (viewport-fit=cover 추가)
|
||||
metaTag.setAttribute('content', 'width=device-width, initial-scale=1.0, viewport-fit=cover');
|
||||
metaTag.setAttribute(
|
||||
"content",
|
||||
"width=device-width, initial-scale=1.0, viewport-fit=cover"
|
||||
);
|
||||
};
|
||||
|
||||
// 메타 태그 설정 적용
|
||||
setViewportMetaTag();
|
||||
|
||||
// 전역 오류 핸들러 추가
|
||||
window.onerror = function(message, source, lineno, colno, error) {
|
||||
console.error('전역 오류 발생:', { message, source, lineno, colno, error });
|
||||
|
||||
window.onerror = function (message, source, lineno, colno, error) {
|
||||
logger.error("전역 오류 발생:", { message, source, lineno, colno, error });
|
||||
|
||||
// 오류 발생 시 기본 오류 화면 표시
|
||||
const rootElement = document.getElementById('root');
|
||||
const rootElement = document.getElementById("root");
|
||||
if (rootElement) {
|
||||
rootElement.innerHTML = `
|
||||
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; font-family: Arial, sans-serif;">
|
||||
@@ -46,16 +50,16 @@ window.onerror = function(message, source, lineno, colno, error) {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// 처리되지 않은 Promise 오류 핸들러 추가
|
||||
window.addEventListener('unhandledrejection', function(event) {
|
||||
console.error('처리되지 않은 Promise 오류:', event.reason);
|
||||
|
||||
window.addEventListener("unhandledrejection", function (event) {
|
||||
logger.error("처리되지 않은 Promise 오류:", event.reason);
|
||||
|
||||
// 오류 발생 시 기본 오류 화면 표시
|
||||
const rootElement = document.getElementById('root');
|
||||
const rootElement = document.getElementById("root");
|
||||
if (rootElement) {
|
||||
rootElement.innerHTML = `
|
||||
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; font-family: Arial, sans-serif;">
|
||||
@@ -75,7 +79,7 @@ window.addEventListener('unhandledrejection', function(event) {
|
||||
});
|
||||
|
||||
// 디버깅 정보 출력
|
||||
console.log('환경 변수:', {
|
||||
logger.info("환경 변수:", {
|
||||
NODE_ENV: import.meta.env.MODE,
|
||||
BASE_URL: import.meta.env.BASE_URL,
|
||||
APPWRITE_ENDPOINT: import.meta.env.VITE_APPWRITE_ENDPOINT,
|
||||
@@ -94,25 +98,25 @@ declare global {
|
||||
window.appwriteEnabled = false;
|
||||
|
||||
try {
|
||||
const rootElement = document.getElementById('root');
|
||||
const rootElement = document.getElementById("root");
|
||||
if (!rootElement) {
|
||||
throw new Error('Root element not found');
|
||||
throw new Error("Root element not found");
|
||||
}
|
||||
|
||||
|
||||
const root = createRoot(rootElement);
|
||||
|
||||
|
||||
root.render(
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
);
|
||||
|
||||
console.log('애플리케이션 렌더링 성공');
|
||||
|
||||
logger.info("애플리케이션 렌더링 성공");
|
||||
} catch (error) {
|
||||
console.error('애플리케이션 렌더링 오류:', error);
|
||||
|
||||
logger.error("애플리케이션 렌더링 오류:", error);
|
||||
|
||||
// 오류 발생 시 기본 오류 화면 표시
|
||||
const rootElement = document.getElementById('root');
|
||||
const rootElement = document.getElementById("root");
|
||||
if (rootElement) {
|
||||
rootElement.innerHTML = `
|
||||
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; font-family: Arial, sans-serif;">
|
||||
@@ -128,4 +132,4 @@ try {
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user