Tech Blog

เหตุใดจึงเลือกโครงสร้าง Spring Boot Backend + Vue 3 Frontend แยกกัน และวิธีเชื่อมต่อจริงๆ

by Tech Writer
Vue3 Spring Boot Architecture CORS

บทนำ

เมื่อสร้างแอพ DVD rental สำหรับลูกค้า มีโครงสร้างที่เราตัดสินใจตั้งแต่แรก

  • Backend: Spring Boot (REST API) → Port 8082
  • Frontend: Vue 3 + Vite → Port 5173 (development)

คุณอาจสงสัยว่า “ทำไมไม่ใช้ Thymeleaf?” — ขอตอบตรงๆ ก่อน

เราสร้าง admin panel ด้วย Thymeleaf นั่นเป็นการเลือกที่ถูกต้องสำหรับ admin panel
อย่างไรก็ตาม แอพฝั่งลูกค้ามีข้อกำหนด UX ที่ยากจะทำได้ด้วย Thymeleaf

บทความนี้ไม่ใช่เรื่อง “อันไหนถูกต้อง” แต่เป็นเรื่อง “เราตัดสินใจอย่างไร”


กรณีที่ Thymeleaf เพียงพอ vs. ไม่เพียงพอ

กรณีที่ Thymeleaf เก่ง

สำหรับ admin panel ที่มีวงจร “ส่งฟอร์ม → แสดงผล” ซ้ำๆ Thymeleaf ยอดเยี่ยมมาก

  • Return HTML จากเซิร์ฟเวอร์ในทุก page transition
  • Integration ที่แน่นกับ Spring Security มี CSRF protection อัตโนมัติ
  • Server-side validation และการแสดงข้อผิดพลาดง่าย

Thymeleaf เพียงพอสำหรับ admin panel

ทำไมจึงเลือก Vue 3

มี UX ที่เราต้องการในแอพฝั่งลูกค้า

  1. Feedback การค้นหาและกรองแบบ instant — ประสบการณ์ “ผลลัพธ์เปลี่ยนโดยไม่ต้องกดปุ่มค้นหา”
  2. Cart drawer เปิด-ปิดได้ smooth — Interactions โดยไม่มี page transition
  3. Layout ที่ต่างกันสำหรับ mobile และ desktop — การสลับการแสดงผลแบบ dynamic ตาม viewport
  4. การแชร์ API กับ native app ในอนาคต — REST API เดียวกันสามารถเรียกจากแอพ iOS/Android ได้

สิ่งเหล่านี้ไม่ใช่ “เป็นไปไม่ได้” กับ Thymeleaf แต่ต้องเขียน JavaScript มาก
ถ้าต้องเขียน JS อยู่แล้ว การทำ componentize ด้วย Vue 3 maintainable มากกว่า


โครงสร้างจริง

dvd-rental-customer-app/
  backend/           ← Spring Boot (Port 8082)
    src/main/java/
      api/           ← REST API controllers
      service/       ← Business logic
  frontend/          ← Vue 3 + Vite (Port 5173 ใน development)
    src/
      api/           ← HTTP client สำหรับ backend
      components/    ← Vue components

การตั้งค่า CORS และ Proxy สำหรับ Development

อุปสรรคแรกกับสถาปัตยกรรมแยกคือ CORS
การเรียกจาก frontend (port 5173) ไปยัง backend (port 8082) ทำให้ browser แสดง CORS error

วิธีแก้ไขที่ 1: Dev Proxy ของ Vite (Development)

// vite.config.ts
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8082',
        changeOrigin: true,
      }
    }
  }
})

ใน development Vite forward requests ไปยัง /api ให้ backend ดังนั้น CORS ไม่เกิดขึ้น

วิธีแก้ไขที่ 2: การตั้งค่า CORS ของ Spring Boot (Production)

ใน production frontend และ backend อาจอยู่ต่าง domain หรือ port
ในกรณีนั้น อนุญาต CORS ฝั่ง Spring Boot

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("https://your-frontend-domain.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowCredentials(true);
    }
}

การรวม Production Build

สำหรับ production เรา build Vue ด้วย npm run build และ serve output เป็น static resources ของ Spring Boot

<!-- pom.xml (ตัดมา) -->
<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>npm build</id>
            <goals><goal>npm</goal></goals>
            <configuration>
                <arguments>run build</arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

mvn package คำสั่งเดียวสร้าง jar ที่รวม frontend build ไว้ด้วย


Pain Points จริงกับโครงสร้างแยก

① ต้องเริ่ม 2 กระบวนการระหว่าง Development

เริ่ม Vite แล้วเริ่ม Spring Boot
เมื่อคุ้นเคยแล้วใช้เวลา 10 วินาที แต่ตอนแรกมักลืมอันหนึ่งแล้วสงสัย “ทำไมไม่ทำงาน?”

② Deploy โดยไม่ Build Frontend

อาจเกิดกรณีที่ mvn package รันขณะที่ frontend ยังมี build เก่า
สำคัญมากที่จะกำหนดลำดับอย่างชัดเจนใน CI/CD ให้รัน npm run build ก่อนเสมอ

③ Type ไม่ตรงกัน

Response types จาก backend และ TypeScript types ใน frontend มีแนวโน้มแยกออกจากกัน
ต้องแชร์คำจำกัดความ schema ด้วย OpenAPI หรือมีนิสัยในการจัดแนวให้ตรงสม่ำเสมอ


สรุป

แง่มุมThymeleafVue 3 + REST API
ความเร็ว development เริ่มต้นเร็วค่อนข้างช้า (ต้องตั้งค่า)
UI แบบ interactiveยากจุดแข็ง
แชร์ API (mobile ฯลฯ)ไม่ได้ได้
Spring Security integrationง่ายต้องทำ implementation เอง
ความซับซ้อนในการ deployง่ายค่อนข้างซับซ้อน

Thymeleaf สำหรับ admin panel, Vue 3 สำหรับ customer-facing app
การแบ่งนี้เป็นตัวเลือกที่เหมาะสมที่สุดสำหรับโปรเจกต์นี้
สิ่งสำคัญไม่ใช่ “อันไหนดีกว่า” แต่คือ “เลือกตามสิ่งที่คุณต้องการสร้าง”


แผนที่บทความของ Series นี้

การสร้างแอพ DVD Rental สำหรับผู้ใช้ควบคู่กับหน้าจัดการ — ภาพรวมโครงสร้าง Vue 3 + Spring Boot

ส่งข้อความได้ตามสบาย

กรุณาส่งข้อความ หากมีคำปรึกษาด้านเทคนิค ความคิดเห็น หรือคำถาม