# Symfony Live Components와 UX 3.0: JavaScript 없이 리액티브 앱 구축하기 (2026년)
> Symfony Live Components와 UX 3.0을 활용하여 JavaScript 프레임워크 없이 리액티브 인터페이스를 구축하는 방법을 다룹니다. LiveProp, LiveAction, 폼 처리, 지연 로딩, URL 바인딩을 포함한 완전한 튜토리얼입니다.
- Published: 2026-05-10
- Updated: 2026-05-10
- Author: SharpSkill
- Tags: symfony, live components, symfony ux, php, twig, reactive ui
- Reading time: 10 min
---
Symfony Live Components는 PHP와 Twig만으로 리액티브하고 실시간적인 사용자 인터페이스를 구현하는 기능입니다. 2026년 4월에 릴리스된 [Symfony UX 3.0](https://symfony.com/blog/symfony-ux-3-0-0-released)에서는 2.x의 모든 지원 중단 기능이 제거되었으며, 최소 요구 사항이 PHP 8.4 및 Symfony 7.4로 상향되었습니다. 또한 4개의 폐기된 패키지가 제외되어 역대 가장 경량화된 UX 툴킷이 되었습니다.
> **Live Components란?**
>
> Live Components는 모든 Twig 컴포넌트를 상태를 유지하는 인터랙티브 요소로 변환합니다. 사용자 상호작용에 따라 서버 측에서 재렌더링이 이루어지며, JavaScript를 작성할 필요가 전혀 없습니다. 데이터 바인딩, 액션, 유효성 검사, 폼 처리가 모두 PHP 내에서 처리됩니다.
## Symfony UX 3.0과 Live Components 설정
설치에는 Symfony 7.4 이상, PHP 8.4 이상, 그리고 프론트엔드 에셋을 위한 AssetMapper 또는 Webpack Encore가 필요합니다.
```bash
# terminal
composer require symfony/ux-live-component
# With AssetMapper (recommended for Symfony 7.4+)
php bin/console importmap:require @symfony/ux-live-component
# Verify installation
php bin/console debug:twig --filter=component
```
AssetMapper는 Node.js, Webpack 또는 기타 빌드 단계 없이 JavaScript를 제공합니다. Live Components를 구동하는 Stimulus 컨트롤러는 자동으로 로드됩니다.
## LiveProp을 활용한 리액티브 검색 컴포넌트 만들기
사용자가 입력할 때마다 결과를 필터링하는 검색 바를 JavaScript 없이 구현할 수 있습니다. `#[LiveProp]` 속성은 프로퍼티를 상태 유지(stateful)로 표시하며, 암호화된 URL 안전 토큰을 통해 재렌더링 간에 값을 유지합니다.
```php
query) < 2) {
return [];
}
return $this->productRepository->search(
query: $this->query,
category: $this->category === 'all' ? null : $this->category,
limit: 20,
);
}
}
```
해당 Twig 템플릿에서는 `data-model`을 사용하여 입력 필드를 프로퍼티에 바인딩합니다.
```twig
{# templates/components/ProductSearch.html.twig #}
{% for product in this.products %}
{{ product.name }}
{{ product.price|format_currency('EUR') }}
{% else %}
{% if query|length >= 2 %}
No results for "{{ query }}".
{% endif %}
{% endfor %}
```
`debounce(300)` 수정자는 마지막 키 입력 후 300밀리초를 대기한 뒤 요청을 전송합니다. 리스트 항목의 `key` 속성은 효율적인 DOM 모핑을 가능하게 하여 변경된 요소만 업데이트됩니다.
> **LiveProp의 URL 바인딩**
>
> LiveProp에서 `url: true`를 설정하면 프로퍼티 값이 쿼리 파라미터로 브라우저 URL에 동기화됩니다. 단 하나의 속성으로 북마크 가능하고 공유 가능한 검색 결과를 구현할 수 있습니다.
## LiveAction으로 사용자 액션 처리하기
데이터 바인딩 외에도, `#[LiveAction]`은 PHP 메서드를 프론트엔드에서 호출 가능한 액션으로 노출합니다. 인자는 `#[LiveArg]`를 통해 전달됩니다.
```php
cartService->add($productId, $quantity);
$this->items = $this->cartService->getItems();
// Notify other components on the page
$this->emit('cart:updated', [
'count' => count($this->items),
]);
}
#[LiveAction]
public function removeItem(#[LiveArg] int $itemId): void
{
$this->cartService->remove($itemId);
$this->items = $this->cartService->getItems();
$this->emit('cart:updated', ['count' => count($this->items)]);
}
public function getTotal(): float
{
return array_sum(array_map(
fn(CartItem $item) => $item->getPrice() * $item->getQuantity(),
$this->items,
));
}
}
```
템플릿에서는 `live_action()` 헬퍼 또는 `data-action` 속성을 사용하여 액션을 트리거합니다.
```twig
{# templates/components/ShoppingCart.html.twig #}
```
`emit()` 메서드는 페이지 내 다른 Live Components에 이벤트를 브로드캐스트합니다. 예를 들어, 장바구니 배지 컴포넌트는 `#[LiveListener('cart:updated')]`로 리슨하여 전체 페이지를 새로고침하지 않고도 카운트를 업데이트할 수 있습니다.
## JavaScript 없는 실시간 폼 유효성 검사
Live Components는 [Symfony Forms](https://symfony.com/doc/current/forms.html)와 직접 통합됩니다. `ComponentWithFormTrait`는 폼 상태, 유효성 검사 오류, 제출을 컴포넌트 라이프사이클에 연결합니다.
```php
createForm(RegistrationType::class, $this->initialFormData ?? new User());
}
#[LiveAction]
public function save(EntityManagerInterface $em): mixed
{
// Submits + validates — re-renders with errors if invalid
$this->submitForm();
$user = $this->getForm()->getData();
$em->persist($user);
$em->flush();
$this->addFlash('success', 'Account created.');
return $this->redirectToRoute('app_login');
}
}
```
```twig
{# templates/components/RegistrationForm.html.twig #}
```
유효성 검사 오류는 사용자가 필드 간에 이동할 때 인라인으로 표시됩니다. `data-model`의 `on(change)` 수정자가 blur 시 재렌더링을 트리거하여 Symfony Validator의 제약 조건 메시지가 즉시 표시됩니다.
## 성능을 위한 지연 로딩과 레이지 로딩
대시보드, 분석 차트, 긴 목록 등 무거운 컴포넌트는 지연 렌더링의 이점을 누릴 수 있습니다. 초기 페이지 로드를 차단하는 대신 컴포넌트가 플레이스홀더를 렌더링하고, 페이지가 준비된 후 AJAX로 콘텐츠를 가져옵니다.
```php
analytics->getMetrics($this->period);
}
}
```
```twig
{# Parent page: load the dashboard after the page renders #}
{# Or load when scrolled into view #}
```
컴포넌트 템플릿 내의 플레이스홀더 매크로는 실제 콘텐츠가 로드되는 동안 사용자에게 표시할 내용을 정의합니다.
```twig
{# templates/components/AnalyticsDashboard.html.twig #}
{% endmacro %}
```
`loading="defer"` 모드는 페이지 로드 직후 AJAX 요청을 발행합니다. `loading="lazy"` 모드는 IntersectionObserver를 사용하여 컴포넌트가 뷰포트에 스크롤될 때만 요청이 발행됩니다. 두 방식 모두 초기 페이지 응답을 빠르게 유지합니다.
> **UX 3.0에서 CSRF 제거**
>
> Symfony UX 3.0은 Live Components의 CSRF 토큰을 동일 출처/CORS 보호로 대체했습니다. `#[AsLiveComponent]`의 `csrf` 인자는 더 이상 존재하지 않습니다. 서버가 동일 출처 정책을 적용하고 있는지 확인해야 합니다.
## 이벤트를 통한 컴포넌트 간 통신
Live Components는 이벤트 시스템을 통해 통신합니다. 자식 컴포넌트가 이벤트를 발행하고, 부모(또는 형제) 컴포넌트가 리슨하여 반응합니다.
```php
count = $cartService->getItemCount();
}
// Automatically re-renders when ShoppingCart emits 'cart:updated'
#[LiveListener('cart:updated')]
public function onCartUpdated(#[LiveArg] int $count): void
{
$this->count = $count;
}
}
```
이 패턴을 통해 컴포넌트 간 결합도가 낮아집니다. ShoppingCart 컴포넌트는 CartBadge를 직접 참조하지 않으며, 이벤트 버스가 연결을 처리합니다.
## Symfony UX 3.0의 주요 변경 사항
UX 3.0은 정리(cleanup) 릴리스입니다. 2.x에서 지원 중단 경고 없이 실행되던 애플리케이션은 최소한의 수정으로 업그레이드할 수 있습니다.
| 변경 사항 | 이전 (2.x) | 이후 (3.0) |
|--------|-------------|-------------|
| CSRF 보호 | `#[AsLiveComponent]`의 `csrf: true` | 동일 출처/CORS (자동) |
| Twig CVA 함수 | `cva()` | twig/html-extra 3.12+의 `html_cva()` |
| 컴포넌트 기본 설정 | 선택 사항 | `twig_component.defaults` 필수 |
| 제거된 패키지 | Swup, LazyImage, Typed, TogglePassword | 네이티브 API 또는 UX Toolkit |
| PHP 요구 사항 | 8.1 이상 | 8.4 이상 |
| Symfony 요구 사항 | 6.4 이상 | 7.4 이상 |
2.x 사이클 동안 도입된 [UX Toolkit](https://symfony.com/blog/symfonyux-2-32-0-released)은 Shadcn UI 또는 Flowbite 4.0으로 스타일링된 프리빌트 UI 컴포넌트(Button, Dialog, Card, Table, Pagination)를 제공하여 제거된 패키지의 빈자리를 채웁니다.
[Symfony 면접 준비](/technologies/symfony/interview-questions/events-subscribers)를 하고 있다면, Live Components와 이벤트 시스템에 대한 이해는 시니어급 포지션에서 갈수록 중요해지고 있습니다. [Symfony 면접 질문 가이드](/blog/symfony/symfony-interview-questions)에서는 이 실무 지식과 잘 어울리는 기초 주제를 다루고 있습니다.
## 결론
- Live Components는 CRUD 중심의 Symfony 애플리케이션 대부분에서 JavaScript 프레임워크의 필요성을 제거합니다. 데이터 바인딩, 액션, 유효성 검사, 폼 처리가 모두 PHP와 Twig에서 이루어집니다
- `#[LiveProp(writable: true, url: true)]`는 단 하나의 속성으로 북마크 가능하고 공유 가능한 상태 유지 인터페이스를 생성합니다
- 지연 로딩과 레이지 로딩(`loading="defer"` / `loading="lazy"`)은 무거운 컴포넌트가 비동기적으로 렌더링되는 동안 초기 페이지 로드를 빠르게 유지합니다
- UX 3.0은 CSRF 토큰을 폐지하고 동일 출처/CORS 보호를 도입했습니다. 움직이는 부품이 적은 더 단순한 보안 구조입니다
- 이벤트 시스템(`emit` / `#[LiveListener]`)은 전역 상태 관리 없이 컴포넌트 간 느슨한 결합 통신을 가능하게 합니다
- API 구축에는 백엔드 중심 아키텍처를 위해 [Symfony 7의 API Platform](/blog/symfony/symfony-7-api-platform-best-practices)을 보완적으로 활용할 수 있습니다
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/ko/blog/symfony/symfony-live-components-ux-3-reactive-apps-without-javascript