[Project] MyFortune 03

mynoseis3·2024년 1월 20일

practice

목록 보기
13/32
post-thumbnail

챕터 06. 프런트엔드 구현

앞 챕터에서 설정한 백엔드와 통신할 수 있는 UI를 구현하는 챕터

학습 목표

  • 프런트엔드와 백엔드 서버가 통신할 수 있도록 연결하는 방법
  • 챗GPT를 통해 채팅 UI를 구현하는 방법

🛫 첫 화면 만들기

프론트엔드에서 백엔드 서버에게 사용자가 요청한 프롬프트를 전달하고
백엔드에서 전달된 챗GPT의 답변을 화면에 출력해야 함 !

프로젝트의 화면 구조는 html, 디자인은 css, 기능은 javascript로 구현한다.

프로젝트 파일 생성하기

  • vscode 실행 - > 전에 생성해둔 frontend 폴더 불러오기

  • index.html 파일 생성 - > 에디터 영역에 느낌표 입력한 뒤 tap키 누르기
    html 기본 양식이 자동 완성됨 !!

  • 언어 - > "ko" 로 변경

  • 페이지 제목 변경


🛫 백엔드와 통신하기

POST 요청 전송

fetch( )

fetch()는 웹 개발에서 서버와 통신하기 위해 사용하는 함수이다.
GET, POST, PUT, DELETE 등 다양한 유형의 HTTP 요청을 보낼 수 있다.

fetch() 함수를 활용하여 백엔드 서버에 POST 요청을 보내보자 !

  • fetch()를 호출할 자리인 스크립트 영역 잡기
    index.html 안에 있는 body 영역 안에 스크립트 태그 추가

fetch()의 예시 코드 찾기

1. 구글 검색 활용 !!

javascript fetch 검색 - > MDN 웹 문서 페이지 접속
https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch

JSON 데이터 업로드 코드를 통해 예시를 확인할 수 있다.

2. 챗GPT 활용

좀 더 정확한 답을 받으려면 영어로 질문하기 !!
질문이 상세할수록 정확한 답변을 제공할 확률이 높다.
물어보려고 하는 질문의 주요 목적인 자바스크립트 fetch(),
백엔드 서버의 url, post 요청 방식, json 응답, await 함수 등을 포함하여 질문

  • 구글 번역 사용

  • gpt에게서 돌아온 답변 !

  • 챗gpt 코드 복사 - > index.html 파일 스크립트 태그 안에 붙여넣기

  • 테스트를 위해 fetchFortune()를 실행하기 위한 버튼 생성

이렇게 하면 요청하기 버튼을 누를 시
백엔드 엔드포인트(http://localhost:3000/fortuneTell)로 POST 요청을 보낸 뒤
백엔드에서 전달한 JSON 형태의 응답을 response라는 변수로 받아 콘솔에 로그를 출력하게 된다.


🛫 프런트엔드 서버 실행

지금까지 구현한 프런트엔드 코드를 화면으로 확인하기 위해
live server 이용하기

liver server는 vscode에서 제공하는 확장 프로그램으로
로컬 서버를 실행하여 수정한 코드의 결과를 실시간으로 확인할 수 있다.

live server 설치

  • vscode 상단 왼쪽에 있는 확장 버튼 - > live server 검색 - > 설치

  • 코드 에디터 영역에서 우클릭 - > open with live server 클릭
    또는 vscode 하단에 보이는 go live 버튼 클릭

💥 에러 발생

해결

확장 - > Live Server 선택 > 확장 설정 > Use Local IP 체크 !!

하고 다시 실행해보면 오류가 사라지고 생성했던 버튼이 보인다.


🛫 백엔드 서버 실행 & 동작 검증

백엔드 서버 실행 전 코드 수정

index.js 파일 열기 - >

전 챕터에서 임시로 app.get() 했던 부분을 다시 app.post()로 변경하기

그리고 프런트엔드와 백엔드가 JSON 형태의 메시지를 주고 받도록 변경이 필요하다.

응답을 보내는 부분의 res.send() 함수를 res.json() 함수로 변경한 뒤 {"assistant":fortune}과 같이 응답 형식을 json으로 바꾼다.

💫 JSON 데이터 구성

JSON은 데이터를 전송할 때 사용하는 보편적인 양식 중 하나로
중괄호를 사용해서 객체를 표현한다.
객체는 이름(key) - 값(value)의 쌍으로 구성되며
key와 value는 콜론(:)으로 구분한다.
ex)
    {
       "name" : "kim",
       "age" : 20
    }

json 참고 글
https://velog.io/@surim014/JSON%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80


