네이버 블로그 주소가 꼭 계정 아이디와 같지는 않습니다. 블로그 설정에서 주소를 따로 정해 둔 경우가 있어서, 주소창에 보이는 blog.naver.com/xxxx 의 xxxx 를 그대로 아이디라고 믿고 API 나 크롤링에 넣으면 엉뚱한 결과가 나오거나 아예 조회가 안 됩니다. 블로그 마케팅 도구를 만들거나 이웃 목록, 순위 조회 같은 기능을 붙이다 보면 "주소"가 아니라 "진짜 아이디"가 필요한 순간이 생깁니다.
확인하는 주소
이럴 때 쓰는 게 네이버가 예전 Windows Live Writer 연동용으로 열어 둔 매니페스트 주소입니다. blogId 자리에 블로그 주소(별칭)를 넣고 열어 보면 됩니다.
https://blog.naver.com/NBlogWlwLayout.naver?blogId=sequoia-jeju
응답은 이런 XML 로 옵니다.
<manifest xmlns="http://schemas.microsoft.com/wlw/manifest/weblog">
<weblog>
<imageUrl>http://blog.naver.com/favicon.ico</imageUrl>
<homepageLinkText>네이버 블로그 바로가기</homepageLinkText>
</weblog>
<views>
<default>WebLayout</default>
<view type="WebLayout" src="/wlwlayout.html" />
<view type="WebPreview" src="http://api.blog.naver.com/BlogPreview.nhn?blogId=atg-cas" />
</views>
</manifest>
볼 곳은 WebPreview 의 src 끝부분입니다. 요청할 때는 sequoia-jeju 를 넣었는데, 돌아온 미리보기 주소에는 blogId=atg-cas 가 박혀 있습니다. 이 atg-cas 가 실제 계정 아이디입니다. 즉 sequoia-jeju 는 나중에 붙인 블로그 주소이고, 내부적으로는 여전히 원래 아이디로 관리되고 있다는 뜻이죠. 주소를 바꾸지 않은 블로그라면 넣은 값과 똑같은 아이디가 돌아옵니다.
코드로 뽑아 쓰려면
매번 브라우저로 열어 볼 수는 없으니, 저는 이런 식으로 정규식 한 줄로 빼서 씁니다. 원 글에는 주소와 응답만 있었고 아래 PHP 는 이해를 돕기 위해 붙인 예시입니다. 서버에서 allow_url_fopen 이 꺼져 있는 환경이 많아 cURL 로 받았습니다.
<?php
function naverRealBlogId(string $alias): ?string
{
$url = 'https://blog.naver.com/NBlogWlwLayout.naver?blogId=' . rawurlencode($alias);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$xml = curl_exec($ch);
curl_close($ch);
if ($xml && preg_match('/BlogPreview\.nhn\?blogId=([^"&]+)/', $xml, $m)) {
return $m[1];
}
return null;
}
echo naverRealBlogId('sequoia-jeju'); // atg-cas
VB.NET 이나 VBA 로 할 때도 방식은 같습니다. WebClient·MSXML2.XMLHTTP 로 받아서 blogId= 뒤부터 큰따옴표 전까지 잘라 내면 됩니다. 엑셀에서 블로그 목록 옆 칸에 아이디를 채우고 싶다면 이런 함수를 표준 모듈에 넣어 두면 됩니다.
Function NaverRealBlogId(blogAlias As String) As String
Dim http As Object, txt As String, p As Long, q As Long
Const KEY As String = "BlogPreview.nhn?blogId="
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", "https://blog.naver.com/NBlogWlwLayout.naver?blogId=" & blogAlias, False
http.send
txt = http.responseText
p = InStr(txt, KEY)
If p = 0 Then Exit Function
p = p + Len(KEY)
q = InStr(p, txt, """")
If q > p Then NaverRealBlogId = Mid(txt, p, q - p)
End Function
찾지 못하면 빈 문자열을 돌려줍니다. 시트에서 =NaverRealBlogId(A2)처럼 수식으로 쓸 수도 있지만, 그러면 재계산될 때마다 요청이 나가니 목록이 길다면 매크로로 한 번 돌려서 값만 남겨 두는 편이 낫습니다.
사용자가 전체 주소를 붙여 넣는 경우
실제로 입력을 받아 보면 별칭만 넣는 사람보다 https://blog.naver.com/sequoia-jeju/2231... 처럼 글 주소를 통째로 붙여 넣는 사람이 더 많습니다. 모바일에서 복사하면 m.blog.naver.com 으로 시작하기도 하고요. 그래서 위 함수에 넘기기 전에 주소에서 첫 번째 경로만 떼어 내는 단계를 하나 두면 편합니다.
function blogAliasFromUrl(string $url): ?string
{
if (preg_match('#^https?://(?:m\.)?blog\.naver\.com/([A-Za-z0-9_-]+)#', $url, $m)) {
return $m[1];
}
return null;
}
다만 blog.naver.com/PostView.naver?blogId=... 같은 예전 형식 주소는 첫 경로가 PostView 라서 이 정규식으로는 엉뚱한 값이 나옵니다. 이런 주소는 경로 대신 쿼리 문자열의 blogId 값을 꺼내야 하니, PostView 가 들어 있으면 parse_url 과 parse_str 로 처리하도록 분기해 두세요. 없는 주소를 넣었을 때 응답이 어떤 모양으로 오는지는 확인해 두지 않았기 때문에, 위 함수들처럼 패턴을 못 찾으면 실패로 처리하는 방식으로만 짰습니다.
왜 아이디를 따로 두었을까
네이버 계정 아이디는 바꿀 수 없지만, 블로그 주소는 별도로 정할 수 있게 해 둔 구조로 보입니다. 아이디가 의미 없는 문자열이거나 회사 계정이라 블로그 성격과 안 맞을 때 보기 좋은 주소를 쓰라는 취지겠지요. 문제는 외부에서 보면 이 둘을 구분할 방법이 잘 안 보인다는 점입니다. 통계나 API 쪽은 대개 원래 아이디 기준이라, 주소만 저장해 두고 나중에 아이디로 조회하면 어긋날 수 있습니다. 블로그 목록을 DB 로 관리한다면 주소와 실제 아이디를 칼럼을 나눠 같이 저장해 두는 편이 덜 헷갈립니다.
비공개 엔드포인트라 언제든 바뀔 수 있다는 점도 염두에 두세요. 짧은 시간에 많이 호출하면 막힐 수 있으니 결과를 캐시해 두고 필요할 때만 다시 묻는 게 안전합니다.