Groq API
내 서비스에 Groq AI 연결하기 — 키 · 호출 · 챗봇
CLICK TO OPEN
내 서비스에 Groq AI 연결하기 — 키 · 호출 · 챗봇
CLICK TO OPEN
키 발급 · 기본 호출 · Express 프록시 · 프론트 챗봇
키 발급
Groq API 키 발급 — 무료로 시작
Groq = 무료로 AI를 코드에서 부르는 통로 (카드 등록 없이 시작)
키 = AI를 쓰기 위한 내 전용 비밀번호 — 발급받아 안전하게 보관
키 받기
① console.groq.com 접속 → 구글 계정 등으로 가입
② 왼쪽 API Keys → Create API Key
③ gsk_ 로 시작하는 키 복사 (생성 직후 한 번만 보임)
.env & .gitignore
• 키가 깃·브라우저에 노출되면 남이 내 키로 사용 가능
• 그래서 호출은 항상 서버(Express)에서 — 카드 03서 실습
핵심 포인트
• 키 = 출입증 — 남이 보면 내 몫을 대신 써버림
• 무료 — 카드 없이 시작, 분당 횟수 한도만 있음
• 키 두는 곳은 .env 한 곳뿐 — 코드·깃엔 직접 안 적음
자주 묻는 질문
.env 파일 이름이 왜 점(.)으로 시작하나요?
점으로 시작하면 '숨김 파일' 취급이라, 비밀값을 눈에 안 띄게 두는 관례 — 탐색기에서 기본으론 안 보일 수 있음
키를 실수로 깃허브에 올렸어요
그 키는 버린 셈 — console.groq.com 에서 해당 키를 삭제(Revoke)하고 새로 발급, 비번 바꾸듯 무조건 새 키로 교체
gsk_ 로 시작하는 게 무슨 뜻이에요?
Groq 키임을 나타내는 앞글자(접두어) — 코드가 'gsk_'로 시작하는지 보고 진짜 키인지 가짜인지 가려내기도 함
node_modules 는 왜 .gitignore 에 넣나요?
설치 파일 모음이라 용량이 크고, npm install 한 번이면 다시 생김 — 깃에 올릴 필요 없어 제외
기본 호출
기본 호출 — 주소·헤더·내용 3가지
핵심은 fetch 한 번 — 택배 보내듯 주소·송장(헤더)·내용물(body) 세 칸만 채우면 끝
Groq는 OpenAI 호환 형식, Node 18+ 내장 fetch 사용 (설치 불필요)
폴더 / 파일
코드 — 09_groq/02/basic_call.js
실행 (터미널)
채울 것 3가지
• 주소 — Groq 호출 엔드포인트
• 헤더 Authorization — Bearer + 키
• body — model · messages(대화 내용)
핵심 포인트
• AI에 말 거는 법 = 어디로(주소)·누구인지(키)·뭐라고(messages) 셋
• AI 답은 항상 choices?.[0]?.message?.content 안에 들어 있음
• model = 똑똑이 종류 고르기 (무료 llama부터 시작)
data.choices?.[0]?.message?.content || data
• ?.(Optional Chaining) — "혹시 이게 없으면 에러 내지 말고 undefined만 돌려줘" 라는 뜻
• data.choices[0]처럼 그냥 접근하면 choices가 없을 때 TypeError로 프로그램 중단, ?. 붙이면 없어도 안 죽고 undefined로 넘어감
• data.choices?.[0]?.message?.content — choices부터 content까지 한 단계씩 안전하게 파고 들어감(하나라도 없으면 그 순간 undefined)
• ||(OR 연산자) — "왼쪽 값 있으면 그거 쓰고, 없으면(undefined 등) 오른쪽 값 써라"
• 그래서 정상 응답이면 AI 답변 글자가 찍히고, 구조가 이상해서 content를 못 찾으면(undefined) data 전체가 대신 찍혀서 뭐가 왔는지 확인 가능
자주 묻는 질문
POST 가 뭐예요? 그냥 주소만 치면 안 되나요?
주소만 치는 건 정보 '받기'(GET) — POST 는 내용물(질문)을 담아 '보내기'. 질문을 실어 보내야 해서 POST 사용
'Bearer' 는 무슨 뜻이고 꼭 붙여야 하나요?
'이 키를 가진 사람' 이라는 정해진 형식 — Bearer 뒤에 한 칸 띄우고 키를 붙여야 인식됨, 빼면 거부당함
JSON.stringify 는 왜 쓰나요?
자바스크립트 객체를 '글자(문자열)'로 바꿔주는 함수 — 인터넷으로는 글자만 오갈 수 있어 보내기 전 변환 필요
await 는 왜 붙어 있어요?
'답이 올 때까지 잠깐 기다려' 라는 표시 — 안 붙이면 응답 오기 전에 다음 줄이 실행돼 빈 값이 나옴
require랑 await를 같이 쓰면 ERR_AMBIGUOUS_MODULE_SYNTAX 에러가 나요
require는 CommonJS 문법, 파일 맨 바깥(top-level)의 await는 ES Module 문법 — 둘이 섞이면 Node가 이 파일을 뭘로 실행할지 판단 못 함. 해결: await 쓰는 부분을 const main = async () => {...}; main()처럼 async 함수로 감싸기 (지금 코드가 이 방식)
프론트 연결
프론트 챗봇 연결 — 화면에서 물어보기
화면에 키 넣으면 누구나 훔쳐봄 → 서버(심부름꾼)가 대신 호출, 키는 서버 금고에만
화면(client) → 내 서버 /api/chat → 응답 표시 — 화면과 서버는 전화 한 통(fetch)으로 연결
폴더 / 파일 (정석 분리)
서버(server/)와 화면(client/)을 폴더로 나눔 — 서버는 키를 가진 심부름꾼, 화면은 서버 주소만 아는 손님
서버 — server/index.js (키 숨기고 대신 호출)
서버 실행 (터미널)
HTML=뼈대 / JS=동작으로 파일을 나눔 — HTML 맨 아래에서 <script src="app.js">로 연결
화면 뼈대 — client/index.html
화면 동작 — client/app.js
실행 순서
① server서 node index.js 먼저
② client/index.html 더블클릭 → 입력 → 보내기
• 응용: 추천 챗봇 · AI 학습도우미 · 여행플래너
핵심 포인트
• 화면은 내 서버 주소만 알면 됨 (AI 키는 화면에 절대 X)
• 순서 = 서버 먼저 켜고 → 화면 열기 (안 켜면 응답 못 받음)
• fetch = 화면이 서버에 "이것 좀 물어봐 줘" 부탁하는 전화
문자열 ↔ 객체 변환 정리표
| 상황 | 타입 | 필요한 변환 |
|---|---|---|
| HTML 입력칸 꺼내기 | 문자열 | ❌ 없음 |
| 객체를 네트워크로 보내기 | 객체 → 문자열 | ✅ JSON.stringify() |
| 네트워크 응답 받기 | 문자열 → 객체 | ✅ .json() |
인터넷으로는 글자(문자열)만 오갈 수 있음 — 그래서 객체를 보낼 땐 글자로 바꾸고(stringify), 받은 글자는 다시 객체로 바꿈(.json()). .value는 원래부터 문자열이라 변환 필요 없음
res.json()이 실제로 하는 일 — 서버 ↔ 클라이언트 왕복
이름이 똑같이 .json()이라 헷갈리기 쉬운데 방향이 정반대임
• 서버의 res.json(객체) — Express 메서드, 객체 → 문자열(내부에서 JSON.stringify)
• 클라이언트의 res.json() — fetch Response 메서드, 문자열 → 객체(파싱)
서버가 실제로 보내는 건 body 안에 든 글자(문자열) — {"reply":"..."} 처럼 생겼지만 그냥 텍스트임. 클라이언트의 res.json()이 이 글자를 파싱해서 진짜 JS 객체로 바꿔줌, 그래야 다음 .then(data => ...)에서 data.reply처럼 점 찍어서 꺼낼 수 있음(문자열 상태면 .reply 안 먹힘)
🎯 .then() vs .catch() 한 문장 요약
• .then() = "성공했을 때 뭐 할 거야?"
• .catch() = "실패했을 때 뭐 할 거야?"
fetch는 서버가 응답만 주면 에러여도 .then()으로 감(404·500도 "응답은 옴"). 근데 서버가 아예 꺼져있거나 네트워크가 끊기면 응답 자체가 안 오는 진짜 실패 — 이때 .catch()가 대신 실행돼서 "❌ 서버 안 켜짐?" 같은 안내를 보여줌. .then()만 있으면 서버 꺼졌을 때 화면이 아무 반응 없이 멈춘 것처럼 보임
자주 묻는 질문
HTML 이랑 JS 를 왜 파일로 나눠요?
HTML=화면 뼈대, JS=동작 — 나누면 찾기·고치기 쉽고 협업에도 좋음, 이게 정석 — <script src="app.js">로 연결
document.getElementById('q') 가 뭐예요?
HTML 에서 id 가 'q' 인 칸을 콕 집어오는 것 — 그 입력칸의 .value 로 사용자가 적은 글을 꺼냄
.then() 이 점점이 이어지는 건 뭐예요?
'응답이 오면 → 그다음 → 또 그다음' 순서 약속 — 답이 도착한 뒤에 차례로 실행되는 단계들
여긴 왜 키(Authorization)가 안 보여요?
화면 코드는 누구나 F12 로 볼 수 있어 키를 넣으면 도둑맞음 — 키는 서버에만, 화면은 서버 주소만 알면 됨