평소 이것저것 서비스를 만들어보는 걸 좋아합니다. 이번에는 최근 트렌드에 맞춰 AI로 사주를 풀어주는 작은 웹사이트를 제작해 봤습니다. 화면 하나, 입력 폼 하나, 결과 창 하나로 구성된 단순한 구조이지만 막상 기획부터 구현까지 손을 대보니 코딩하기 전에 미리 정하고 가야겠다 싶은 갈림길이 몇 개 존재했습니다.

만들기 전에는 안 보이다가 막상 배포 단계에 이르러서야 보이는 실전 지점들이죠. 같은 형태의 AI 활용 웹앱을 만들려는 개발자나 테크 입문자분들에게 도움이 되도록, 구조적 고려 사항과 제가 직접 내린 기술적 선택을 명확히 정리했습니다.

1. AI에게 무엇을 맡길지 역할 분담부터 정한다

가장 먼저 짚어야 할 건 의외로 역할의 정의입니다. 사주풀이 서비스는 크게 두 단계의 프로세스로 나뉩니다.

첫째는 계산 단계입니다. 생년월일시 데이터를 기반으로 사주팔자 명식을 뽑는 과정으로, 음력 변환, 절기 계산, 60갑자 배치 같은 정해진 규칙과 공식의 영역입니다.

둘째는 해석 단계입니다. 추출된 팔자 명식을 사용자가 읽기 좋은 사람의 언어로 스토리텔링하여 풀어주는 과정입니다.

여기서 주의할 점은 큰 언어모델(LLM)은 문장을 매끄럽게 쓰는 해석에는 압도적으로 강하지만, 음력과 절기 경계를 계산하는 정확한 날짜 연산에는 의외로 자주 오류를 범한다는 것입니다.

제 선택은 이렇습니다. 토이 프로젝트 초기 단계 특성상 단순함을 유지하기 위해 계산까지 AI에게 맡겼습니다. 대신 화면에 재미로 보는 용도라는 한계점을 명확히 명시했습니다. 만약 추후 정밀한 정확도가 생명인 상용 서비스로 고도화한다면, 계산 단계는 검증된 만세력 라이브러리로 백엔드에서 정확히 처리하고, AI에게는 그 결과값만 건네 순수 해석만 전담시키는 구조로 설계해야 안전합니다.

2. API 키는 어디에 둘까 — 클라이언트단 배포는 절대 안 된다

가장 흔하게 보안 사고가 발생하는 지점입니다. 브라우저 자바스크립트에서 직접 AI API를 호출하면 개발이 단순해지지 않을까라는 유혹에 빠지기 쉽습니다. 하지만 API 키를 프론트엔드 코드에 노출하는 순간, 페이지 소스를 열어본 누구나 내 키를 그대로 탈취해 갈 수 있습니다. 거대한 요금 폭탄으로 이어지는 지름길입니다.

따라서 아키텍처를 철저하게 이원화해야 합니다.

  • 브라우저(화면단): 사용자의 입력 데이터만 받아 내 백엔드 서버로 전달
  • 내 서버: 보안 키를 숨긴 채 외부 AI API를 호출하고, 가공된 결과 텍스트만 다시 반환

API 키를 클라이언트가 아닌 백엔드 서버 뒤에 숨기고 안전하게 호출하는 아키텍처 구조

제 선택은 API 키를 소스 코드에 하드코딩하지 않고, 환경변수 파일인 .env로 격리하여 서버 구동 시점에만 읽어오도록 한 것입니다. 더불어 깃허브 같은 원격 저장소에 코드가 실수로 올라가는 불상사를 막기 위해 .gitignore에 해당 파일을 반드시 등록했습니다. 키 유출의 가장 흔한 경로가 저장소 커밋인 만큼, 이 기본 규칙을 지키는 것이 가장 중요합니다.

3. 서버 공개 순간 시작되는 진짜 위협 — 키 유출이 아니라 호출 남용

