
하고싶던 프로젝트를 구상하던 중 챗지피티가 대답을 해준다면? 이라는 생각이 떠올라서 찾다가
chat GPT API가 있다는 걸 알게되었다. 해서 해당 API를 사용하여 원하는 웹페이지를 만들고자 하였다.
CHAT GPT API 에서 사용 가능 하며, 챗지피티 어플리케이션에 직접 접속해서 사용할 수 있지만 API 사용은 유료이며, 대화에 사용된 토큰(Tokens)의 크기(1,000 토큰당 $0.002)에 따라 과금된다.
처음 Open AI를 가입하면 체험용 토큰을 주는데, 나는 이미 가입한지 오래되어 따로 충전을 하고 사용했다.
스스로 처음부터 디자인 및 빌드를 혼자서 한 첫번째 프로젝트였어서 홀로 다 찾아보고 하는 경험을 쌓을 수 있었던것 같다
앞으로도 이런 간단한 사이드 프로젝트를 통해 강의에서 배울 수 없었던 새로운 라이브러리, 새로운 API들을 알아가면서 지식의 세계를 넓히는 프론트엔드가 되고싶다!
이때까지 CHAT GPT API가 있는지도 몰랐는데, 홈페이지에 꽤나 손쉬운 사용법이 나와있어서 쉽게 사용할 수 있었다.
Quick Start 에 나와있는대로 손쉽게 다운로드 해서 사용하면 됐다.
npm install openai
npm 을 통해 설치해서
import OpenAI from "openai";
const openai = new OpenAI();
이렇게 가져오는 방법을 알려주는데,,,
나는 이 방법을 몰랐어서 fetch로 가져왔다.
fetch("https://api.openai.com/v1/chat/completions")
해당 형태로 가져와서 옵션값을 설정해서 GPT를 구축했다.
일단 됐으니까!
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content: "You are a knowledgeable assistant and must only provide answers related to medical information. Always include the following disclaimer at the end of your responses: 약과에서 제공되는 정보는 일반적인 건강 정보로, 의학적 조언이나 진단을 대신하지 않습니다.",
},
...messageHistory,
{ role: "user", content: questionText },
],
max_tokens: 300,
다음으로는 해당 옵션값만 설정해주면 끝!
headers에서는 내가 주고받는 데이터 (json, apiKey) 값을 넣어주고
body에서는 옵션값을 설정할 수 있다.
model로는 gpt-4o-mini를 사용했고 ( gpt-3.5-turbo를 쓰니 답변이 너무 퀄리티가 좋지 못했다 ㅠ)
message에서는 gpt 대답의 기본셋팅을 구축할 수 있었다.
나는 의약품 검색 사이트를 만들었기 때문에 의약품 및 병에 관련된 질문에만 대답하도록 설정했고, 항상 대답마다 특정 문장을 추가하도록 설정했다.
또한 사용자의 질문을 어디서 받아올지 설정 할 수도 있다.
const [talk, setTalk] = useState([
{ type: "question", message: firstQuestionInput },
]);
해당 state를 만들어서 대답을 했는데, 해당 페이지가 렌더링되면 첫번째 질문은 recoil로 관리된 질문이 항상 같이 들어오기때문에, 해당 state를 선언했다.
const messageHistory = talk.map((item) => ({
role: item.type === "question" ? "user" : "assistant", content: item.message,
}));
또한 gpt에게 질문을 하기전 해당 배열에 들어온 질문의 type을 확인 후 type: question은 user로, type: answer는 assistant로 변환해서 질문을 던졌다.
useEffect(() => {
const getAnswer = async () => {
const lastMessage = talk[talk.length - 1];
if (
lastMessage?.type === "question" && !loading && lastMessage?.message.length > 0
) {
const answer = await getGPTResponse(lastMessage.message);
setTalk((prev) => [...prev, { type: "answer", message: answer }]);
}
};
getAnswer();
}, [talk]);
또한 talk 배열에 사용자의 질문이 추가 되면, getGPTResponse을 다시 호출해서 질문을 던지고 답변을 할 수 있도록 useEffect를 한번 더 돌려주었다.

해당형태로 지피티가 대답할 수 있도록 구현 완료!
자세한 내용은 해당 포스팅에 나와있다
공공데이터포털 cors 정책 위반 우회하기 (Node.js)
위에 포스팅처럼 열심히 서버를 만들어서 dev 환경에서 사용했으나
AWS에서 배포하는 단계에서 뭔가 문제가 생겼는지 https로 배포가 되지않아 dev 환경에서는 node 서버로 데이터를 가져올 수 있었으나 배포 후에는 해당 node서버로 데이터를 가져올 수 없는 문제가 발생하였다.
그래서 결국 배포 데이터는 node가 아닌 해당 프로젝트와 공공데이터 포털을 바로 연결해서 해결은.. 했다..
위와 이어지는 내용인데 초반 cors 정책을 우회하고자 node 서버로 우회를 했을때는 node.js로 설정해서 해당 공공데이터 데이터를 수신했다.

약에 대한 정보를 수신하기 위해 식품의약품안저처_의약품개요정보(e약은요) 라는 해당 OPEN API를 활용했고, 해당 데이터를 수신해서 검색 및 상세정보 조회가 가능하도록 설정하였다.
app.get("/api/drugs", async (req, res) => {
try {
const response = await fetch(
`${apiUrl}?serviceKey=${apiKey}&pageNo=1&numOfRows=100&type=json`
);
const allData = await response.json();
res.json(allData.body.items);
} catch (error) {
console.error(error);
res.status(500).send("Internal Server Error");
}
});
하지만 배포하면서 react 배포서버와 바로 연결하기 위해서 fetch로 가져오는 함수로 변경하였다.
export const getAllDrugs = async () => {
try {
const response = await fetch(
`${API_URL}?serviceKey=${API_KEY}&pageNo=1&numOfRows=100&type=json`
);
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching drugs:", error);
throw error;
}
};


실제로 구현한 웹사이트 주소도 살며시..
약과 함께하는 건강한 생활, 약과
물론 혼자서 하는 프로젝트라 부족한 점은 매우 많았지만 몇가지만 뽑자면
성능최적화의 부재
물론 엄청난 데이터를 가져오고 로딩시간이 오래 걸리는 프로젝트는 아니었지만 (따라서 엄청난 로딩이 걸리지는 않는다) 그래도 어느정도의
새로운 라이브러리 및 기술에 대한 장벽
새로운 기술일수록 한국말로 블로그에 잘 정리된 경우가 적기때문에 외국 사이트나 외국 글에 대한 장벽을 좀 줄여야겠다는 생각이 들었다.
프론트엔드 혼자서만 구현할 수 없는 서비스가 많기 때문에 다양한 라이브러리, 다양한 API를 통해 새로운 서비스, 새로우 웹을 구현해서 만들어 보고 싶다.
지금 생각하고 있는 서비스는 업비트에서 제공하는 실시간 코인정보 API를 통해 코인 사이트를 구현하는 것이 목표!
또한 새로운 기술, 새로운 라이브러리에 겁먹지말고 새롭게 사용해보고싶다.