Back To Articles

포트폴리오에 채팅 인터페이스 추가하기

Written by Sangmin on July 16, 2024

Article Image
#웹개발 #프론트엔드 #채팅인터페이스

구현 데모

구현 이유

포트폴리오를 작성하면서 너무 정적인 것보다 어느 정도 나를 어필하는 게 좋지 않을까 싶은 생각이 들었다. 그래서 static하게 만들었던 포트폴리오 사이트에 JavaScript로 채팅 인터페이스를 구현하기로 했다. 이는 내가 만들어놓은 생성형 AI를 이용한 챗 API에 POST 요청을 보내고 정보를 받아오는 기능이다.

오랜만에 프레임워크가 아닌 vanilla JavaScript를 써보니 새삼 재미있었다.

주요 구현 내용

먼저 HTML에서 채팅 UI의 기본 구조를 다음과 같이 구성했다:

<div class="chat-container">
  <div class="chat-messages" id="chatMessages"></div>
  <div class="chat-input">
    <input
      type="text"
      id="messageInput"
      placeholder="저에 대해 뭐든지 물어보세요"
    />
    <button id="sendButton">Send</button>
  </div>
</div>

이 구조는 메시지를 표시할 영역과 사용자 입력 필드, 전송 버튼으로 이루어져 있다. 심플하면서도 직관적인 UI를 목표로 했다.

다음으로, JavaScript로 메시지를 동적으로 추가하는 함수를 구현했다:

function addMessage(content, isUser = false) {
  const messageDiv = document.createElement("div");
  messageDiv.className = `message ${isUser ? "user-message" : ""}`;

  const avatar = document.createElement("img");
  avatar.className = "avatar";
  avatar.src = isUser ? "/chat/human.png" : "/chat/bot.png";

  const messageContent = document.createElement("div");
  messageContent.className = "message-content";
  messageContent.textContent = content;

  messageDiv.appendChild(avatar);
  messageDiv.appendChild(messageContent);

  chatMessages.appendChild(messageDiv);
  chatMessages.scrollTop = chatMessages.scrollHeight;
}

이 함수는 사용자와 AI의 메시지를 구분해서 다른 스타일을 적용한다. 아바타 이미지를 추가하여 시각적 구분을 더욱 명확히 했고, 새 메시지가 추가될 때마다 스크롤이 자동으로 내려가도록 구현했다.

마지막으로, 전송 버튼 클릭 시 서버에 질문을 보내고 응답을 받아와 메시지로 추가하는 로직을 구현했다:

sendButton.addEventListener("click", async () => {
  const message = messageInput.value.trim();
  if (message) {
    addMessage(message, true);
    messageInput.value = "";

    try {
      const response = await getChatAnswer(message);
      addMessage(response);
    } catch (error) {
      addMessage("죄송합니다. 답변을 가져오는 데 문제가 발생했습니다.", false);
      console.error("Error fetching chat answer:", error);
    }
  }
});

여기서는 사용자 입력값을 검증하고, 서버 통신 중 발생할 수 있는 오류를 처리하는 로직도 추가했다. 이는 사용자 경험을 향상시키는 데 중요한 요소다.

추가로 구현한 기능들

  1. 입력 필드에 엔터 키로도 메시지를 전송할 수 있게 했다.
  2. 채팅창이 일정 높이를 넘어가면 스크롤이 생기도록 CSS를 조정했다.
  3. 질문자 입장에서 질문을 직접 입력하는게 번거로울 수 있으니 질문이 적힌 버튼을 만들어 누르면 바로 질문에 대한 답을 들을 수 있도록 했다.
  4. 사용자별로 질문 횟수를 제한하는 작업도 진행했다. 몇명이 이 포트폴리오를 보고 이 챗을 사용할지는 모르겠지만 어쨌든 질문을 할때마다 큰 돈은 아니지만 그래도 비용이 계속 발생하는 상황이라서 어쩔 수 없는 조치였다. 대신에 횟수 제한을 넘어가면 기타 앱처럼 로그인하라거나 결제하라는 말 대신 추가 질문은 면접을 통해 해달라고 멘트를 썼다.

마무리

이번 프로젝트를 통해 vanilla JavaScript의 강력함을 다시 한번 체감했다. 프레임워크의 도움 없이도 충분히 동적이고 인터랙티브한 웹 요소를 만들 수 있다는 점이 인상 깊었다. 또한, 비동기 프로그래밍과 DOM 조작에 대한 이해도를 한층 높일 수 있었다.

이 프로젝트를 통해 내 포트폴리오가 단순한 정보 나열을 넘어 방문자와 상호작용할 수 있는 공간이 되었다는 점에서 큰 만족감을 느낀다.

이런 작은 아이디어들을 구현하는게 항상 재밌다. 또 어떤 식으로 포트폴리오를 풍성하게 만들 수 있을지 생각을 해봐야겠다.