365 lines
9.1 KiB
Markdown
365 lines
9.1 KiB
Markdown
|
|
# SEO 및 봇 차단 설정 문서
|
||
|
|
|
||
|
|
## 개요
|
||
|
|
|
||
|
|
이 문서는 멀티 테넌트 ERP 시스템의 SEO 설정 및 봇 차단 전략을 설명합니다. 폐쇄형 시스템의 특성상 검색 엔진 수집을 방지하면서도, 과도한 차단으로 인한 브라우저 경고를 피하는 **균형 잡힌 접근 방식**을 채택했습니다.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📋 구현 내용
|
||
|
|
|
||
|
|
### 1. robots.txt 설정 ✅
|
||
|
|
|
||
|
|
**위치**: `/public/robots.txt`
|
||
|
|
|
||
|
|
**전략**: 느슨한 차단 (Moderate Blocking)
|
||
|
|
|
||
|
|
#### 주요 설정
|
||
|
|
|
||
|
|
```txt
|
||
|
|
# 허용된 경로 (Allow)
|
||
|
|
- / (홈페이지)
|
||
|
|
- /login (로그인 페이지)
|
||
|
|
- /about (회사 소개)
|
||
|
|
|
||
|
|
# 차단된 경로 (Disallow)
|
||
|
|
- /dashboard (대시보드)
|
||
|
|
- /admin (관리자 페이지)
|
||
|
|
- /api (API 엔드포인트)
|
||
|
|
- /tenant (테넌트 관리)
|
||
|
|
- /settings, /users, /reports, /analytics
|
||
|
|
- /inventory, /finance, /hr, /crm
|
||
|
|
- 기타 ERP 핵심 기능 경로
|
||
|
|
|
||
|
|
# 민감한 파일 형식 차단
|
||
|
|
- /*.json, /*.xml, /*.csv
|
||
|
|
- /*.xls, /*.xlsx
|
||
|
|
|
||
|
|
# Crawl-delay: 10초
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 크롬 경고 방지 전략
|
||
|
|
|
||
|
|
1. **홈페이지(/) 허용**: 완전 차단하지 않아 브라우저에서 악성 사이트로 분류되지 않음
|
||
|
|
2. **공개 페이지 제공**: /login, /about 등 일부 공개 경로 허용
|
||
|
|
3. **Crawl-delay 설정**: 서버 부하 감소 및 정상적인 봇 동작 유도
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. Middleware 봇 차단 로직 ✅
|
||
|
|
|
||
|
|
**위치**: `/src/middleware.ts`
|
||
|
|
|
||
|
|
**역할**: 런타임에서 봇 요청을 감지하고 차단
|
||
|
|
|
||
|
|
#### 핵심 기능
|
||
|
|
|
||
|
|
##### 2.1 봇 패턴 감지
|
||
|
|
|
||
|
|
User-Agent 기반으로 다음 패턴을 감지:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
- /bot/i, /crawler/i, /spider/i, /scraper/i
|
||
|
|
- /curl/i, /wget/i, /python-requests/i
|
||
|
|
- /axios/i (프로그래밍 방식 접근)
|
||
|
|
- /headless/i, /phantom/i, /selenium/i, /puppeteer/i, /playwright/i
|
||
|
|
- /go-http-client/i, /java/i, /okhttp/i
|
||
|
|
```
|
||
|
|
|
||
|
|
##### 2.2 경로 보호 전략
|
||
|
|
|
||
|
|
**보호된 경로 (Protected Paths)**:
|
||
|
|
- `/dashboard`, `/admin`, `/api`
|
||
|
|
- `/tenant`, `/settings`, `/users`
|
||
|
|
- `/reports`, `/analytics`
|
||
|
|
- `/inventory`, `/finance`, `/hr`, `/crm`
|
||
|
|
- `/employee`, `/customer`, `/supplier`
|
||
|
|
- `/orders`, `/invoices`, `/payroll`
|
||
|
|
|
||
|
|
**공개 경로 (Public Paths)**:
|
||
|
|
- `/`, `/login`, `/about`, `/contact`
|
||
|
|
- `/robots.txt`, `/sitemap.xml`, `/favicon.ico`
|
||
|
|
|
||
|
|
##### 2.3 차단 동작
|
||
|
|
|
||
|
|
봇이 보호된 경로에 접근 시:
|
||
|
|
```json
|
||
|
|
HTTP 403 Forbidden
|
||
|
|
{
|
||
|
|
"error": "Access Denied",
|
||
|
|
"message": "Automated access to this resource is not permitted.",
|
||
|
|
"code": "BOT_ACCESS_DENIED"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
##### 2.4 보안 헤더 추가
|
||
|
|
|
||
|
|
모든 응답에 다음 헤더 추가:
|
||
|
|
```http
|
||
|
|
X-Robots-Tag: noindex, nofollow, noarchive, nosnippet
|
||
|
|
X-Content-Type-Options: nosniff
|
||
|
|
X-Frame-Options: DENY
|
||
|
|
Referrer-Policy: strict-origin-when-cross-origin
|
||
|
|
```
|
||
|
|
|
||
|
|
##### 2.5 로깅
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// 차단된 봇 로그
|
||
|
|
[Bot Blocked] {user-agent} attempted to access {pathname}
|
||
|
|
|
||
|
|
// 허용된 봇 로그 (공개 경로)
|
||
|
|
[Bot Allowed] {user-agent} accessed {pathname}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. SEO 메타데이터 설정 ✅
|
||
|
|
|
||
|
|
**위치**: `/src/app/layout.tsx`
|
||
|
|
|
||
|
|
#### 메타데이터 구성
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
metadata: {
|
||
|
|
title: {
|
||
|
|
default: "ERP System - Enterprise Resource Planning",
|
||
|
|
template: "%s | ERP System"
|
||
|
|
},
|
||
|
|
description: "Multi-tenant Enterprise Resource Planning System for SME businesses",
|
||
|
|
robots: {
|
||
|
|
index: false, // 검색 엔진 색인 방지
|
||
|
|
follow: false, // 링크 추적 방지
|
||
|
|
nocache: true, // 캐싱 방지
|
||
|
|
googleBot: {
|
||
|
|
index: false,
|
||
|
|
follow: false,
|
||
|
|
'max-video-preview': -1,
|
||
|
|
'max-image-preview': 'none',
|
||
|
|
'max-snippet': -1,
|
||
|
|
}
|
||
|
|
},
|
||
|
|
openGraph: {
|
||
|
|
type: 'website',
|
||
|
|
locale: 'ko_KR',
|
||
|
|
siteName: 'ERP System',
|
||
|
|
title: 'Enterprise Resource Planning System',
|
||
|
|
description: 'Multi-tenant ERP System for SME businesses',
|
||
|
|
},
|
||
|
|
other: {
|
||
|
|
'cache-control': 'no-cache, no-store, must-revalidate'
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 주요 특징
|
||
|
|
|
||
|
|
1. **noindex, nofollow**: 검색 엔진 색인 및 링크 추적 차단
|
||
|
|
2. **nocache**: 민감한 페이지 캐싱 방지
|
||
|
|
3. **Google Bot 세부 제어**: 이미지, 비디오, 스니펫 미리보기 차단
|
||
|
|
4. **Cache-Control 헤더**: 브라우저 및 프록시 캐싱 방지
|
||
|
|
5. **다국어 지원**: locale 설정 (ko_KR)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 구현 전략 요약
|
||
|
|
|
||
|
|
| 구성 요소 | 목적 | 차단 강도 | 위치 |
|
||
|
|
|---------|------|---------|------|
|
||
|
|
| `robots.txt` | 검색 엔진 크롤러 가이드 | 느슨함 (Moderate) | `/public/robots.txt` |
|
||
|
|
| `middleware.ts` | 런타임 봇 감지 및 차단 | 강함 (Strong) | `/src/middleware.ts` |
|
||
|
|
| `layout.tsx` | HTML 메타 태그 설정 | 강함 (Strong) | `/src/app/layout.tsx` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔒 보안 수준
|
||
|
|
|
||
|
|
### 다층 방어 (Defense in Depth)
|
||
|
|
|
||
|
|
```
|
||
|
|
Layer 1: robots.txt
|
||
|
|
↓ 정상적인 검색 엔진 봇은 여기서 차단
|
||
|
|
|
||
|
|
Layer 2: Middleware Bot Detection
|
||
|
|
↓ 악의적인 봇 및 자동화 도구 차단
|
||
|
|
|
||
|
|
Layer 3: SEO Meta Tags
|
||
|
|
↓ HTML 레벨에서 색인 방지
|
||
|
|
|
||
|
|
Layer 4: Security Headers
|
||
|
|
↓ 추가 보안 헤더로 보호 강화
|
||
|
|
```
|
||
|
|
|
||
|
|
### 차단 vs 허용 균형
|
||
|
|
|
||
|
|
| 요소 | 설정 | 이유 |
|
||
|
|
|-----|------|------|
|
||
|
|
| 홈페이지 (/) | ✅ 허용 | 크롬 경고 방지 |
|
||
|
|
| 로그인 (/login) | ✅ 허용 | 정상 접근 가능 |
|
||
|
|
| 대시보드 (/dashboard) | ❌ 차단 | ERP 핵심 기능 보호 |
|
||
|
|
| API (/api) | ❌ 차단 | 데이터 보호 |
|
||
|
|
| 정적 파일 (.svg, .png 등) | ✅ 허용 | 정상 웹사이트 기능 |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 동작 흐름
|
||
|
|
|
||
|
|
### 정상 사용자 (브라우저)
|
||
|
|
|
||
|
|
```
|
||
|
|
1. 사용자가 /dashboard 접근
|
||
|
|
2. middleware.ts: User-Agent 확인 → 정상 브라우저
|
||
|
|
3. X-Robots-Tag 헤더 추가
|
||
|
|
4. 정상 페이지 렌더링
|
||
|
|
5. HTML에 noindex 메타 태그 포함
|
||
|
|
```
|
||
|
|
|
||
|
|
### 검색 엔진 봇
|
||
|
|
|
||
|
|
```
|
||
|
|
1. Googlebot이 사이트 접근
|
||
|
|
2. robots.txt 확인 → /dashboard Disallow
|
||
|
|
3. Googlebot은 /dashboard 접근하지 않음
|
||
|
|
4. / (홈페이지)만 크롤링 → noindex 메타 태그 확인
|
||
|
|
5. 검색 결과에 포함하지 않음
|
||
|
|
```
|
||
|
|
|
||
|
|
### 악의적인 봇/스크래퍼
|
||
|
|
|
||
|
|
```
|
||
|
|
1. curl/python-requests로 /api/users 접근 시도
|
||
|
|
2. middleware.ts: User-Agent에서 'curl' 감지
|
||
|
|
3. isProtectedPath('/api/users') → true
|
||
|
|
4. HTTP 403 Forbidden 반환
|
||
|
|
5. 로그 기록: [Bot Blocked] curl/7.68.0 attempted to access /api/users
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🧪 테스트 방법
|
||
|
|
|
||
|
|
### 1. robots.txt 확인
|
||
|
|
|
||
|
|
브라우저에서 접속:
|
||
|
|
```
|
||
|
|
http://localhost:3000/robots.txt
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Middleware 테스트
|
||
|
|
|
||
|
|
**정상 브라우저 접근**:
|
||
|
|
```bash
|
||
|
|
curl -H "User-Agent: Mozilla/5.0" http://localhost:3000/dashboard
|
||
|
|
# 예상: 정상 페이지 반환 (인증 로직 없으면 접근 가능)
|
||
|
|
```
|
||
|
|
|
||
|
|
**봇으로 접근**:
|
||
|
|
```bash
|
||
|
|
curl http://localhost:3000/dashboard
|
||
|
|
# 예상: HTTP 403 Forbidden
|
||
|
|
# {"error":"Access Denied","message":"Automated access to this resource is not permitted.","code":"BOT_ACCESS_DENIED"}
|
||
|
|
```
|
||
|
|
|
||
|
|
**공개 페이지 접근**:
|
||
|
|
```bash
|
||
|
|
curl http://localhost:3000/
|
||
|
|
# 예상: 정상 페이지 반환 (X-Robots-Tag 헤더 포함)
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 헤더 확인
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl -I http://localhost:3000/
|
||
|
|
# 확인 항목:
|
||
|
|
# X-Robots-Tag: noindex, nofollow
|
||
|
|
# X-Content-Type-Options: nosniff
|
||
|
|
# X-Frame-Options: DENY
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. SEO 메타 태그 확인
|
||
|
|
|
||
|
|
브라우저에서 페이지 소스 보기:
|
||
|
|
```html
|
||
|
|
<meta name="robots" content="noindex, nofollow">
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ⚠️ 주의사항
|
||
|
|
|
||
|
|
### 크롬 경고 방지
|
||
|
|
|
||
|
|
1. **완전 차단 금지**: robots.txt에서 모든 경로를 차단하면 안 됨
|
||
|
|
```txt
|
||
|
|
# ❌ 절대 사용 금지
|
||
|
|
User-agent: *
|
||
|
|
Disallow: /
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **공개 페이지 유지**: 최소한 홈페이지는 허용
|
||
|
|
3. **HTTP 상태 코드**: 403 사용 (404나 500은 피함)
|
||
|
|
4. **정상 사용자 차단 방지**: User-Agent 패턴 신중히 선택
|
||
|
|
|
||
|
|
### 로그 모니터링
|
||
|
|
|
||
|
|
- 차단된 봇 접근 시도를 모니터링하여 새로운 패턴 감지
|
||
|
|
- 정상 사용자가 차단되는 경우 BOT_PATTERNS 조정
|
||
|
|
- 로그 파일 위치: 콘솔 출력 (프로덕션에서는 로깅 서비스 연동 필요)
|
||
|
|
|
||
|
|
### 성능 고려사항
|
||
|
|
|
||
|
|
- Middleware는 모든 요청에 실행되므로 성능 영향 최소화
|
||
|
|
- 정규표현식 패턴 최적화 필요
|
||
|
|
- 필요시 Redis 등으로 IP 기반 rate limiting 추가 고려
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔄 향후 개선 사항
|
||
|
|
|
||
|
|
### 1. IP 기반 Rate Limiting
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// 추가 예정: Redis를 활용한 rate limiting
|
||
|
|
import { Ratelimit } from "@upstash/ratelimit";
|
||
|
|
import { Redis } from "@upstash/redis";
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 화이트리스트 관리
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// 신뢰할 수 있는 IP나 User-Agent 화이트리스트
|
||
|
|
const WHITELISTED_IPS = ['123.45.67.89'];
|
||
|
|
const WHITELISTED_USER_AGENTS = ['MyCompanyMonitoringBot'];
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. 고급 봇 감지
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// 행동 패턴 분석 (빠른 요청 속도, 비정상 경로 접근 등)
|
||
|
|
// Fingerprinting 기술 적용
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. 로깅 서비스 연동
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Sentry, LogRocket 등 APM 도구 연동
|
||
|
|
// 봇 공격 패턴 분석 및 알림
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📝 변경 이력
|
||
|
|
|
||
|
|
| 날짜 | 버전 | 변경 내용 |
|
||
|
|
|-----|------|---------|
|
||
|
|
| 2025-11-06 | 1.0.0 | 초기 SEO 및 봇 차단 설정 구현 |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 참고 자료
|
||
|
|
|
||
|
|
- [Next.js Middleware Documentation](https://nextjs.org/docs/app/building-your-application/routing/middleware)
|
||
|
|
- [robots.txt Specification](https://developers.google.com/search/docs/crawling-indexing/robots/intro)
|
||
|
|
- [X-Robots-Tag HTTP Header](https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag)
|
||
|
|
- [OWASP Bot Management](https://owasp.org/www-community/controls/Blocking_Brute_Force_Attacks)
|