클로드코드(Claude Code)로
주식 분석 웹 서비스 만들기
— #5. 카카오톡 연동하기
분석 기능까지 완성됐으니 이제 매수 신호가 발생했을 때 카카오톡으로 알림을 받는 기능을 붙일 차례다. 카카오 비즈니스 채널 없이 무료로 구현할 수 있고, 본인뿐 아니라 친구에게도 알림을 보낼 수 있다. 설정 과정에서 마주친 에러들과 해결 방법도 함께 정리했다.
01 사용한 프롬프트 모음
아래 프롬프트를 순서대로 입력하면 이 글의 카카오톡 연동 기능 전체를 재현할 수 있다.
# FastAPI로 카카오 OAuth 2.0 로그인 흐름을 구현해줘.
# GET /api/kakao/auth-url : scope=talk_message,friends 인가 URL 반환
# GET /api/kakao/callback : 인가 코드 → 토큰 교환, kakao_tokens.json에 저장
# 토큰 교환 시 client_secret 필수 포함, prompt=consent로 동의 화면 강제 표시
# 콜백 응답은 HTMLResponse + charset utf-8로 처리해줘 (한글 깨짐 방지)
# 카카오 토큰을 서버의 kakao_tokens.json 파일에 저장하고
# access_token 만료(401) 시 refresh_token으로 자동 갱신하는 로직을 만들어줘.
# refresh_token도 새로 발급되면 함께 갱신 저장.
# access_token ~6시간, refresh_token ~2개월 만료 주기 고려.
# 카카오톡 메시지 발송 함수 2개를 구현해줘.
#
# 1. send_to_me(title, description)
# POST https://kapi.kakao.com/v2/api/talk/memo/default/send
# text 타입 템플릿, "확인하기" 버튼 포함
#
# 2. send_to_friends(friend_uuids, title, description)
# POST https://kapi.kakao.com/v1/api/talk/friends/message/default/send
# receiver_uuids 파라미터로 발송 대상 지정
#
# 3. send_alert() — 위 두 함수를 묶어 나에게 + 동의한 친구 전체에게 동시 발송
# 친구가 앱에 동의할 수 있는 별도 콜백 엔드포인트를 만들어줘.
# GET /api/kakao/friend-callback : 토큰 교환 후 저장하지 않고 동의만 등록
# GET /api/kakao/friends : 친구 목록 조회 (앱 심사 전 팀원만 노출)
# GET /api/kakao/status : 연동 상태 확인 (토큰 유무)
# Next.js 14 + TypeScript + Tailwind CSS로 카카오 연동 UI를 만들어줘.
# - "카카오 계정 연동하기" 버튼: auth-url 호출 → 새 창(500×600)으로 열기
# - 연동 상태 표시 (연동됨 / 미연동)
# - 친구 목록 새로고침 버튼
# - 테스트 발송 버튼: POST /api/kakao/test 호출
# next.config.js에 /api/* → http://localhost:8005/api/* 프록시 설정도 포함해줘.
02 사용하는 카카오 API 개요
카카오 비즈니스 채널 없이 개인 프로젝트 수준에서 사용할 수 있는 API만 활용한다. 모두 무료다.
| API | 용도 | 제약 |
|---|---|---|
| 카카오 로그인 (OAuth 2.0) | access_token / refresh_token 발급 | 무료, 제한 없음 |
| 나에게 보내기 | 본인 카카오톡으로 알림 | 무료, 제한 없음 |
| 친구 목록 조회 | 발송 대상 UUID 조회 | 앱 심사 전: 팀원만 조회 가능 |
| 친구에게 보내기 | 친구 카카오톡으로 알림 | 친구도 앱에 OAuth 로그인 + 동의 필요 |
인가 코드 발급
access + refresh
서버 저장
나에게 + 친구에게
03 카카오 Developers 앱 설정
developers.kakao.com 에 접속해 아래 순서대로 설정한다. 코드 작성 전에 이 과정을 먼저 완료해야 한다.
- 01 앱 추가 — 앱 이름, 회사명, 카테고리(금융) 입력. 앱 대표 도메인은
http://192.168.x.x형식의 사설 IP 입력 (localhost불가) - 02 REST API 키 발급 — [플랫폼 키] → [REST API 키 추가]. Client Secret도 이 단계에서 함께 발급되니 반드시 저장
- 03 Redirect URI 등록 —
http://192.168.x.x:3002/api/kakao/callback과/friend-callback두 개 모두 등록. URI가 1자라도 다르면 KOE006 에러 발생 - 04 카카오 로그인 활성화 — [제품 설정] → [카카오 로그인] → 상태 ON. 이 설정이 OFF면 KOE004 에러
- 05 동의항목 설정 —
talk_message: 선택 동의 /friends: 이용 중 동의 (선택 동의는 API 검수 필요라 비활성). 동의 목적 텍스트도 입력 필요 - 06 팀원(테스터) 등록 — [앱] → [팀 관리]. 앱 심사 전에는 팀원으로 등록된 사용자만 친구 API 대상이 됨
ipconfig(Windows) 또는 ifconfig(Mac/Linux) 명령어로 확인한다. 공유기 환경에서 IP가 바뀌면 Redirect URI도 다시 등록해야 한다.발급된 키는 바로 .env 파일에 저장한다.
KAKAO_REST_API_KEY=your_rest_api_key_here
KAKAO_CLIENT_SECRET=your_client_secret_here
KAKAO_REDIRECT_URI=http://192.168.x.x:3002/api/kakao/callback
04 백엔드 구현 (FastAPI)
OAuth 콜백, 토큰 저장/갱신, 메시지 발송 세 부분으로 나뉜다.
OAuth 콜백 — prompt=consent 파라미터를 넣어 이미 동의한 사용자도 동의 화면을 다시 표시하도록 강제한다. "이용 중 동의" 항목의 권한을 얻기 위해 필요하다.
@router.get("/api/kakao/auth-url")
def get_auth_url():
scope = "talk_message,friends"
url = (
f"https://kauth.kakao.com/oauth/authorize"
f"?client_id={settings.KAKAO_REST_API_KEY}"
f"&redirect_uri={settings.KAKAO_REDIRECT_URI}"
f"&response_type=code"
f"&scope={scope}"
f"&prompt=consent" # 동의 화면 강제 표시
)
return {"url": url}
토큰 저장 — access_token은 약 6시간, refresh_token은 약 2개월 후 만료된다. 서버의 kakao_tokens.json에 저장해두면 서버 재시작 후에도 유지된다.
토큰 자동 갱신 — 메시지 발송 시 401 응답이 오면 refresh_token으로 재발급을 시도한다. 새 refresh_token이 응답에 포함될 경우 함께 갱신한다.
async def refresh_access_token() -> str | None:
tokens = _load_tokens()
async with httpx.AsyncClient() as client:
resp = await client.post(
"https://kauth.kakao.com/oauth/token",
data={
"grant_type": "refresh_token",
"client_id": settings.KAKAO_REST_API_KEY,
"client_secret": settings.KAKAO_CLIENT_SECRET,
"refresh_token": tokens.get("refresh_token"),
},
)
data = resp.json()
tokens["access_token"] = data["access_token"]
if "refresh_token" in data: # 새 refresh_token 발급 시 갱신
tokens["refresh_token"] = data["refresh_token"]
_save_tokens(tokens)
return data["access_token"]
통합 발송 함수 — 나에게 보내기와 친구에게 보내기를 하나의 함수로 묶었다. APScheduler에서 매매 조건 충족 시 이 함수 하나만 호출하면 된다.
async def send_alert(title: str, description: str):
# 나에게 보내기
await send_to_me(title, description)
# 동의한 친구 전원에게 보내기
friends = await get_friends()
if friends:
uuids = [f["uuid"] for f in friends]
await send_to_friends(uuids, title, description)
05 친구에게 보내기
친구에게 알림을 보내려면 친구도 앱에 OAuth 로그인 + 메시지 수신 동의를 완료해야 한다. 별도 콜백 엔드포인트를 만들어 친구가 직접 동의할 수 있는 링크를 제공하는 방식으로 구현했다.
- 01 본인이 웹 UI에서 "친구 초대 링크 복사" 클릭
- 02 생성된 URL을 카카오톡으로 친구에게 전달
- 03 친구가 링크 클릭 → 카카오 로그인 → 동의 완료
- 04 본인이 "친구 목록 새로고침" 클릭 → 친구가 목록에 나타남
06 프론트엔드 연동 UI
Next.js에서 FastAPI 백엔드로 요청을 프록시하도록 next.config.js를 설정한다.
const nextConfig = {
async rewrites() {
return [{ source: "/api/:path*", destination: "http://localhost:8005/api/:path*" }];
},
};
"카카오 계정 연동하기" 버튼 클릭 시 auth-url에서 받은 주소를 팝업 창으로 연다.
const handleConnect = async () => {
const { url } = await api.kakaoAuthUrl();
window.open(url, "_blank", "width=500,height=600");
};
| 기능 | API |
|---|---|
| GET /api/kakao/status | 연동 상태 확인 (토큰 유무) |
| GET /api/kakao/auth-url | OAuth 로그인 URL 반환 |
| GET /api/kakao/friends | 동의한 친구 목록 조회 |
| POST /api/kakao/test | 테스트 메시지 발송 |
07 트러블슈팅
설정 과정에서 자주 마주치는 에러들을 정리했다.
-
KOE006 — 등록하지 않은 리다이렉트 URI 카카오 Developers에 등록된 Redirect URI와 요청 URI가 1자라도 다를 때 발생한다. [플랫폼 키] → REST API 키의 "카카오 로그인 리다이렉트 URI"에 정확한 URI를 등록한다. "로그아웃 리다이렉트 URI"(카카오 로그인 → 고급)와 혼동하지 말 것.
-
KOE010 — Bad client credentials 토큰 교환 요청 body에
client_secret이 누락됐을 때 발생한다. REST API 키 생성 시 함께 발급된 Client Secret을 반드시 포함해야 한다. -
KOE205 — 설정하지 않은 동의 항목 OAuth scope에 존재하지 않거나 미설정된 항목을 넣었을 때 발생한다. 유효한 scope는
talk_message,friends두 가지다.talk_message_friends같은 항목은 없다. -
403 insufficient scopes 동의항목 설정 전에 발급된 토큰을 사용하고 있을 때 발생한다. 서버의
kakao_tokens.json을 삭제하고 "카카오 계정 연동하기"를 다시 실행해 모든 항목에 재동의한다. -
친구 목록 code: -5 앱 심사 전 상태에서 팀원이 아닌 사용자를 친구 API로 조회할 때 발생한다. [앱] → [팀 관리]에서 해당 친구를 테스터로 등록하면 해결된다.
-
친구 목록 elements: [] (빈 배열) API는 200이지만 결과가 비어 있는 경우. 친구가
friends스코프에 동의하지 않았거나, 동의항목이 "이용 중 동의"가 아닌 경우다. 본인 토큰 삭제 후prompt=consent로 재인증하고, 친구도 앱 연결 해제 후 재연동한다. -
콜백 페이지 한글 깨짐 JSON 응답으로 한글을 반환할 때 인코딩이 깨진다. 콜백 응답을
HTMLResponse로 바꾸고<meta charset='utf-8'>를 포함하면 해결된다.
카카오 비즈니스 채널 없이 무료로 나에게 보내기 + 친구에게 보내기를 구현했다. 핵심은 세 가지다: Redirect URI 정확히 등록, 토큰 교환 시 client_secret 필수 포함, friends 동의항목을 "이용 중 동의"로 설정. 트러블슈팅 목록을 참고하면 대부분의 에러는 설정 문제임을 확인할 수 있다. 다음 편에서는 단타 매매 포지션 관리와 매도 알림 기능을 다룬다.
'비전공자의 바이브 코딩 > 일상 & 기초' 카테고리의 다른 글
| 클로드코드(Claude Code)로 코인 자동매매 프로그램 만들기 : #2. 자동매매 전략 수립 (0) | 2026.05.16 |
|---|---|
| 클로드코드(Claude Code)로 코인 자동매매 프로그램 만들기 : #1. 계획 수립 및 PRD (0) | 2026.05.16 |
| 클로드코드(Claude Code)로 주식 분석 웹 서비스 만들기 : #4. 주식 분석 기능 만들기 (0) | 2026.05.05 |
| 클로드코드(Claude Code)로 주식 분석 웹 서비스 만들기 : #3. 웹 페이지 만들기 (0) | 2026.05.04 |
| RAG 완벽 정리 (0) | 2026.05.03 |