블루오션 키워드 판정
검색량만 보고 주제를 고르면 레드오션에 들어간다. 검색량 1만짜리 키워드에 이미 좋은 글이 10만 개 있으면 그건 기회가 아니다. 반대로 검색량 3천에 제대로 답한 글이 없으면 그게 빈 자리다.
수요와 공급을 함께 재기 전에는 주제를 확정하지 않는다.
도구
node ~/.claude/skills/blueocean/scripts/blueocean.mjs --seeds 요양병원 요양원 장기요양등급
node ~/.claude/skills/blueocean/scripts/blueocean.mjs --exact 욕창 섬망 본인부담상한제
node ~/.claude/skills/blueocean/scripts/blueocean.mjs --seeds 명조 명조공략 --hot 30
| 옵션 | 뜻 |
|---|---|
--seeds <k...> |
시드 키워드. 연관키워드로 확장한 뒤 판정한다 |
--exact <k...> |
확장 없이 이 키워드만 잰다 |
--hot <n> |
기회점수 순 상위 n개. 열기 축을 함께 잰다. 아래 참고 |
--revenue <n> |
수익점수 순 상위 n개. 광고 단가 축으로 줄을 세운다 |
--min <n> |
확장 결과 중 이 검색량 이상만 (기본 500) |
--top <n> |
판정할 개수 (기본 80). 키워드당 검색 API 2회 |
--exclude <re> |
제외 정규식. 아래 '오염 키워드' 참고 |
--out <path> |
JSON 저장 경로 (기본 blueocean.json) |
--json |
표 대신 JSON 을 표준출력으로 |
--no-trend |
추세 생략. 빠르게 볼 때 |
시드 5개면 연관키워드가 최대 1,000개까지 딸려 나온다. 니치 하나에 시드 3~5개면 충분하다.
—— 트래픽으로 줄을 세울 때는 --hot
기본 정렬(실질포화도)은 못 쓸 1위를 만든다. 수요 10에 글 0편인 키워드는 포화 0 으로
A등급 최상위에 오르지만 그 글은 월 10회 노출된다. 실제로 명조 니치를 재 보니 A등급 14위가
전부 수요 1040짜리(명조음골, 명조성흔, 명조성휘광석)였고, 진짜 자리인 명조청초
(수요 3,920 · 글 684편)는 8위에 있었다.
--hot은 수요와 공백을 곱해 트래픽 기회의 상대 순위를 매긴다. 점수는 실제 월 방문자 예측값이 아니다.
reach = 1 / (1 + 실질포화/3) 공백이 클수록 상위에 붙을 확률이 높다
scale = 1 / (1 + 문서수/20000) 포화가 같아도 절대 문서량이 크면 신규 블로그가 못 뚫는다
점수 = 수요 × 0.3 × reach × scale
scale 이 없으면 헤드 키워드가 무조건 1위가 된다. 명조(수요 41,100 · 글 12.6만)는
reach 만으로 6,100점이지만 개인 블로그가 12.6만 편을 제칠 확률은 그렇지 않다.
scale 을 곱하면 838점으로 내려가 명조청초(1,076점) 아래에 놓인다. 뚫리는 쪽이 위로 온다.
점수의 절대값은 의미가 없다. 같은 실행 안에서 키워드끼리 비교하는 용도다.
다섯 번째 축 — 열기
--hot 일 때만 키워드당 1회를 더 써서 sort=date 로 최신 100편을 받는다.
같은 '글 1,000편'이라도 2년에 걸쳐 쌓인 것과 지난주에 쏟아진 것은 완전히 다른데
포화도는 이 둘을 구분하지 못한다.
| 칼럼 | 읽는 법 |
|---|---|
| 신규글/일 | 최신 표본의 절반이 쌓인 속도. 높으면 지금 터지는 이슈이자 남들도 달려드는 중 |
| 30일 | 최신 100편 중 30일 이내 비율. 100%면 살아 있는 주제, 0%면 아무도 안 쓴다 |
| 최근글 | 마지막 글이 며칠 전인가. 수요가 있는데 이 값이 크면 방치된 자리다 |
속도는 양날이라 점수에 넣지 않고 칼럼으로만 보여준다. 해석은 사람이 한다.
명조청초는 4.3편/일에 30일 비율 71% — 지금 터지는 중이라 빨리 써야 하고,
명조용량은 0.1편/일에 최근글 11일 전인데 YoY 2.46 — 수요는 느는데 아무도 안 쓰는 자리다.
속도는 최신 절반으로만 잰다. 표본 전체를 쓰면 꼬리가 결과를 뒤집는다. 명조청초는
출시 11일차인데 표본 100편 중 29편이 30일보다 오래됐다(네이버가 '청초'를 따로 매칭해
옛 글을 물어온다). 그 29편이 span 을 늘리면 4.3편/일짜리가 0 으로 찍힌다.
—— 트래픽이 곧 수익은 아니다: --revenue
애드포스트 수익은 노출 × 단가인데 앞의 축들은 전부 노출만 잰다. 그래서 트래픽이 크고 돈이 안 되는 주제를 1위로 올린다. 실측한 값이 이렇다.
| 키워드 | 월검색 | 광고깊이 | 경쟁 | 광고CTR | 단가배율 |
|---|---|---|---|---|---|
| 손흥민 | 413,400 | 0 | 낮음 | 0.00 | 0.03 |
| 이강인 | 622,800 | 0 | 낮음 | 0.00 | 0.03 |
| KBO순위 | 612,000 | 0 | 낮음 | 0.00 | 0.03 |
| 명조 | 41,100 | 4 | 중간 | 0.42 | 0.33 |
| 실손보험 | 18,480 | 10 | 높음 | 2.88 | 1.15 |
위 표의 조회 당시 연예인·운동선수 키워드는 검색광고 깊이가 0이었다. 검색광고 지표만으로 콘텐츠 광고의 광고주 유무나 애드포스트 수익을 단정할 수는 없다. 검색량 22분의 1인 실손보험이 단가배율 38배다. 트래픽만 보고 연예·스포츠로 가면 안 된다.
단가배율 = 경쟁도(낮음 0.2 · 중간 0.6 · 높음 1.0) × (0.15 + 광고깊이/10)
수익점수 = 기회점수 × 단가배율
0.15 는 바닥값이다. 광고 슬롯이 0 이어도 콘텐츠 광고로 소액은 붙으므로 0 으로 죽이지 않는다.
검색광고 API 같은 응답에 이미 들어 있어 추가 호출이 없다.
--hot 과 순위가 뒤집히는 일이 흔하다. 발로란트전적검색은 기회점수 4,716 으로 1위였지만
광고깊이 0 이라 수익점수 141 로 밀리고, 기회점수 2,094 인 발로란트조준점(광고깊이 1)이
314 로 올라선다. 트래픽을 원하면 --hot, 수익을 원하면 --revenue 를 쓴다.
이 도구가 못 재는 것 — SERP 구조
포화도는 '블로그 글 수 ÷ 검색량'이지 네이버 검색 결과에서 블로그 영역이 실제로 보이는지는
재지 못한다. 연예·스포츠·시사 쿼리는 네이버가 뉴스·스포츠 전용 영역을 최상단에 박아
블로그가 비집을 자리가 구조적으로 없다. 오늘의운세(검색 523만, 포화 0, 광고깊이 9)가
수익점수 1위로 찍히지만 실제로는 네이버 자체 운세 서비스가 상단을 차지한다.
A등급 + 고단가인데 유독 비어 있으면 의심한다. 왜 아무도 안 썼는지 SERP 를 직접 본다.
네 축
| 축 | 출처 | 뜻 |
|---|---|---|
| 수요 | 검색광고 키워드도구 | 월간검색수(PC+모바일) |
| 공급 | API HUB 검색>블로그 | 이미 존재하는 글 수 |
| 상업성 | 같은 검색 결과 상위 10건 | 파는 글의 비율 |
| 추세 | DataLab 검색어트렌드 | 전년 동기 대비 + 성수기 달 |
포화도 = 블로그 글 수 / 월간검색수
실질포화도 = 포화도 × (1 − 광고비율 × 0.5)
등급 = A 블루오션(<3) · B 양호(<10) · C 경쟁(<40) · D 레드오션
세 번째 축이 핵심이다. 문서가 많아도 전부 광고면 정보 공백은 그대로 남는다. 상위 10건이 전부 업체 글인 키워드는 포화도가 40이어도 실제로는 쓸 자리가 있다.
결과를 읽을 때 — 반드시 확인할 세 가지
1. A등급인데 성수기 N월! 이 붙어 있으면 그 등급은 한 달짜리다
말복은 검색량 213만, 포화 0.22 로 A등급 1위로 올라온다. 그런데 말복은 8월의 하루다.
월간검색수가 며칠에 몰려 있어서 포화도가 좋아 보일 뿐, 연중 대부분은 아무도 안 찾는다.
! 가 붙은 키워드는 순위가 아니라 발행 시점을 알려주는 신호로 읽는다.
쓸 가치가 있는 계절 키워드도 있다 — 본인부담상한제는 성수기 8월이지만 평시에도 꾸준히 검색된다.
구분하려면 24개월 곡선을 직접 본다(--json 으로 받아서 확인).
2. 오염 키워드를 걸러라
연관키워드 확장은 우리 독자가 아닌 것을 잔뜩 물어온다. 실제로 겪은 것들:
| 종류 | 예 | 왜 문제인가 |
|---|---|---|
| 구직자 | 요양보호사(36,420), 병원동행매니저(28,350) |
서비스를 받는 사람이 아니라 하려는 사람 |
| 브랜드 | 페넬로페기저귀, 나비잠기저귀 |
특정 상품. 정보 글로 못 이긴다 |
| 인접 오독 | 기저귀(33,840) 중 대부분이 신생아용 |
성인용은 9,700 뿐이다 |
| 지역·내비게이션 | 아산병원근처암요양병원, 강남역 |
글이 아니라 위치를 찾는 검색 |
--exclude '채용|자격증|학원|중고|근처|가격비교' 처럼 정규식으로 잘라낸다.
합산 검색량을 보고하기 전에 무엇이 섞였는지 반드시 뜯어본다.
3. 포화도는 네이버 블로그 생태계의 것이다
구글·AI 검색을 노리는 사이트라면 절대값이 아니라 키워드 사이의 상대 비교로만 읽는다. 제도·행정 키워드는 네이버가 과대평가되는 경향이 있다.
자격증명
다음 순서로 찾는다. 하나만 있으면 된다.
- 환경변수
./.env— 프로젝트 로컬~/.claude/.naver-api.env— 전역 (사용자별 설정 필요)
| 키 | 무엇 | 발급 |
|---|---|---|
NAVER_AD_API_KEYNAVER_AD_SECRET_KEYNAVER_AD_CUSTOMER_ID |
수요. 월간검색수의 유일한 출처 | searchad.naver.com → 도구 → API 사용 관리. 무료, 결제정보 불필요 |
NAVER_CLIENT_IDNAVER_CLIENT_SECRET |
공급·추세 | ncloud.com → NAVER API HUB → Application 등록 → 검색(블로그·뉴스)과 Data Lab 체크 |
한도는 넉넉하다. 블로그 검색 25,000회/일, 트렌드 50,000회/월. 후보 80개 판정에 약 170회를 쓴다.
API 규격이 2026년에 바뀌었다
신규 신청은 NAVER API HUB(네이버 클라우드 플랫폼)를 사용한다. 기존 개발자센터에서 2026년 7월 31일 이전 신청한 검색·검색어 트렌드 API는 공식 공지상 2027년 6월 30일까지 지원된다. 이 스크립트는 API HUB 규격을 사용하므로 구형 인증정보를 혼용하지 않는다.
공식 공지: https://developers.naver.com/notice/article/32530
| 기존 개발자센터 | 현행 | |
|---|---|---|
| 헤더 | X-Naver-Client-Id / -Secret |
X-NCP-APIGW-API-KEY-ID / X-NCP-APIGW-API-KEY |
| 검색 | openapi.naver.com/v1/search/blog.json |
naverapihub.apigw.ntruss.com/search/v1/blog |
| 트렌드 | openapi.naver.com/v1/datalab/search |
naverapihub.apigw.ntruss.com/search-trend/v1/search |
트렌드 경로는 하이픈이 들어간 search-trend 다. datalab/* 계열은 전부 404 다.
검색광고 API(api.searchad.naver.com)는 이관 대상이 아니라 HMAC 방식 그대로다.
응답 코드로 원인을 구분한다.
404— 그런 경로가 없다. 오타이거나 규격이 다르다401— 인증정보와 신청 API를 확인한다. 원인을 상태 코드만으로 단정하지 않는다429— 한도 초과. 호출 간격을 늘린다
추세 지표를 짧은 창으로 내지 마라
12개월치의 '최근 3개월 / 첫 3개월' 비교는 계절 키워드에서 거짓 하락을 만든다. 본인부담상한제는 매년 8~9월에 환급 안내문이 나가 그때만 5배로 뛴다. 12개월 창의 앞쪽에 그 스파이크가 걸리면 0.24, 급락으로 찍힌다. 24개월을 받아 같은 달끼리 비교하면 1.74, 성장 중이다.
스크립트는 한국 시간 기준 완료된 월 24개를 조회해 이전 12개월 평균과 최근 12개월 평균을 비교한다. 24개 월의 누락·중복이 있으면 원자료만 보존하고 전년 대비 계산을 생략한다. 직접 계산할 일이 있어도 이 방식을 쓴다.
판정 후
블루오션이라고 다 쓸 수 있는 건 아니다. 등급은 쓸 수 있는 주제인지의 필요조건이지 충분조건이 아니다. 그 주제로 원천보다 나은 글을 쓸 수 있는지는 따로 판단한다. 프로젝트에 원고 헌장이 있으면 그 기준(원천 우위 테스트 등)을 함께 적용한다.
구현 보완 — 2026-09-20
- 광고성은 상위 10건의 거친 추정이다. 일반 제목·요약의
병원,센터,상담만으로는 광고로 판정하지 않는다. 의료기관명으로 끝나는 블로그 이름, 상담 신청·무료 상담·협찬 등 명시적인 신호를 사용한다. 기관 계정도 정보 글을 쓸 수 있으므로 오판 가능성은 남는다. - JSON의 각 행에
monthly(월별 상대 검색 지수),trendWindow,trendComplete를 보존한다. 월별 지수는 절대 검색량이 아니다. - JSON의
warnings에 조회 실패·추세 누락을 기록하고, 포화도 측정 불가 키워드는unmeasured에 보존한다.measuredCount는 순위 산출에 성공한 개수다. 뉴스·추세 등 보조 지표까지 모두 성공했다는 뜻은 아니다. - 통신 오류·HTTP 429·5xx는 최대 3회 시도하고, 요청마다 30초 제한을 둔다. 인증·경로 오류는 재시도하지 않는다.
- 수익점수는 검색광고 경쟁도·깊이에 기반한 비교용 휴리스틱이다. 실제 CPC·애드포스트 수익을 측정하지 않는다. 광고 CTR은 표시만 하며 점수에는 쓰지 않는다.
- 추세·열기는 정렬 점수에 들어가지 않는 참고 정보다.
--hot과--revenue를 함께 쓰면 수익 정렬이 우선하고 열기는 조회하지 않는다. - 검증:
node --test scripts/blueocean.test.mjs(외부 API 호출 없음).
다른 에이전트에서 시작하기
설치 안내를 읽는다. 파일·명령 실행이 가능한 에이전트와 Node.js가 필요하다. API 키가 없으면 설정·테스트까지만 완료하고 사용자에게 발급 경로를 안내한다. 조회하지 않은 수치를 만들지 않는다.