크롤링의 법·윤리·안티봇 — 지속 가능한 수집기를 위해
크롤링 프로젝트가 어느 정도 규모로 커지면, 반드시 세 가지 벽을 만난다.
1. 대상 사이트가 우리를 차단한다
2. 법무팀에서 "이거 문제 없어요?" 물어본다
3. 대상 사이트가 부하로 죽는다 (그리고 우리 쪽 IP가 밴)
앞선 글에서는 "어떻게 긁을 것인가"를 봤다. 이 글은 "어떻게 지속 가능하게 긁을 것인가"를 정리한다. 도구 얘기가 아니라 원칙과 실무 관행이다.
시나리오는 그대로다.
예시 시나리오 예시 수집기가 이제 실제 운영 단계에 들어간다. 하루 수십만 페이지를 긁고, 여러 사이트의 데이터를 다룬다. 이 시점에 반드시 짚어야 할 것들이 있다.
robots.txt는 뭘까
가장 기본적인 규약이다.
https://example.com/robots.txt 경로에 웹사이트가 크롤러에게 주는 안내문이 있다.
User-agent: *
Disallow: /admin/
Disallow: /api/internal/
Allow: /
User-agent: Googlebot
Crawl-delay: 5
Sitemap: https://example.com/sitemap.xml
User-agent: 이 규칙이 적용될 봇Disallow: 접근 금지 경로Allow: 명시적 허용Crawl-delay: 요청 사이 최소 간격 (초)Sitemap: 사이트가 자발적으로 공개한 URL 목록
법적 강제력은 없다. 하지만…
robots.txt는 권고다. 지키지 않아도 그 자체로 법 위반은 아니다.
하지만 실무에서는 이렇게 본다:
- 무시하면 명시적으로 거부된 자원에 접근한 셈이 된다. 나중에 분쟁이 생기면 "고의성"의 근거가 된다.
- 법적으로도 지키는 편이 훨씬 안전하다. 접근 통제를 우회했는지가 정보통신망법·저작권법 판단에서 중요한 요소가 된다.
- 사이트 운영자와의 관계 문제도 있다. 무시하고 긁다가 IP 차단되면 그때부터 진짜 힘들어진다.
원칙: robots.txt는 지킨다. 지키지 못할 이유가 있으면 법무 검토 먼저.
robots.txt 파싱
Java에서는 별도 라이브러리가 있다. 직접 파싱해도 되지만 엣지 케이스가 많다. Google이 오픈소스로 낸 파서(crawler-commons, robots-txt-parser) 를 쓰는 편이 안전하다.
sitemap.xml도 같이 가져오는 게 좋다. 사이트가 스스로 공개한 URL 목록이라 가장 예의 바른 크롤링 진입점이다.
법·윤리 관점 (한국 기준)
법 전문가는 아니지만, 백엔드 개발자가 최소한 알아야 할 원칙을 정리한다. 구체적인 프로젝트는 반드시 법무 검토를 거쳐야 한다.
관련 법률
- 저작권법: 크롤링한 데이터가 저작물이면 무단 사용 시 침해. 단순 정보(사실·수치)는 저작권 대상이 아니지만, DB로서 편집저작권이 인정될 수 있다.
- 정보통신망법: 침입, 접근 통제 우회, 서비스 방해는 형사처벌 대상. 로그인·인증을 우회하거나, 캡차를 뚫거나, 대량 요청으로 서비스에 지장을 주면 문제.
- 개인정보보호법: 크롤링 데이터에 개인정보가 포함되면 별도 규제. 특히 이름/전화번호/이메일이 섞이면 조심.
- 부정경쟁방지법: 상당한 노력·투자로 만든 성과물(데이터베이스)을 무단으로 대량 수집·사용하면 부정경쟁행위로 인정될 수 있다. 최근 몇 년간 크롤링 관련 주요 판례들이 이 조항을 근거로 한다.
실무 판단 체크리스트
- 대상 사이트의 이용약관에 크롤링 금지 조항이 있는가?
- 대상 데이터가 공개된 사실 정보인가, 아니면 저작물/편집물인가?
- 로그인이 필요한 영역인가? 로그인 후 접근하는 크롤링은 훨씬 위험도가 높다.
- 수집한 데이터를 재배포·상업적 사용할 것인가? 내부 분석용과 서비스 노출은 완전히 다른 이슈.
- 원본 사이트의 트래픽·성능에 실질적 영향을 주는가?
이 다섯 개 중 하나라도 "예"가 있으면 법무 검토를 받아야 한다. 예시 수집기 같은 사내 데이터 파이프라인도 예외 아님.
실용적 원칙
- 공식 API가 있으면 무조건 API를 쓴다. 크롤링은 API가 없거나 부족할 때만.
- 처음 시도할 때 사이트 운영자에게 문의하는 것도 방법. 의외로 협조적일 때가 많다.
- 가져올 필요 없는 데이터는 가져오지 않는다. 특히 개인정보성 필드는 최소화.
- 재배포 여부는 명확히 결정한 뒤 시작.
안티봇, 뭐가 있고 어떻게 대응하나
사이트가 크롤러를 감지하고 막는 방식은 크게 5가지다. 하나씩 보자.
1. User-Agent 필터링
가장 기본. 이상하거나 비어있는 User-Agent를 차단.
User-Agent: python-requests/2.28
→ 차단
대응: 정상적인 브라우저의 User-Agent를 사용. 단, 가짜 User-Agent로 위장하는 것 자체가 접근 통제 우회로 해석될 여지가 있으므로, 크롤러임을 밝히는 것이 가장 안전하다.
User-Agent: MyDataCollectorBot/1.0 (+https://example.com/bot-info)
봇 정보 URL도 함께 남기면 사이트 운영자가 문의할 수 있다. 실제 대형 검색엔진들의 방식.
2. Rate Limiting
일정 시간 안에 같은 IP에서 너무 많은 요청이 오면 429/503 응답.
대응: 요청 간격을 두는 게 정공법.
- 사이트 규모별로 다르지만, 초당 1~2건, 페이지당 최소 500ms 대기 정도가 보수적 기준.
- 지수 백오프: 429 응답 받으면 다음 요청까지 대기 시간을 2배씩 늘림.
- 서버가
Retry-After헤더를 주면 반드시 지킨다.
Batch로 돌리는 경우 Chunk 안에서 Thread.sleep()보다는 Reader에서 페이싱하거나 별도 RateLimiter를 두는 게 안전.
3. IP 기반 차단
같은 IP에서 대량 요청이 오면 아예 차단. Cloudflare 같은 CDN 레벨에서 자동 감지·차단.
대응 선택지:
- 회사 정책상 가능한 범위 내에서 대응한다. 크롤링 방지 목적을 우회하는 조치는 법적 위험이 있다.
- 정공법은 요청량을 줄이는 것.
- 필요하다면 사이트 운영자와 협의해 화이트리스트에 등록받는 것이 최선.
프록시 로테이션은 기술적으로는 가능하지만, 명시적 차단을 회피하는 행위로 해석될 수 있어 신중해야 한다.
4. JavaScript 챌린지 (Cloudflare 등)
페이지 로드 시 JS 챌린지를 실행하고, 통과한 브라우저만 진짜 페이지를 준다.
대응: HTTP 파서로는 통과 불가. 브라우저 자동화(Playwright)로 넘어가는 시점.
다만 캡차나 챌린지 자동 해결기를 붙이는 것은 접근 통제 우회 이슈가 다시 등장. 여기서부터는 법적·윤리적 회색지대다.
5. 브라우저 지문(Fingerprint)
브라우저 자동화를 감지하려는 시도.
navigator.webdriver === true체크- Canvas fingerprint, WebGL fingerprint
- 마우스 움직임, 스크롤 패턴 분석
Playwright는 기본적으로 상당수 자동화 흔적을 지워주고, playwright-stealth 같은 부가 도구도 있다.
중요: 여기까지 오면 "대상 사이트가 명확히 크롤러 접근을 거부하고 있다"는 신호다. 기술적으로 뚫는 것보다 정말 그 데이터가 필요한지, 다른 경로는 없는지를 먼저 고민해야 한다.
예시 수집기의 방어적 설계
지금까지의 원칙을 예시 수집기 코드로 옮기면 이런 것들이 나온다.
1. 도메인별 설정
public record CrawlPolicy(
String domain,
long minIntervalMs, // 요청 간 최소 간격
int maxConcurrent, // 동시 요청 수
boolean respectRobots, // robots.txt 준수 (기본 true)
String userAgent
) {}도메인마다 정책을 따로 갖는다. 예시 수집기가 100개 사이트를 다룬다면 100개의 정책. 값은 사이트별 실측·robots.txt를 기반으로.
2. RateLimiter 계층
@Component
public class DomainRateLimiter {
private final Map<String, Semaphore> limiters = new ConcurrentHashMap<>();
// 도메인별로 Semaphore or Token Bucket 관리
}Batch의 Chunk와 별개로, 도메인 단위로 부하를 통제하는 것이 핵심.
3. 응답 코드 기반 자동 백오프
if (response.statusCode() == 429) {
long retryAfter = parseRetryAfter(response.headers());
Thread.sleep(retryAfter);
// Batch retry에게 다시 던져 재시도
throw new RateLimitedException();
}.retry(RateLimitedException.class).backOffPolicy(exponential()) 로 Batch가 자동으로 재시도.
4. 관측 지표
- 도메인별 성공/실패율
- 도메인별 평균 응답 시간
- 429/503 발생률
- 봇 차단(403, 챌린지 페이지) 감지 카운트
403이 갑자기 늘어나면 알림. 사이트가 우리를 차단하기 시작한 신호다. 요청량을 줄이거나 잠시 중단해야 한다.
5. 부하 실험은 스테이징에서
새 사이트 크롤링을 시작하기 전에 스테이징 환경에서:
- 요청 1회 → 응답 헤더·바디 확인
- 요청 10회 → 5초 간격
- 요청 100회 → 10분에 걸쳐
이렇게 점진적으로 늘려가며 어느 지점에서 사이트가 반응이 나빠지는지 관찰. 프로덕션에서 처음 100만 건 돌리는 짓은 금물.
크롤링 프로젝트 시작 전 체크리스트
이 목록만 지켜도 사고의 90%는 예방된다.
- ☐ 대상 사이트의 robots.txt 확인 (필요 시 준수)
- ☐ 대상 사이트의 이용약관 크롤링 조항 확인
- ☐ 대상 데이터에 개인정보 포함 여부 확인
- ☐ 공식 API 존재 여부 확인 (있으면 크롤링 대신 API)
- ☐ 데이터의 재배포·상업적 이용 여부 결정
- ☐ 필요 시 법무 검토 요청
- ☐ 사이트 규모에 맞는 요청 간격·동시성 정책 수립
- ☐ User-Agent에 봇 정보와 연락처 명시
- ☐ 관측(로그·메트릭) 설정 (403/429 알림)
- ☐ 스테이징에서 부하 테스트 후 프로덕션 투입
정리
- robots.txt는 지킨다. 법적 강제는 없어도 실무 표준.
- 크롤링은 저작권·정보통신망법·부정경쟁방지법 이슈가 얽혀 있다. 공식 API 우선, 크롤링은 최후 수단.
- 안티봇 대응은 기술적 회피가 아니라 예의 바른 크롤링이 정답. User-Agent 명시, Rate Limiting, 백오프.
- 챌린지·캡차 우회, 프록시 로테이션은 접근 통제 우회로 해석될 위험 있음. 신중히.
- 수집기는 도메인별 정책·RateLimiter·응답 코드 기반 백오프·관측 지표를 갖춰야 지속 가능.
- 새 사이트는 반드시 스테이징에서 점진적 부하 실험 후 투입.
크롤링은 기술이 아니라 관계다. 대상 사이트와 오래 좋은 관계를 유지할 때만 데이터 파이프라인도 오래간다.