실시간 채팅 컴포넌트 만들기
v-for를 사용한 메시지 목록, 입력값 바인딩, 제출 시 이벤트 발생, 새 메시지의 하단으로 스크롤하는 기능을 구현합니다.
실시간 채팅 컴포넌트 만들기은(는) CoddyKit의 무료 Vue Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Vue Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Vue Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
목표: 실시간 채팅 상자
작지만 완전한 채팅 컴포넌트를 만들어 보겠습니다. 스크롤되는 메시지 목록을 표시하고, 사용자가 입력해 전송할 수 있으며, 들어오는 메시지를 실시간으로 추가합니다.
이 과정에서 반응형 상태, 수명 주기 훅, DOM 접근을 함께 사용합니다.
메시지 ref
대화 내용을 반응형 배열에 보관합니다. 각 항목은 id, 작성자, 텍스트가 있는 단순한 객체입니다.
import { ref } from "vue"
const messages = ref([
{ id: 1, user: "system", text: "Welcome to the room" },
])입력을 위한 ref
텍스트 상자를 v-model을 사용하는 별도의 ref에 연결합니다. 이 ref에는 전송하기 전에 작성 중인 메시지가 저장됩니다.
// template:
// <input v-model="draft" @keyup.enter="sendMessage" />
const draft = ref("")소켓 수신기 등록
onMounted에서 들어오는 메시지를 구독하고 각각을 배열에 추가합니다. onMounted를 사용하면 처리기를 연결하기 전에 컴포넌트가 준비되었음을 보장할 수 있습니다.
import { onMounted } from "vue"
onMounted(() => {
socket.on("message", (msg) => {
messages.value.push(msg)
})
})메시지 보내기
sendMessage 함수는 작성 중인 내용을 서버로 보내고 입력란을 비웁니다. 빈 문자열은 보내지 않도록 확인합니다.
function sendMessage() {
const text = draft.value.trim()
if (!text) return
socket.emit("send", { text })
draft.value = ""
}목록 렌더링
템플릿은 v-for를 사용해 id를 키로 삼아 messages를 반복합니다. 각 행에는 작성자와 텍스트가 표시됩니다.
<!-- template -->
<div ref="chatBox" class="chat">
<p v-for="m in messages" :key="m.id">
<strong>{{ m.user }}:</strong> {{ m.text }}
</p>
</div>스크롤 문제
새 메시지가 도착하면 사용자는 화면이 아래쪽에 고정되기를 바랍니다. 하지만 배열에 추가한 직후 스크롤하면 새 행이 아직 DOM에 나타나지 않습니다. Vue가 업데이트를 아직 반영하지 않았기 때문입니다.
너무 일찍 스크롤하면 최신 줄을 놓치게 됩니다.
컨테이너에 템플릿 ref 사용하기
템플릿 ref로 스크롤 컨테이너를 가져오면 스크롤 위치를 읽고 설정할 수 있습니다.
import { ref } from "vue"
const chatBox = ref(null)
// template: <div ref="chatBox"> ... </div>nextTick으로 DOM 기다리기
nextTick은 Vue가 보류 중인 DOM 업데이트를 적용한 후 이행되는 프로미스를 반환합니다. 스크롤하기 전에 이를 기다려 새 메시지가 DOM에 존재하도록 하세요.
import { nextTick } from "vue"
async function scrollToBottom() {
await nextTick()
const el = chatBox.value
el.scrollTop = el.scrollHeight
}새 메시지마다 스크롤하기
메시지를 push한 직후 scrollToBottom을 호출하세요. 수신 메시지와 발신 메시지 모두에 적용해야 합니다. scrollTop = scrollHeight를 설정하면 맨 아래로 바로 이동합니다.
onMounted(() => {
socket.on("message", async (msg) => {
messages.value.push(msg)
await scrollToBottom()
})
})전체 흐름
이제 컴포넌트는 메시지를 받고, 반응형 상태를 업데이트하고, nextTick으로 DOM이 업데이트될 때까지 기다린 다음 스크롤합니다. 메시지를 보낼 때도 같은 경로를 따릅니다. 깔끔하고 예측 가능하며 실시간으로 동작합니다.
async function sendMessage() {
const text = draft.value.trim()
if (!text) return
socket.emit("send", { text })
draft.value = ""
await scrollToBottom()
}빠른 확인
채팅 컴포넌트에서 DOM 타이밍을 어떻게 처리하는지 이해했는지 확인해 보세요.
복습
이 강의에서는 실시간 채팅 컴포넌트를 만들었습니다. 핵심 내용은 다음과 같습니다.
- 메시지는 반응형
ref배열에 보관하고, 작성 중인 내용은 별도의 ref에 보관합니다. onMounted에서 소켓 리스너를 등록하고 수신 메시지를push합니다.sendMessage는 작성 중인 내용을emit하고 입력값을 지웁니다.- 템플릿 ref를 사용하고
scrollTop = scrollHeight를 설정하기 전에await nextTick()을 사용하여 최신 메시지가 표시되도록 합니다.
자주 묻는 질문
“실시간 채팅 컴포넌트 만들기” 강의는 무료인가요?
네 — “실시간 채팅 컴포넌트 만들기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Vue Academy 강의 전체를 잠금 해제할 수 있습니다. Vue Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“실시간 채팅 컴포넌트 만들기”에서 뭘 배우나요?
v-for를 사용한 메시지 목록, 입력값 바인딩, 제출 시 이벤트 발생, 새 메시지의 하단으로 스크롤하는 기능을 구현합니다. 브라우저에서 직접 실행하는 실습 코드로 Vue Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Vue Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Vue Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“실시간 채팅 컴포넌트 만들기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Vue Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Vue Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.