여기서 많은 초보 개발자가 오해하는 부분이 있습니다. 키를 서버 뒤에 숨겼으니 안심해도 된다고 생각하는 것입니다. 브라우저로 변수 값이 내려가지 않으니 키 자체는 안전한 게 맞습니다. 하지만 서버를 인터넷에 공개하는 순간 진짜 위협은 따로 시작됩니다. 바로 내 백엔드 API 엔드포인트 자체를 타인이 무단으로 대량 호출하는 것입니다.

인증 없는 공개 라우트라면 공격자가 내 api/saju 주소로 반복 스크립트를 돌려 수천, 수만 번 호출할 수 있습니다. 내 키는 노출되지 않았더라도 그 AI 연산 비용은 고스란히 내가 감당해야 합니다. 타인에게 공짜 API 프록시를 제공하는 꼴이죠. 실제로 인터넷에 연결된 모든 공개 서버는 매일 자동화된 스캐닝 봇의 무차별 호출 타깃이 됩니다.

그래서 방어의 초점을 단순히 키 숨기기가 아니라 호출 남용 차단으로 옮겼습니다.

  • 호출 횟수 제한: 같은 IP에서 분·일 단위 최대 횟수를 제한해 매크로 공격과 비용 폭탄을 물리적으로 차단
  • 리버스 프록시 및 CDN: 서버 앞단에 프록시를 두어 악성 봇을 1차 필터링하고 실제 서버 IP를 은닉
  • 응답 토큰 상한: 호출당 최대 토큰을 제한해 한 번의 호출당 비용 천장을 고정

4. 트래픽 증가에 대비한 비용 구조 설계

모든 요청마다 매번 실시간으로 AI를 호출하면 개발은 직관적이지만, 방문자가 늘수록 요금이 정비례로 상승합니다. 그렇다고 모든 결과를 미리 만들어 둘 수도 없습니다. 생년월일·시간·성별의 조합은 사실상 무한대이기 때문입니다.

그래서 콘텐츠 성격을 경우의 수에 따라 나눠 로직을 설계했습니다.

콘텐츠경우의 수처리 방식
띠별·별자리 운세12개미리 생성해 저장 후 조회만
오늘의 운세하루 12개매일 새벽 한 번만 갱신
개인 맞춤 사주사실상 무한요청 시 실시간 호출 + 캐싱

제 선택은 프로토타입 첫 버전은 단순함을 위해 매번 실시간 호출로 만들되, 위와 같은 비용 분할 설계 지도를 미리 그려둔 것입니다. 이렇게 라우트를 나눠 두면 방문자가 몰려도 트래픽의 상당수를 차지하는 띠별 운세 조회는 AI 비용이 거의 발생하지 않아 유지 비용이 획기적으로 줄어듭니다.

5. 서비스 특성을 고려한 프롬프트 톤앤매너

마지막으로 조율한 영역은 사주·운세 도메인이 가진 정서적 특성입니다. 운세 서비스는 본질적으로 미래에 대한 불안 심리를 자극하기 쉽습니다. 자칫 AI가 부정적이거나 자극적인 단어로 결과를 출력하면 사용자에게 불쾌감을 줄 수 있습니다.

그래서 백엔드 시스템 프롬프트에 단정적인 어조나 공포심을 조장하는 표현을 금지하고, 삶의 방향성을 제시하는 따뜻하고 희망적인 카운셀러 톤을 유지하도록 가이드라인을 심었습니다. 물론 화면에도 이 서비스는 재미로 보는 콘텐츠임을 명시해 두었습니다.

결론적으로 작은 토이 프로젝트 하나를 세상에 내놓는 과정도 단순 코드 작성을 넘어 아키텍처와 보안, 비용 관점의 끊임없는 선택의 연속이었습니다. 무엇을 모델에 맡길지, 키를 어떻게 격리할지, 남용 트래픽을 어떻게 제어할지, 비용을 어떻게 나눌지. 이 네 가지 기준점만 명확히 정하고 시작한다면 개발 기간을 크게 단축할 수 있습니다. 나만의 AI 서비스를 준비 중이라면 키보드를 잡기 전 이 설계 요소들을 먼저 점검해 보시길 권합니다.

🔮 내 사주 직접 보러 가기 →
이번에 만든 결과물 · saju.dadanote.net