- MailService.cs 추가: ServiceBase 상속받는 Windows 서비스 클래스 - Program.cs 수정: 서비스/콘솔 모드 지원, 설치/제거 기능 추가 - 프로젝트 설정: System.ServiceProcess 참조 추가 - 배치 파일 추가: 서비스 설치/제거/콘솔실행 스크립트 주요 기능: - Windows 서비스로 백그라운드 실행 - 명령행 인수로 모드 선택 (-install, -uninstall, -console) - EventLog를 통한 서비스 로깅 - 안전한 서비스 시작/중지 처리 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
197 lines
8.0 KiB
HTML
197 lines
8.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>React Test Page - GroupWare</title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
|
margin: 0;
|
|
padding: 20px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
.container {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
background-color: white;
|
|
padding: 30px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
}
|
|
.header {
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
}
|
|
.status {
|
|
padding: 20px;
|
|
margin: 20px 0;
|
|
border-radius: 5px;
|
|
}
|
|
.success {
|
|
background-color: #d4edda;
|
|
border: 1px solid #c3e6cb;
|
|
color: #155724;
|
|
}
|
|
.loading {
|
|
background-color: #fff3cd;
|
|
border: 1px solid #ffeaa7;
|
|
color: #856404;
|
|
}
|
|
.error {
|
|
background-color: #f8d7da;
|
|
border: 1px solid #f5c6cb;
|
|
color: #721c24;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>🚀 React Integration Test</h1>
|
|
<p>GroupWare + OWIN + React 통합 테스트</p>
|
|
</div>
|
|
|
|
<div id="react-app">
|
|
<div class="status loading">
|
|
React 컴포넌트를 로딩 중입니다...
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- React & ReactDOM CDN -->
|
|
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
|
|
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
|
|
<!-- Babel standalone for JSX -->
|
|
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
|
|
<!-- React Component -->
|
|
<script type="text/babel">
|
|
const { useState, useEffect } = React;
|
|
|
|
// 메인 React 컴포넌트
|
|
function ReactTestApp() {
|
|
const [status, setStatus] = useState('loading');
|
|
const [counter, setCounter] = useState(0);
|
|
const [serverTime, setServerTime] = useState('');
|
|
const [apiTest, setApiTest] = useState({ status: 'pending', message: '' });
|
|
|
|
// 컴포넌트가 마운트될 때 실행
|
|
useEffect(() => {
|
|
// React가 정상적으로 로드되었음을 표시
|
|
setTimeout(() => {
|
|
setStatus('success');
|
|
setServerTime(new Date().toLocaleString('ko-KR'));
|
|
}, 1000);
|
|
|
|
// API 테스트 (GroupWare의 기존 컨트롤러 테스트)
|
|
testAPI();
|
|
}, []);
|
|
|
|
// GroupWare API 테스트 함수
|
|
const testAPI = async () => {
|
|
try {
|
|
// Home 컨트롤러 테스트 (기존에 있을 것으로 예상)
|
|
const response = await fetch('/Home');
|
|
if (response.ok) {
|
|
setApiTest({ status: 'success', message: 'API 연결 성공' });
|
|
} else {
|
|
setApiTest({ status: 'warning', message: `API 응답: ${response.status}` });
|
|
}
|
|
} catch (error) {
|
|
setApiTest({ status: 'error', message: `API 오류: ${error.message}` });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<div className={`status ${status === 'success' ? 'success' : 'loading'}`}>
|
|
{status === 'success' ? (
|
|
<div>
|
|
<h3>✅ React 컴포넌트가 성공적으로 로드되었습니다!</h3>
|
|
<p><strong>현재 시간:</strong> {serverTime}</p>
|
|
</div>
|
|
) : (
|
|
<h3>React 컴포넌트를 로딩 중입니다...</h3>
|
|
)}
|
|
</div>
|
|
|
|
{status === 'success' && (
|
|
<div>
|
|
<div className="status">
|
|
<h3>📊 상태 관리 테스트</h3>
|
|
<p><strong>카운터:</strong> {counter}</p>
|
|
<button
|
|
onClick={() => setCounter(counter + 1)}
|
|
style={{
|
|
padding: '10px 20px',
|
|
marginRight: '10px',
|
|
backgroundColor: '#007bff',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '5px',
|
|
cursor: 'pointer'
|
|
}}
|
|
>
|
|
증가 (+1)
|
|
</button>
|
|
<button
|
|
onClick={() => setCounter(0)}
|
|
style={{
|
|
padding: '10px 20px',
|
|
backgroundColor: '#6c757d',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '5px',
|
|
cursor: 'pointer'
|
|
}}
|
|
>
|
|
리셋
|
|
</button>
|
|
</div>
|
|
|
|
<div className={`status ${
|
|
apiTest.status === 'success' ? 'success' :
|
|
apiTest.status === 'error' ? 'error' : 'loading'
|
|
}`}>
|
|
<h3>🌐 API 연결 테스트</h3>
|
|
<p><strong>상태:</strong> {apiTest.message}</p>
|
|
<button
|
|
onClick={testAPI}
|
|
style={{
|
|
padding: '10px 20px',
|
|
backgroundColor: '#28a745',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '5px',
|
|
cursor: 'pointer'
|
|
}}
|
|
>
|
|
API 다시 테스트
|
|
</button>
|
|
</div>
|
|
|
|
<div className="status">
|
|
<h3>📋 통합 테스트 체크리스트</h3>
|
|
<ul style={{ textAlign: 'left' }}>
|
|
<li>✅ OWIN 정적 파일 서빙</li>
|
|
<li>✅ React 라이브러리 로딩 (CDN)</li>
|
|
<li>✅ JSX 컴파일 (Babel)</li>
|
|
<li>✅ React Hooks (useState, useEffect)</li>
|
|
<li>✅ 이벤트 핸들링</li>
|
|
<li>✅ API 호출 (fetch)</li>
|
|
<li>✅ 반응형 UI 업데이트</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// React 컴포넌트를 DOM에 렌더링
|
|
const root = ReactDOM.createRoot(document.getElementById('react-app'));
|
|
root.render(<ReactTestApp />);
|
|
</script>
|
|
</body>
|
|
</html> |