서버 환경
| 구분 | 값 |
| 도메인 | sb.kiam.kr (DNS 연결 완료) |
| 경로 | /var/www/webapp/sb |
| 웹서버 | Apache 2.4 (mod_rewrite, mod_headers, mod_ssl) |
| 언어 | PHP 8.x |
| DB | MariaDB - DB명: sbdb |
| SSL 인증서 | /var/www/kiam_ssl/ssl.crt 외 (와일드카드) |
| VHost 파일 | /etc/apache2/sites-available/sb.kiam.kr.conf |
| 금지 | ❌ Nginx 설치/사용 절대 금지 |
디렉토리 구조
/var/www/webapp/sb/
├── index.html # 진입점 (PWA 셸)
├── manifest.json # PWA 매니페스트
├── service-worker.js # 오프라인 캐시 + 푸시
├── login.html register.html splash.html onboarding.html
├── doc/ # 📑 설계도 30페이지 (현재 보고 있는 곳)
├── css/
│ └── app.css
├── js/
│ ├── app.js
│ ├── auth.js
│ ├── ai-chat.js
│ ├── video-call.js
│ └── sos.js
├── assets/
│ ├── icon-192.png icon-512.png
│ └── images/
├── mind/ # 마음 (감정/AI말벗/화상)
├── health/ # 건강
├── family/ # 가족
├── safety/ # 안전센터/SOS
├── village/ help/ job/ learn/ life2/ ai/
├── admin/ # 관리자 페이지
├── api/ # REST API
│ ├── index.php # 라우터
│ └── v1/
│ ├── auth/ ai/ health/ sos/ family/ payment/ ...
├── includes/ # 공통 PHP (db, auth, mail, ai)
│ ├── db.php config.php auth.php deepseek.php toss.php
└── .htaccess # 라우팅 + 보안 헤더
Apache 설정 (sb.kiam.kr.conf 핵심)
<VirtualHost *:443>
ServerName sb.kiam.kr
DocumentRoot /var/www/webapp/sb
SSLEngine on
SSLCertificateFile /var/www/kiam_ssl/ssl.crt
SSLCertificateKeyFile /var/www/kiam_ssl/privkey_nopass.pem
SSLCertificateChainFile /var/www/kiam_ssl/chain_ssl.crt
<Directory /var/www/webapp/sb>
AllowOverride All
Require all granted
DirectoryIndex index.html index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/api/
RewriteRule ^api/(.*)$ /api/index.php [QSA,L]
Header set Permissions-Policy "microphone=(self), camera=(self), geolocation=(self)"
<FilesMatch "service-worker\.js$">
Header set Service-Worker-Allowed "/"
Header set Cache-Control "no-cache"
</FilesMatch>
</Directory>
</VirtualHost>
보안 체크리스트
| 항목 | 적용 방법 |
| HTTPS 강제 | HTTP → HTTPS 301 리다이렉트 + HSTS |
| SQL Injection | PDO prepared statement 100% 사용 |
| XSS | htmlspecialchars + CSP 헤더 |
| CSRF | JWT + SameSite Cookie + CSRF 토큰 |
| 비밀번호 | bcrypt cost 12 |
| Rate Limit | IP별 60req/분 + 인증 5req/분 |
| 파일 업로드 | 화이트리스트 확장자 + MIME 검증 + 격리 저장소 |
| API 키 | .env 파일, gitignore, 환경변수만 |
| 로깅 | SOS / 결제 / 관리자 액션 영구 기록 |
| 개인정보 | 전화번호·주소 등 AES-256 암호화 저장 |
모니터링 / 알림
- UptimeRobot — 5분마다 sb.kiam.kr 헬스체크
- Apache Access/Error Log — /var/log/apache2/sb_*.log
- Slack/Telegram — SOS 발생 즉시 운영자 알림
- 일일 백업 — sbdb 매일 03:00 mysqldump → AI Drive 보관
- 주간 보고 — KPI 자동 메일 (월요일 09:00)
배포 명령어
# 1) 코드 배포
cd /var/www/webapp/sb && git pull origin main
# 2) DB 마이그레이션
mysql -u root sbdb < migrations/latest.sql
# 3) Apache 재시작 없이 적용 (graceful)
apache2ctl configtest && systemctl reload apache2
# 4) 서비스워커 캐시 무효화 (버전 업)
sed -i "s/const CACHE = 'silbeot-v[0-9]*'/const CACHE = 'silbeot-v$(date +%s)'/" service-worker.js