실제로 llms.txt에 접근하는 사람 확인하기
/llms.txt와 /llms-full.txt는 한동안 richardlemon.com에 공개되어 왔습니다. 당연히 다음 질문은, 과연 누가 이를 요청하고 있는가?입니다.
이를 파악하는 한 가지 방법은 웹 서버 로그를 직접 확인하는 것입니다. 대시보드나 느낌(vibes) 같은 것은 없습니다. 그저 드롭렛(droplet)에 있는 Nginx 접근 로그만 있으면 됩니다.
증거가 존재하는 곳: Nginx 접근 로그
작은 VPS에서 일반적인 Nginx 설정의 경우, 접근 로그는 보통 다음과 같은 위치에 존재합니다:
/var/log/nginx/access.log
/var/log/nginx/access.log.1
/var/log/nginx/access.log.2.gz
...
정확한 경로는 배포판(distro)과 Nginx 설치 방식에 따라 다르지만, 패턴은 비슷합니다: 현재의 access.log와 회전되어 때때로 gzip 압축된 오래된 로그들입니다.
llms.txt와 관련된 모든 것에 대해, 관련 필드는 요청 경로(request path)와 사용자 에이전트(user agent)입니다. 이것은 어떤 클라이언트가 어떤 파일을 요청했는지, 그리고 어떻게 자신을 소개하기로 했는지를 알려줍니다.
llms.txt와 llms-full.txt 필터링
첫 번째 단계는 이 두 파일에 접근한 라인만 추출하는 것입니다. 간단한 grep으로 로그 전체에서 처리할 수 있습니다. 예를 들어, 로그가 있는 디렉토리에서 다음 명령을 사용할 수 있습니다:
cd /var/log/nginx
grep -hE "llms\.txt|llms-full\.txt" access.log* > llms-requests.log
여기에 몇 가지 세부 사항이 있습니다:
-h는 출력에서 파일 이름을 숨겨 다음 단계를 더 깔끔하게 만듭니다.
-E는 확장 정규 표현식(extended regular expression)을 사용하도록 허용하여 두 파일명을 한 번에 일치시킬 수 있게 합니다.
access.log*는 현재 로그와 gzip 압축되지 않은 모든 회전 로그를 처리합니다. 만약 .gz 파일이 있다면, 유사하게 zgrep을 실행할 수 있습니다.
이렇게 하면 LLM 관련 파일에 대한 요청만 포함하는 더 작은 파일인 llms-requests.log가 생깁니다.
사용자 에이전트별 그룹화
다음 단계는 이 요청들이 누구에게 속하는지 확인하는 것입니다. 이를 위해서는 각 로그 라인에서 사용자 에이전트 필드가 필요합니다.
이것은 Nginx 로그 형식에 따라 다르지만, 비교적 표준적인 combined log format을 사용한다면 user agent는 라인의 마지막 따옴표로 묶인 문자열입니다. awk와 sort를 사용하여 이를 추출하고 그룹화할 수 있습니다:
awk -F '"' '{print $6}' llms-requests.log \
| sort \
| uniq -c \
...
이것의 작동 방식:
-F '"'는 awk에게 구분 기호로 큰따옴표를 사용하라고 지시합니다. combined log에서는 user agent가 필드 6으로 끝납니다.
sort | uniq -c는 동일한 user agent들을 그룹화하고 개수를 셉니다.
- 최종
sort -nr은 빈도수(frequency)를 기준으로 내림차순 정렬하여 가장 높은 순서로 보여줍니다.
이 시점에서 여러분은 llms.txt 또는 llms-full.txt를 요청한 모든 user agent 목록과 그 요청 횟수를 얻게 됩니다.
GPTBot, ClaudeBot, Perplexity, Googlebot, 기타로 분류하기
원시(Raw) user agent 문자열은 지저분합니다. 가독성 있는 결과를 원한다면, 이를 알려진 크롤러 몇 가지와 '기타' 버킷으로 나누는 것이 도움이 됩니다.
LLM 관련 트래픽의 경우, 일반적으로 의심되는 주체들은 다음과 같습니다:
- GPTBot (OpenAI)
- ClaudeBot (Anthropic)
- PerplexityBot
- Googlebot (비교 목적으로 유용합니다. 비록 LLM 크롤러는 아니지만)
- 기타 (브라우저, 임의 스크래퍼, SEO 도구, 잘못 구성된 스크립트)
user agent 문자열에서 부분 문자열을 찾아 레이블을 할당하는 또 다른 awk 작업을 통해 대략적인 분류를 수행할 수 있습니다.
awk -F '"' '{
ua = $6
bucket = "Other"
...
이것은 몇 가지 일을 합니다:
- 각 로그 라인을 살펴보고 user agent를 추출하며, 기본 버킷을
Other로 설정합니다.
- 대소문자를 구분하지 않는 정규 표현식(regex)을 사용하여 알려진 봇 식별자를 확인합니다.
- 각 요청에 대해 해당 버킷 이름을 출력한 다음, 그룹화하고 개수를 셉니다.
결과는 각 크롤러 계열에서 온 요청 수가 담긴 작은 표가 됩니다. 이 스크립트를 주기적으로 실행하여 시간이 지남에 따라 구성 비율이 변하는지 확인할 수 있습니다.
기대할 수 있는 결과물
이미 llms.txt와 llms-full.txt가 몇 달 동안 공개되어 왔다는 점을 고려할 때, 만약 해당 도메인을 크롤링하는 알려진 LLM 크롤러들이 있다면 가끔씩 이 파일들을 확인해 볼 것이라고 예상하는 것이 합리적입니다.
이것은 다음과 같은 형태로 나타날 수 있습니다:
llms.txt 스타일의 파일을 존중하고 찾으려는 GPTBot, ClaudeBot 또는 PerplexityBot의 간헐적인 접근.
- 텍스트 파일처럼 보이는 모든 것을 가져가려고 시도하는 Googlebot 및 기타 검색 크롤러들의 주기적인 백그라운드 노이즈.
- 사람들이 테스트하거나 디버깅할 때 브라우저나 커맨드라인 도구에서 발생하는 수동 요청.
만약 로그에 특정 크롤러 계열로부터 장기간 동안 아무런 요청도 기록되어 있지 않다면, 이는 해당 크롤러가 아예 도메인을 방문하지 않거나 이 특정 파일들에 관심이 없다는 것을 시사합니다. 이름이 주요 제공업체처럼 들리는 봇으로부터 요청을 보더라도 어느 정도의 회의적인 태도가 필요합니다.
요청이 학습 데이터셋에 포함되었다는 것과 같지 않은 이유
GPTBot이라고 불리는 것의 로그 항목을 보고 즉시 자신의 콘텐츠가 어떤 학습 코퍼스(training corpus)에 들어갔다고 결론 내리기가 쉽습니다. 하지만 그 추론은 데이터로 뒷받침되지 않습니다.
로그는 단지 한 가지 사실만을 증명합니다: 특정 시점에, 특정 IP에서, 특정 사용자 에이전트(user agent)를 주장하는 클라이언트가 특정 URL을 가져갔고 특정 HTTP 상태 코드(HTTP status code)를 받았다는 것입니다. 그 외의 모든 것은 추론에 불과합니다.
몇 가지 구체적인 제한 사항:
- 신원 확인은 자체 보고에 의존합니다. 사용자 에이전트(User agents)는 위조될 수 있습니다. 역방향 DNS(reverse DNS) 및 IP 범위 검사 없이는 요청이 실제로 OpenAI, Anthropic 또는 다른 누군가로부터 왔는지 알 수 없습니다.
- 데이터 가져오기가 저장하는 것은 아닙니다. 크롤러(crawler)는
llms.txt를 요청하고 정책을 읽은 다음, 크롤링을 하지 않거나 콘텐츠를 보존하지 않기로 결정할 수 있습니다. 이 파일은 순전히 라우팅 또는 필터링 힌트(hint)로 사용될 수 있습니다.
- 저장하는 것이 학습하는 것은 아닙니다. 콘텐츠가 캐시(cache)되더라도, 그것이 학습 데이터셋에 포함된다는 것을 증명하지 못합니다. 제공업체들은 종종 크롤링, 인덱싱(indexing), 그리고 학습 파이프라인을 분리합니다.
- 학습하는 것이 인용하는 것은 아닙니다. 콘텐츠가 학습 세트에 있더라도, 생성된 출력물에서 인용(citation)이나 명시적 참조로 나타날 것이라는 보장은 없습니다.
따라서 “내 로그에서 GPTBot이 보인다”는 주장은 “GPTBot이 내 콘텐츠로 학습했다”는 주장보다 약하며, “GPTBot이 내 콘텐츠를 인용할 것이다”라는 주장보다는 훨씬 더 약합니다. 전자는 관찰 가능하지만, 후자들은 제공업체 측의 정책 및 구현 세부 사항입니다.
GEO에 대해 이것이 말해주고 안 말해주는 것
모델이 콘텐츠를 사용하는 방식을 통제하는 방법으로 지리적 옵트아웃 파일(geographic opt-out files)이나 LLM 전용 봇 로봇 지침(LLM-specific robots instructions)에 대한 논의가 많습니다. llms.txt와 같은 파일은 그 대화의 한 부분일 뿐이며, 액세스 로그는 GEO 정책이 실제로 어떻게 시행되는지에 대해 많은 것을 알려주지 않습니다.
로그를 통해 합리적으로 말할 수 있는 것은 다음과 같습니다:
- “이 크롤러 계열은
llms.txt를 알고 있으며 이를 가져오는 것 같습니다.”
- “이 크롤러는 이러한 IP 범위와 빈도로 방문하는 것 같습니다.”
로그를 통해 안전하게 말할 수 없는 것은 다음과 같습니다:
- “이 제공업체는 나의 GEO 또는 사용 지침을 완전히 준수하고 있다.”
- “내 콘텐츠가 모든 지역의 향후 학습 실행에서 제외된다.”
- “만약 내가 오늘
llms.txt를 변경한다면, 그 영향이 특정 날짜까지 모든 곳에 전파될 것이다.”
최선이라고 해도 상관관계를 파악할 수 있습니다. 즉, llms.txt를 게시하거나 변경하면 특정 봇이 이를 가져가는 것을 보고, 해당 파일에 언급된 정책이 이제 적용된다고 가정할 수 있습니다. 실제 강제 로직과 시간표는 다른 사람의 API와 릴리스 노트 뒤에 놓여 있습니다.
llms.txt와 로그를 여전히 신경 써야 하는 이유
이러한 모든 주의사항에도 불구하고, llms.txt와 llms-full.txt는 여전히 유용한 조절 장치(knobs)입니다:
- 이는 선호 사항을 명확하고 기계가 읽을 수 있는 곳에 명시할 수 있게 해줍니다.
- 접근 로그를 통해 최소한 일부 크롤러들이 관심을 기울이고 있는지 확인할 수 있습니다.
- 정책이나 제공업체가 변경될 때, 이번 달 어떤 메타 태그나 헤더가 중요한지 추측하는 대신 업데이트할 구체적인 파일이 있습니다.
반면에 이들은 마법이 아닙니다. 만약 콘텐츠가 LLM에서 어떻게 사용되는지에 관심이 있다면, 로그는 단지 첫 번째의 저기술적 피드백 루프일 뿐입니다. 누가 문을 두드렸는지 알려줄 뿐입니다. 데이터가 서버를 떠난 후에 무슨 일이 일어났는지는 알려주지 않습니다.