08/05/2026 06:52น.

EP.119 สร้างระบบ Real-time Document Editing แบบ Google Docs ด้วย WebSocket และ Go
#WebSocket
#Go
#Real-time Document
#Google Docs
การแก้เอกสารพร้อมกันหลายคน (Collaborative Editing) คือหนึ่งใน use case ที่ท้าทายที่สุดของระบบ Real-time เพราะต้องรับมือกับหลายปัญหาในเวลาเดียวกัน เช่น:
- ผู้ใช้หลายคนพิมพ์พร้อมกัน
- ความขัดแย้งของข้อความ (conflict)
- ความต้องการให้ทุกคนเห็นผลลัพธ์ "ตรงกัน 100%"
- ประสบการณ์การใช้งานที่ลื่นไหล และ latency ต่ำมาก
บทความนี้จะพาคุณสร้างระบบ Real-time Document Editing โดยใช้ Go + WebSocket เป็นแกนหลัก พร้อมแนวคิด Conflict Resolution ที่ใช้จริงในระบบระดับโลก เช่น Google Docs หรือ Notion
🧠 ภาพรวม Architecture ของ Collaborative Editing
โครงสร้างระบบพื้นฐาน:
Client (Browser/App)
→ WebSocket
→ Collaboration Server (Go)
→ Broadcast Update
→ Client ทุกคนใน Document เดียวกัน
องค์ประกอบหลัก:
- Document State – สถานะปัจจุบันของเอกสาร
- Operations / Changes – การแก้ไขของผู้ใช้
- Version / Sequence – ลำดับการเปลี่ยนแปลง
- Conflict Resolution Engine – กลไกจัดการเมื่อเกิดข้อความชนกัน
✍️ 1. รูปแบบข้อมูลการแก้ไข (Edit Operation)
ระบบที่ดีจะไม่ส่ง "ทั้งเอกสาร" ทุกครั้ง แต่จะส่งเฉพาะ "สิ่งที่เปลี่ยน" เช่น:
{
"doc_id": "doc-123",
"user_id": "user-a",
"op": "insert",
"position": 15,
"text": "Hello",
"version": 42
}
Operation ที่ใช้บ่อย:
insert– แทรกข้อความdelete– ลบข้อความreplace– แทนที่ข้อความ
🔄 2. Real-time Sync ด้วย WebSocket
เมื่อผู้ใช้พิมพ์:
- Client สร้าง Operation
- ส่งผ่าน WebSocket
- Server ตรวจสอบ + apply
- Broadcast ไปยังทุกคนในเอกสารเดียวกัน
⚙️ 3. ตัวอย่าง WebSocket Server ด้วย Go
type EditOperation struct {
DocID string `json:"doc_id"`
UserID string `json:"user_id"`
Op string `json:"op"`
Position int `json:"position"`
Text string `json:"text"`
Version int `json:"version"`
}
var documents = make(map[string]string)
var docVersion = make(map[string]int)
func handleEdit(conn *websocket.Conn) {
for {
var op EditOperation
if err := conn.ReadJSON(&op); err != nil {
return
}
current := documents[op.DocID]
updated := applyOperation(current, op)
documents[op.DocID] = updated
docVersion[op.DocID]++
broadcast(op.DocID, updated, docVersion[op.DocID])
}
}
🧩 4. Conflict Resolution คืออะไร?
Conflict เกิดขึ้นเมื่อ:
- ผู้ใช้ 2 คนแก้ไขตำแหน่งเดียวกัน
- Operation มาถึง server ไม่พร้อมกัน
แนวทางการแก้:
- OT (Operational Transformation) – ใช้ใน Google Docs
- CRDT (Conflict-free Replicated Data Type) – ใช้ใน Notion, Figma
- Version Checking & Rebase – สำหรับระบบเริ่มต้น
if op.Version != docVersion[op.DocID] {
// rebase หรือ reject
return
}
👥 5. การจัดการผู้ใช้หลายคนในเอกสารเดียวกัน
- แยก Room ตาม
doc_id - Broadcast เฉพาะผู้ใช้ใน document เดียวกัน
- Track ตำแหน่ง cursor:
{
"type": "cursor",
"user": "user-b",
"position": 22
}
⚡ 6. Performance Optimization
เทคนิคเพื่อให้ระบบทำงานลื่น:
- ส่งเฉพาะ Operation ไม่ส่งทั้ง Document
- ใช้ Debounce ป้องกัน flood
- Batch operation ถี่ ๆ
- ใช้ Binary Protocol (ในระบบใหญ่)
🔐 7. Security ที่ระบบควรมี
- ตรวจสอบสิทธิ์ผู้ใช้ (Access Control)
- ยืนยันตัวตน (Auth)
- Rate Limiting
- ป้องกัน spam / flood
🚀 ท้าให้ลอง!
ลองทำ Mini Project:
- ให้ 2–3 คนแก้เอกสารพร้อมกัน
- Sync ตัวอักษรแบบ Real-time
- แสดง cursor ของคนอื่น
- ใช้ version ในการป้องกัน conflict
หากคุณทำจุดนี้ได้ = คุณเข้าใจ Real-time System ในระดับ Production แล้ว! 🎯
🔮 ตอนถัดไป: EP.120 Whiteboard & Real-time Drawing
ครั้งหน้าเราจะขยับจาก “ตัวอักษร” ไปสู่ “การวาดรูป” ด้วยระบบ Real-time Drawing Sync สำหรับ Whiteboard App เหมือน Miro หรือ FigJam
พร้อมการ sync canvas, mouse position, shape, และ undo-redo แบบทันที! 🎨