스크립트
00:00:00Solid 2가 드디어 출시되었으며, 이번 업데이트는 규모가 매우 큽니다.
00:00:03프레임워크에서 비동기 처리 방식을 완전히 개편하여 일등 시민(First-class) 기능으로 만들었으며,
00:00:07데이터 패칭, 로딩 상태, 반응성 측면에서 훨씬 더 뛰어난 개발자 경험을 제공합니다.
00:00:11이펙트(Effects)가 변경되었고, 스토어와 경계(Boundaries)도 바뀌었으며,
00:00:14수많은 SolidJSX 구문이 변경되었습니다. 그것만으로는 부족하다는 듯이,
00:00:17러스트(Rust)로 작성되어 이전보다 20배 이상 빠른 새로운 컴파일러 도구 체인이 추가되었고,
00:00:21플러그인에는 이제 start 모드가 기본 포함되어 Solid Start가 아예 필요 없게 되었습니다.
00:00:25사실 몇 주 전에 Solid Start 2가 출시되었지만,
00:00:27이번 업데이트를 통해 이제 이별을 고할 수 있게 되었습니다.
00:00:29이번 업데이트 전체가 프론트엔드 프레임워크의 진정한 혁신처럼 느껴지므로,
00:00:32어떤 점들이 바뀌었는지 자세히 살펴보겠습니다.
00:00:39Solid 2의 가장 큰 핵심은 비동기가 이제 반응형 그래프의 일부가 되었다는 점입니다.
00:00:44Solid 1에서는 비동기 데이터를 관리하기 위해 특별한 create resource 프리미티브를 사용해야만 했지만,
00:00:48여기서 fetch user로 하는 것처럼 말이죠. 그리고 그 리소스로부터,
00:00:50최신 해결된 값, 로딩 상태, 에러에 접근할 수 있었습니다.
00:00:54하지만 Solid 2에서는 이 과정이 훨씬 간단해집니다.
00:00:56이제 연산(Computations)이 직접 프로미스(Promises)를 반환할 수 있으므로, create memo 내부에서
00:00:59fetch user를 사용할 수 있습니다. 이제 user는 단순히 비동기인 메모(memo)일 뿐이며,
00:01:03하위의 모든 요소가 이를 자연스럽게 이해합니다.
00:01:05create resource는 제거되었습니다.
00:01:07눈치채셨겠지만 서스펜스 경계(suspense boundary)도 loading으로 대체되었습니다.
00:01:10모든 경계들이 새롭게 개편되어,
00:01:12suspense가 이제 제거되고 loading 경계를 사용하게 됩니다.
00:01:15데이터가 아직 없을 때(즉, 첫 결과가 없을 때) 폴백(fallback)을 렌더링하며,
00:01:18그 이후에는 새로운 값이 가져와지고 있는지 추적하기 위해 isPending을 사용할 수 있습니다.
00:01:22에러 경계(Error boundary)도 erud로 대체되었는데,
00:01:24대체로 내부적인 이름 변경 및 개편에 가깝고,
00:01:27suspense list 역시 reveal로 변경된 것도 마찬가지입니다.
00:01:30이러한 예시들만 보면 비동기 작업 관련 변경이 단순한 이름 변경처럼 보일 수 있지만,
00:01:34내부적으로는 프레임워크에서 비동기를 다루는 완전히 새로운 접근 방식입니다.
00:01:37Ryan이 레딧(Reddit)에 이를 설명하기 위한 다이어그램을 게시했으니,
00:01:40완벽한 심층 분석을 위해 해당 글을 읽어보시는 것을 추천합니다.
00:01:42하지만 요약하자면, 대부분의 프레임워크는 프로미스를 소비하는 것과 동시에 서스펜스 경계로 UI를 차단합니다.
00:01:47React의 use()나 Svelte의 await처럼 말이죠. 하지만 Solid 2는 생성 시점에 프로미스를 그래프로 소비하고
00:01:52실제로 값이 읽히는 곳에서 차단(blocking)을 수행합니다.
00:01:54React에서 이를 확인할 수 있습니다. 부모 컴포넌트에 모든 프로미스가 있고 리플레이를 누르면,
00:01:59요청이 UI를 차단하고 있기 때문에 첫 번째 서스펜스 경계 폴백만 계속 보게 되며,
00:02:03모든 요청이 끝날 때까지 기다리게 됩니다.
00:02:05프로미스를 전달하거나 컴포넌트를 함께 배치하는 등의 다른 방법으로 이를 해결할 수 있지만,
00:02:09항상 개발자 경험(DX)과 사용자 경험(UX) 사이의 타협이 필요했습니다.
00:02:12Solid 1도 이를 부분적으로 해결하긴 했습니다. 여기서 create resource로 모든 프로미스가 소비되고 있으며,
00:02:16리플레이를 누르면 데이터가 읽힐 때 사용자 프로필이 표시되고,
00:02:20데이터가 준비될 때까지 팀 스켈레톤이 표시됩니다. 팀 컴포넌트도 마찬가지입니다.
00:02:24따라서 데이터가 준비되면 UI가 즉시 업데이트되므로 사용자 경험 문제는 해결되었습니다.
00:02:28하지만 Solid 1의 문제는 리소스로부터 얻은 값을 다룰 때 널(null) 및 언디파인드(undefined) 체크를
00:02:32곳곳에 흩뿌려야 했다는 점입니다. Solid 2는 이 모든 것을 해결합니다.
00:02:36create memo로 프로미스를 소비하면 프로미스가 즉시 그래프에 들어가고,
00:02:40그 시점부터는 프로미스가 아닌 순수 값만 다루게 됩니다. 따라서 이 모든 중첩된 컴포넌트들은
00:02:44순수하게 프리젠테이셔널(Presentational)해질 수 있으며, 값에 더 이상 undefined 상태가 존재하지 않습니다.
00:02:49따라서 코드에서 그러한 체크들을 모두 제거할 수 있고, 동시에 loading 경계를 사용하여
00:02:52Solid가 값이 준비되었는지 여부를 처리하도록 할 수 있습니다. 이를 통해 최고의 사용자 경험을 얻을 수 있으며,
00:02:56UI가 준비될 때 표시되면서도 코드가 더 깔끔해지므로 개발자 경험도 훨씬 좋아집니다.
00:03:00구독을 하시면 이와 같은 AI 및 개발 소식을 최신으로 받아볼 수 있어 개발자 경험이 훨씬 좋아집니다.
00:03:04지금까지 비동기에 대해 언급한 내용은 모두 '읽기'에 관한 것이었지만, '쓰기'는 어떨까요?
00:03:08낙관적 업데이트(Optimistic updates)를 수행하는 방식에도 일부 변경 사항이 있기 때문입니다.
00:03:13Solid 1에서는 낙관적 업데이트에 리소스 mutate 함수를 사용했지만, 이는 실제로 제거되었으며
00:03:18action, create optimistic, create optimistic store를 이용한 훨씬 멋진 흐름으로 대체되었습니다.
00:03:23할 일(to-do) 앱에 낙관적 업데이트를 적용하고 싶다면, 먼저 서버 페치인 진실의 원천(source of truth)으로
00:03:27낙관적 스토어를 생성한 다음, 할 일 추가 액션을 만들고,
00:03:31로컬 스토어에 할 일을 즉시 추가하고 저장 API를 실행한 뒤, 완료되면 서버에서 새로고침을 호출합니다.
00:03:35Action은 뮤테이션에 라이프사이클을 부여하므로, 낙관적 스토어에 만드는 로컬 변경 사항은
00:03:40이 액션의 수명 동안에만 존재합니다. 즉, 이 API 호출에서 에러가 발생하면
00:03:44낙관적 오버라이드가 사라지고 UI가 신뢰할 수 있는 원래 값으로 돌아간다는 뜻입니다.
00:03:49따라서 이제 자동 롤백 기능이 제공되는데, 이는 Solid 1에서 수동으로 처리하던 것에 비해 꽤 멋진 변화입니다.
00:03:52Solid 개발자분들이라면 낙관적 스토어에 대한 특별한 점을 눈치채셨을지도 모릅니다.
00:03:56여기서 직접 변형(mutated)할 수 있는 초안(draft)을 제공했다는 점이죠.
00:04:01이러한 변경 사항은 모든 스토어에 걸쳐 적용되었으므로,
00:04:04더 이상 produce 함수가 필요 없습니다. create mutable과 함께 제거되었으며, 이제 기본 동작이 되었기 때문입니다.
00:04:08하지만 예전 방식을 원한다면 여전히 store path 헬퍼를 사용할 수 있습니다.
00:04:12이펙트로 넘어가보면, 이 부분에서도 큰 변화가 있었습니다. Solid 1에서는 이펙트가
00:04:17읽는 모든 것을 추적하는 것과 사이드 이펙트를 동시에 수행하는 하나의 함수였습니다.
00:04:21Solid 2는 이를 둘로 나누어 의존성 추적과 사이드 이펙트를 분리합니다.
00:04:26첫 번째 함수는 값을 계산하고 추적되며, 두 번째 함수는 추적되지 않고(untracked) 값을 받아.
00:04:30실제 작업을 수행합니다. 이를 통해 무엇에 의존하는지와 그에 대해 무엇을 할지 사이의 분리가 이루어지며.
00:04:34이는 계산 함수에서 처리되기 때문에 on 함수의 필요성을 대체합니다.
00:04:39그리고 on 함수가 가지고 있던 defer 옵션을 원한다면, 이제 이펙트의 옵션으로 간단히 지정할 수 있습니다.
00:04:43이와 함께 create computed도 제거되었습니다. 파생된 값이 필요하면 메모를 사용하고.
00:04:47사이드 이펙트가 필요하면 분할된 이펙트(split effect)를 사용하면 되기 때문입니다. 이펙트 정리(cleanup)와 관련해서도.
00:04:52변화가 생겼습니다. 함수 본문 내부에서 on cleanup을 호출하는 대신,
00:04:56apply 함수가 단순히 정리 함수를 반환하는 방식(React의 접근 방식과 유사함)으로 바뀝니다.
00:05:01on mount 함수에도 동일한 변경이 적용되어 이제는 on settled가 되었습니다. 콜백에서 정리 함수를 반환하면 됩니다.
00:05:05on settled는 단순히 컴포넌트가 마운트될 때가 아니라 그 하위의 모든 비동기 작업이 해결되었을 때 실행됩니다.
00:05:10시그널(Signals)의 경우 사용하는 방식 자체는 크게 달라지지 않았지만, 내부적인 차이가 있습니다.
00:05:14Solid 2는 쓰기 작업을 스테이징하고 다음 마이크로 태스크에서 커밋하므로,
00:05:18시그널을 설정한 바로 다음 줄에서 읽으면 이전 값을 얻게 됩니다.
00:05:22하지만 당장 값이 필요하다면 flush 함수를 사용하여 강제로 값을 밀어 넣을 수 있습니다.
00:05:26이러한 변경으로 인해 연속된 쓰기 작업은 기본적으로 이미 하나의 배치(batch)를 공유하므로,
00:05:30더 이상 감쌀 필요가 없어 batch가 제거되었습니다. 다루고자 했던 비동기 및 반응성 변경 사항은.
00:05:34대략 이 정도면 된 것 같으니, HTML에 더 가까운 DOM 모델을 목표로 개편된 JSX를 살펴보겠습니다.
00:05:39클래스부터 시작하면, class list는 이제 사라졌습니다.
00:05:44대신 이제 class 속성 자체가 문자열, 객체, 배열을 모두 허용합니다. 조건부 스타일의 경우.
00:05:48간단히 객체를 사용할 수 있으므로 더 이상 문자열 결합, filter, join 트릭이 필요 없습니다.
00:05:52속성(Attributes)도 동일한 처리를 받아 attribute 및 bool 접두사가 사라졌으며.
00:05:56표준 속성을 그대로 작성하고 불리언은 일반 HTML 존재 및 부재 규칙을 따르므로,
00:06:00값이 truthy일 때만 속성이 나타납니다. on 및 on capture도 사라졌으며.
00:06:04이제 카멜 케이스 이벤트 프로필을 사용하고, 네이티브 리스너 옵션이 필요하면 ref 콜백과 addEventListener를 사용하세요.
00:06:08디렉티브의 경우 유저 네임스페이스가 사라졌고, ref 콜백과 디렉티브 팩토리로 대체되었습니다.
00:06:13그리고 ref는 이제 배열을 받으므로 래퍼 함수 없이도 동일한 요소에 여러 디렉티브를 스택할 수 있습니다.
00:06:17JSX에 머물러서, 리스트도 단순화되었습니다. Solid 1에서는.
00:06:23배열을 렌더링하기 위해 for와 index라는 두 가지 컴포넌트가 있었습니다. for는 키가 지정되어 각 항목이 아이덴티티로 매칭되었고.
00:06:28index는 그 반대로 위치(position)로 매핑되었습니다. 하지만 Solid 2에서는 index가 제거되어.
00:06:32이제 for만 남았지만, keyed prop을 false로 설정하면 해당 index 동작을 다시 구현할 수 있습니다.
00:06:37그리고 JSX 변경 사항의 마지막으로 repeat이라는 새로운 컴포넌트도 생겼습니다. 배열을 받는 대신.
00:06:42이 컴포넌트는 개수로 렌더링하며, 시작 인덱스와 개수를 주면 각 행이 스토어에서 자신의 슬롯을 읽으므로.
00:06:47하나의 행을 업데이트해도 다른 것은 전혀 건드리지 않습니다. 프레임워크 관점에서의 주목할 만한 변경 사항은 드디어 이게 전부인 것 같으니,
00:06:52이제 도구(Tooling)에 집중해 보겠습니다. Vite 플러그인에 두 가지 큰 변경 사항이 생겼고,
00:06:57그중 두 번째 변경 사항 덕분에 solid start가 더 이상 존재할 필요가 없어졌습니다. 먼저 컴파일러입니다.
00:07:01Solid 2는 Oxy 기반으로 러스트로 작성된 완전히 새로운 컴파일러 도구 체인을 탑재했으며 Vite 플러그인이 이를 기본값으로 사용하므로.
00:07:06사용자가 별도의 변경을 할 필요는 없습니다. 벤치마크에 따르면,
00:07:10테스트 프로젝트의 컴파일 시간이 약 440밀리초에서 불과 19밀리초로 단축되었고, 더 큰 1메가바이트
00:07:16단일 모듈에서는 25초에서 단 70밀리초로 단축되어 무려 355배 빨라졌습니다. 두 번째 변경 사항은 더 큰 변화입니다.
00:07:24플러그인에 이제 자체 start 모드가 생겼습니다. 이를 통해 인덱스 HTML 스크립트나 엔트리 파일 없이
00:07:28순수 Vite에서 완전한 앱 빌드를 수행할 수 있습니다. 기본적으로 이는 클라이언트 전용 모드로 작동하여
00:07:33빌드 시 순수 정적 파일만 출력되지만, 서버 번들을 함께 빌드하여 서버 사이드 렌더링을 원할 경우 SSR을 활성화할 수도 있습니다.
00:07:38참고로 서버 함수를 좋아하신다면 use server가 이제 핵심 기능입니다. 그뿐만 아니라,
00:07:42라우터 중립적인 패키지를 통해 파일 시스템 라우팅을 사용할 수 있으며, solid start의 검증된 규칙들, HMR, 코드 분할 등을 제공합니다.
00:07:47라우터 중립적인 패키지를 통해 파일 시스템 라우팅을 사용할 수 있으며, solid start의 검증된 규칙들, HMR, 코드 분할 등을 제공합니다.
00:07:51이 세팅이 정말 마음에 드는 이유는 배포가 정적 파일이거나, 혹은 웹 표준 fetch 핸들러를 내보내는 서버 모듈이기 때문입니다.
00:07:56Cloudflare Workers, Netlify, Nitro, Bun, Deno 등이 이미 지원하는 방식이므로
00:08:01중간에 Solid 전용 어댑터 없이 플랫폼 자체 도구로 배포할 수 있습니다.
00:08:06그렇다면 이제 solid start는 더 이상 필요 없다는 뜻이 됩니다. 블로그 글에서 말하듯.
00:08:10solid start는 자신의 역할을 다했습니다. Solid의 공백을 채우기 위한 메타 프레임워크였지만, 이제 2 버전이 그 모든 기능을 집으로 가져왔습니다.
00:08:14현재 solid start를 사용 중이시라면 오늘 당장 바뀌는 것은 없습니다. 유지보수 업데이트는 계속 제공될 것이며,
00:08:18전환하고 싶다면 해당 마이그레이션 가이드를 확인하시면 됩니다.
00:08:22하나의 영상에 담을 수 있는 업데이트는 대략 이 정도입니다. 이번 업데이트가 엄청난 규모의 변경 사항과.
00:08:26API 제거를 담은 대단한 업데이트라는 것을 알 수 있으며, 제가 다루지 않은 부분도 몇 가지 있을 겁니다.
00:08:30start transition이나 use transition이 제거된 것 같은 말이죠. 따라서 전체 목록을 원하신다면
00:08:34solid 1에서 solid 2로의 마이그레이션 가이드를 확인해보시는 것을 추천하며, 이는 AI에게 마이그레이션을 부탁하기에도.
00:08:39아주 훌륭한 리소스입니다. 저도 solid 1과 solid 2를 오가며 작업을 해보았는데,
00:08:43Claude Code가 이 문서를 바탕으로 모든 변경 사항을 잘 이해하고 파악하는 것 같았습니다.
00:08:47이번 업데이트를 깊이 있게 파고들어 정말 즐거웠고 솔직히 말씀드리면.
00:08:51Solid를 안 쓴 지 좀 되었는데, Solid 2 덕분에 아주 쉽게 다시 시작할 수 있었고 사용하기도 꽤 즐거웠습니다.
00:08:55그래서 앞으로는 조금 더 자주 쓰게 될 것 같습니다. 여러분은 어떻게 생각하시나요? 예전에 Solid를 써보신 적이 있으신가요,
00:08:59그리고 이번 업데이트가 마음에 드시나요? 아래 댓글로 남겨주시고
00:09:02구독도 부탁드리며, 늘 그렇듯 다음 영상에서 뵙겠습니다.