백엔드 서버 실행

  • 코드 수정 후 터미널에서 서버 실행

명령어 : node index.js

  • 라이브 서버로 실행한 브라우저의 개발자도구 열기 (크롬 브라우저 단축키 : f12)

++ 내 pc에서는 책에서와 달리 live server가 edge로 열려서 크롬으로 변경해주었다.

방법 :

File - > Preferences - > Settings - > Extensions - > live server config - > custom browser 변경

요청하기 버튼 클릭 !
콘솔 화면에서 JSON 형태로 된 챗GPT 응답이 출력되는 걸 확인해야 하는데

오류가 났다 헉.

연결이 안 돼서 fetch로 가져오지 못한다는 뜻 같은데
해결한 부분은 api키를 깃허브 올릴 땐 가린다고 다른 문구를 넣어두었던 게 원인이었다.
발급 받았던 api키로 다시 잘 넣어주고 서버 실행 후 버튼을 누르면 결과가 잘 나오고 있다 !


🛫 채팅 UI 구현하기

위까지 진행하면
프런트엔드에서 운세 정보를 백엔드로 요청한 뒤
백엔드에서 응답하는 부분까지 기본적인 구현이 되었다.

이제 프런트엔드에 채팅 UI를 추가하는 작업 진행한다.

UI 참고 방법

  1. 코드펜 활용
  2. 챗GPT 활용

우선 나는 책을 따라서 챗GPT를 활용하는 방법으로 일단 하고
추후에 내가 원하는 스타일로 수정하기로 했다.

채팅 UI 코드 생성

챗GPT에게 질문과 작성했던 index.html 코드를 전달한다.
프롬프트는 문장 + 코드로 구성되며
문장에는 코드를 전달하는 목적을 담고
첨부한 코드 앞에는 어떤 언어로 작성했는지를 알리는 ```html 을 추가로 넣어주자 !

💫 그리고 책에서 배운대로 처음에 gpt 칭찬해줌 !!! 약간 주입식 칭찬 느낌스

마지막에 이런 식으로 질문하고 채팅 UI에 대한 예시 코드를 받았다.

결과 확인하기

  1. 챗gpt에게 받은 코드 복사 - > index.html 파일에 붙여넣기

  2. 제목이랑 멘트들 수정하기

  3. live server 실행해서 확인

결과 화면

추후에 구현 다 끝나고 디자인 바꿔보기 !!

++ ☁️ 코드 관리

  • html, css, js 파일 분리
  • index.html 파일에서 css, js 파일 링크 추가

동작 검증하기

위까지 진행하면 채팅 ui를 구현하고 결과 화면을 확인했다.
이제 사용자가 운세를 물어보면 챗gpt가 답변해 주는 동작을 검증해야 한다!

⚡ 백엔드에서 보내는 JSON 응답 형태를 프론트에서 처리할 수 있는지 점검 필요

백엔드에서 작성했던 값 형태가

{"assistant" : fortune} 이었다.

fortune이라는 운세 값을 가져오기 위해서는 이름(key)인 assistant를 명시해야 한다!

script.js 파일에서
console.log('Response:', data.assistant); 추가

  • 결과 확인
    하려는데 오류가 나서 확인해보니

401 Error - Incorrect API key provided 에러 원인

이 오류에 관해 찾아보니까... 앗차 싶었던게 실수로 api 테스트하다가 내 키를
깃허브에 푸시해버렸다.

오픈된 리포지토리에 올렸던 게 원인이었다.

오마이갓 !!! 그리고 메일 도착

테스트키가 유출되어 바로 비활성화 되었다는 ... !
다행히도 새로 api키를 발급받으면 되는 것 같다.
앞으로 조심 조심 💥

다시 api키를 발급받고 실행해보았다.

어 ??
개발도구에서 확인하면 console에는 답변이 나오고 있지만
ui 화면에서는 서버 응답을 표시하는 부분이 뭔가 잘 못 된 것 같다.

수정 return data; - > return data.assistant;

결과 - > ui 화면에 응답이 잘 뜨고 있다 !

그런데 왜 두번씩 알려주지 ?....
다시 테스트 해보니까
처음 실행할 때 우선 1번 먼저 출력이 되고
물어보면 또 그에 대한 답변으로 2번째의 출력이 되는 것이었다.

그러니까 처음 실행했을 때 먼저 나오는 1번 현상만 제거하면 될 것 같은데
어디서 처음 한 번을 불러오는걸까 ??

서버쪽인가 ???

뭔가 롤 user가 질문하는 부분을 주석해보고 시도하면
처음 나오는 메세지가 달라지고 마음대로 운세를 알려주진 않지만
운세를 물어보면 계속 그전에 대답만 비슷하게 반복한다.

어이 없어서 웃음이 나왔다.
.  ∩
∧∧  |
⊂(
_⊂ノ 미끄덩 ー

시도 - > index.js 에서 messages 설정 부분에 system 컨텐트를 빈 문자열로 두기

-> 실패 - > 질문 후 돌아온 답변

시도 - > 실패

시도 - > 시간을 넣어서 초기 응답 시간 늦추기 - > 실패
이 방법도 결국엔 늦출 순 있지만
사용자가 질문 하기 전에 먼저 실행된다.

알바갈 시간이 벌써 다가와서 일 갔다가 다시 해보자요

++ 지금 내 코드는 책에서의 코드랑 다른 부분들이 있어서
다르게 설정하거나 책대로 똑같이 진행을 해야 할 것 같은데
일단 !! 책에서 나온 예시대로 index.js, script.js 코드를 변경해주고
이후에 완성되고 수정할 때 다시 바꿔보자요 !!

  • index.html 수정

  • script.js 수정

수정 후 시도하면 질문을 했을 때만 답변이 나타나게 잘 작동하고 있는 걸
확인할 수 있었다.


🛫 연속된 채팅 메세지 연결

현재는 post 요청을 받을 때마다 messages라는 고정된 값으로
챗gpt api를 호출하는 형태로 구성되어 있음 !

고정된 값 - >
사용자와 챗gpt의 채팅 데이터를 반영하여 챗gpt api를 호출하게끔 대체해보자 !

sendMessage() 함수

sendMessage() 함수는 script.js 파일에서 정의한
프론트엔드 메세지를 백엔드로 전송하는 역할을 수행하고 있다.

동작 흐름

사용자가 채팅 창에 메세지 입력 후 send 버튼 클릭 - > sendMessage()함수 호출 - > 입력 필드의 messageInput 값을 가져와 message라는 변수에 저장

++ 사용자 메세지를 채팅창에 출력하고 입력 필드 초기화
백엔드 엔드포인트로 지정한 http://localhost:3000/fortuneTell 로 POST 요청을
보낸 뒤 챗gpt의 응답을 받아 채팅 창에 출력한다.


프런트엔드에 채팅 데이터 누적하기

사용자와 챗gpt의 채팅 데이터를 누적되게 처리해보자

⚡ 채팅 데이터의 종류 2가지

  1. 사용자가 입력한 메세지
  2. 챗gpt(assistant)가 입력한 메세지

  • 각 메세지를 담을 배열 변수 추가하기

사용자가 메세지를 입력할 때마다 설정한 userMessages에 값이 추가되게 설정 필요 !

채팅 창에 사용자의 메세지를 출력하고 입력 필드를 초기화하기 전에 값이 추가될 수 있게 초기화 하는 코드 위에 작성해주기

  • userMessages에 사용자의 메세지를 저장하는 코드 추가

  • 챗gpt 응답 메세지를 assistantMessages에 추가


누적된 채팅 데이터 전송하기

이제 누적된 사용자와 챗gpt의 채팅 데이터를 백엔드 서버로 전송해보자

userMessages, assistantMessages 두 변수를 JSON 형태로 만든 뒤
백엔드 서버에 전달하기

기존 script.js 코드에서 설정했던
JSON.stringify() 함수가 백엔드로 보내는 메세지의 본문에 해당하는 부분이므로
자바스크립트 객체를 만들고 이를 JSON.stringify() 함수의 파라미터로 전달하면 된다.

💡 JSON.stringify( ) 함수의 역할

  • 프런트엔드와 백엔드 간 json 형태의 데이터를 주고받을 때 활용한다.
  • 자바스크립트 값이나 객체를 JSON 포맷의 문자열로 변환하는 역할을 수행한다.
  • 클라이언트가 서버로 객체를 전송하려면 객체를 문자열화해하 하는데 이를 직렬화라고 한다.

프런트엔드와 연결하기

프런트엔드에서 보낸 누적된 채팅 메세지가 백엔드 서버로 잘 도착하는지 점검하기

프런트엔드에서 전달된 메세지는 app.post() 함수에서 req라는 파라미터로 받게 되는데
이 값은 JSON 형태이고 본문 내용만 가져와 출력해보자.

index.js

  • 2개의 변수 userMessages, assistantMessages 생성 - >
    JSON 데이터의 본문인 req.body의 값 넣기

테스트 후 콘솔 확인

배열 형태의 누적된 채팅 메세지가 콘솔에서 확인된다.

실행된 sendMessage() 함수의 구조

사용자의 메세지를 userMessages에 저장 - >
백엔드로 POST 요청 - >
백엔드의 응답을 처리한 뒤 챗gpt의 응답을 assistantMessages에 저장

그래서 안녕하세요 1번을 입력했을 때는 백엔드 서버의 콘솔 로그에
사용자의 메세지만 출력되고
안녕하세요 2번을 입력했을 때는
사용자 메세지와 챗gpt의 바로 이전 응답이 누적되어 출력된다.


백엔드 서버에 채팅 데이터 누적하기

챗gpt api 내부에서 messages 객체에 system의 역할과
user와 assistant의 사전 대화를 학습시켰던 부분을
messages라는 별도의 변수로 분리

이렇게 하면 messageg 변수에는 system의 역할과 user와 assistant의 사전 대화가 담긴다.
이후에 프런트엔드에서 전달한 사용자의 메세지와 챗gpt의 응답이 계속해서 누적되어야 한다.

while 반복문을 통해 구현하기

  • while 반복문은 userMessages 또는 assistantMessages의 길이가 0일 때까지
    계속해서 messages에 데이터를 저장한다.
  • 이때 사용자의 메세지 또는 챗gpt의 응답이 빈 값일 경우가 발생할 수 있으므로
    조건문은 ||(OR)로 작성한다.
  • 반복문에서는 차례로 사용자의 메세지, 챗gpt의 응답을 저장한다.

💡 messages를 빈 값으로 초기화시키지 않는 이유

챗gpt에게 원하는 답변을 하도록 유도하려면 system에 역할을 주입시키고
user와 assistant의 대화를 사전에 학습시키는 것이 중요하기 때문에
해당 내용을 기본값으로 넣어야 한다.

사용자와 챗gpt의 채팅 메세지 저장 코드 작성

📌 고려사항 3가지

1. userMessages, assistantMessages 배열에서 데이터를 꺼내는 것
2. 채팅 메세지 문자열을 처리하는 것
3. messages에 JSON으로 값을 저장하는 것
  1. userMessages, assistantMessages 배열에서 데이터 꺼내기
    프런트엔드 코드에서 채팅 데이터 누적을 위해 배열 형태의 변수를 생성했으므로
    백엔드에서도 배열 데이터를 하나씩 꺼내어 messages에 저장해야 한다.
    shift() 함수 활용하기

  2. 채팅 메세지 문자열 처리
    채팅 메세지가 항상 깔끔한 문자열로 전달되지 않고 특히 문자열이 아닌
    숫자 형태로 전달되는 경우를 처리하기 위해
    userMessages, assistantMessage 배열에서 꺼낸 데이터를 String() 으로 감싸준다.
    개행 문자가 포함되어 있을 시 replace() 함수와 정규표현식 패턴을 활용하여 제거

  3. messages에 JSON으로 값 저장하기
    프런트엔드에서 JSON.stringify() 함수를 통해 자바스크립트 객체를 JSON 문자열로
    변환했으므로 백엔드 코드에서는 반대 역할의 함수가 필요하다.
    JSON.parse() 함수를 활용하면 JSON 문자열을 인자로 받아
    자바스크립트 값이나 객체를 생성할 수 있다.

📃 테스트

코드 수정이 위처럼 끝나고 다시 채팅 창에 메세지를 작성하고 전송한다.
정상적으로 응답이 온다면 성공 !!


느낀점

gpt를 항상 한글로만 대화했었는데
영어로 하니까 돌아오는 답변이 전보다 정확성이 올라간 느낌이다.
물론 영알못이라 계속 번역을 하며 해야 해서 시간은 더 걸리지만
그래도 나에게 필요한 좋은 시도인 것 같다.
그리고 json에 대한 것도 자세히 써보진 못했었는데
이 프로젝트에서 json을 조금 다루다보니 모르는 부분들에 대해서
조금씩 익혀가는 느낌이라 좋았다.
근데 ai를 활용해서 웹을 만드니까 기존에 만들던 프로젝트보다
더 신기한 ? 느낌 때문에 또 다른 재밌는 느낌이었다.
책 보고 따라가니까 오류 났을 때 좀 많이 버벅이는 중이긴 한데
그래도 이 끝엔 꼭 결과물을 맺고 한 걸음 더 나아간 내가 될 수 있게
끝까지 잘 마쳐보자 🛩️

profile
웹개발자 꿈나무 꾸준함의 힘을 믿습니다 🚶

0개의 댓글