SolidJS 완벽 가이드 | 고성능 반응형 프레임워크·Signals·JSX·실전 활용
이 글의 핵심
SolidJS로 초고속 웹 앱을 개발하는 완벽 가이드. Signals, JSX, Stores, SolidStart, TypeScript까지 실전 예제로 정리. SolidJS·Signals·Reactivity 중심으로 설명합니다.
이 글의 핵심
SolidJS로 초고속 웹 앱을 개발하는 완벽 가이드입니다. Signals, JSX, Stores, SolidStart, TypeScript까지 실전 예제로 정리했습니다.
실무 경험 공유: React에서 SolidJS로 전환하면서, 성능이 3배 향상되고 번들 크기가 60% 감소한 경험을 공유합니다.
들어가며: “React가 느려요”
실무 문제 시나리오
시나리오 1: 불필요한 리렌더링이 많아요
React는 컴포넌트 전체를 리렌더링합니다. SolidJS는 변경된 부분만 업데이트합니다. 시나리오 2: 성능 최적화가 어려워요
useMemo, useCallback이 복잡합니다. SolidJS는 자동으로 최적화됩니다. 시나리오 3: 번들 크기가 커요
React는 40KB입니다. SolidJS는 7KB입니다.
1. SolidJS란?
핵심 특징
SolidJS는 고성능 반응형 JavaScript 프레임워크입니다. 주요 장점:
- 초고속: Virtual DOM 없음
- 작은 번들: 7KB
- Signals: 세밀한 반응형
- JSX: React와 유사
- No Re-renders: 컴포넌트는 한 번만 실행
2. 설치 및 프로젝트 생성
Vite
npm create vite@latest my-app -- --template solid-ts
cd my-app
npm install
npm run dev
SolidStart
npm create solid@latest my-app
3. Signals
createSignal
import { createSignal } from 'solid-js';
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
<p>Count: {count()}</p>
<button onClick={() => setCount(count() + 1)}>Increment</button>
</div>
);
}
createEffect
import { createSignal, createEffect } from 'solid-js';
function App() {
const [count, setCount] = createSignal(0);
createEffect(() => {
console.log('Count changed:', count());
});
return <button onClick={() => setCount(count() + 1)}>Increment</button>;
}
4. Derived Signals
import { createSignal, createMemo } from 'solid-js';
function App() {
const [count, setCount] = createSignal(0);
const doubled = createMemo(() => count() * 2);
return (
<div>
<p>Count: {count()}</p>
<p>Doubled: {doubled()}</p>
<button onClick={() => setCount(count() + 1)}>Increment</button>
</div>
);
}
5. Control Flow
Show
import { createSignal, Show } from 'solid-js';
function App() {
const [loggedIn, setLoggedIn] = createSignal(false);
return (
<div>
<Show when={loggedIn()} fallback={<p>Please log in</p>}>
<p>Welcome!</p>
</Show>
<button onClick={() => setLoggedIn(!loggedIn())}>Toggle</button>
</div>
);
}
For
import { For } from 'solid-js';
function TodoList() {
const [todos] = createSignal([
{ id: 1, text: 'Learn SolidJS' },
{ id: 2, text: 'Build an app' },
]);
return (
<ul>
<For each={todos()}>
{(todo) => <li>{todo.text}</li>}
</For>
</ul>
);
}
6. Stores
import { createStore } from 'solid-js/store';
function App() {
const [state, setState] = createStore({
user: { name: 'John', age: 30 },
todos: [{ id: 1, text: 'Learn SolidJS', done: false }],
});
const addTodo = (text: string) => {
setState('todos', (todos) => [...todos, { id: Date.now(), text, done: false }]);
};
const toggleTodo = (id: number) => {
setState('todos', (todo) => todo.id === id, 'done', (done) => !done);
};
return (
<div>
<p>{state.user.name}</p>
<ul>
<For each={state.todos}>
{(todo) => (
<li onClick={() => toggleTodo(todo.id)}>
{todo.text} {todo.done ? '✓' : '}
</li>
)}
</For>
</ul>
</div>
);
}
7. Context
import { createContext, useContext } from 'solid-js';
const CounterContext = createContext<[() => number, (v: number) => void]>();
function CounterProvider(props) {
const [count, setCount] = createSignal(0);
return (
<CounterContext.Provider value={[count, setCount]}>
{props.children}
</CounterContext.Provider>
);
}
function useCounter() {
return useContext(CounterContext);
}
// 사용
function Counter() {
const [count, setCount] = useCounter();
return <button onClick={() => setCount(count() + 1)}>Count: {count()}</button>;
}
8. 실전 예제: 사용자 목록
import { createSignal, createResource, For, Show } from 'solid-js';
interface User {
id: number;
name: string;
email: string;
}
async function fetchUsers(): Promise<User[]> {
const response = await fetch('https://api.example.com/users');
return response.json();
}
function UserList() {
const [users] = createResource(fetchUsers);
return (
<div>
<Show when={!users.loading} fallback={<p>Loading...</p>}>
<Show when={!users.error} fallback={<p>Error: {users.error}</p>}>
<ul>
<For each={users()}>
{(user) => (
<li>
{user.name} - {user.email}
</li>
)}
</For>
</ul>
</Show>
</Show>
</div>
);
}
정리 및 체크리스트
핵심 요약
- SolidJS: 고성능 반응형 프레임워크
- Signals: 세밀한 반응형
- 초고속: Virtual DOM 없음
- 작은 번들: 7KB
- JSX: React와 유사
- No Re-renders: 한 번만 실행
구현 체크리스트
- SolidJS 설치
- Signals 사용
- createEffect 활용
- createMemo 사용
- Control Flow
- Stores 활용
- Context 구현
- SolidStart 사용
같이 보면 좋은 글
- React 완벽 가이드
- Svelte 완벽 가이드
- 성능 최적화 가이드
이 글에서 다루는 키워드
SolidJS, Signals, Reactivity, Performance, JSX, TypeScript, Frontend
내부 동작과 핵심 메커니즘
이 글의 주제는 「SolidJS 완벽 가이드 | 고성능 반응형 프레임워크·Signals·JSX·실전 활용」입니다. 여기서는 앞선 설명을 구현·런타임 관점에서 한 번 더 압축합니다. 구성 요소 간 책임 분리와 관측 가능한 지점을 기준으로 생각하면, “입력이 어디서 검증되고, 핵심 연산이 어디서 일어나며, 부작용(I/O·네트워크·디스크)이 어디서 터지는가”가 한눈에 드러납니다.
처리 파이프라인(개념도)
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
알고리즘·프로토콜 관점에서의 체크포인트
- 불변 조건(Invariant): 각 단계가 만족해야 하는 조건(예: 버퍼 경계, 프로토콜 상태, 트랜잭션 격리)을 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 동일 입력에 동일 출력이 보장되는 순수한 층과, 시간·네트워크에 의해 달라질 수 있는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화/역직렬화, 문자 인코딩, syscall 횟수, 락 경합처럼 “한 번의 호출이 아니라 누적되는 비용”을 의심 목록에 넣습니다.
프로덕션 운영 패턴
실서비스에서는 기능 구현과 함께 관측·배포·보안·비용이 동시에 요구됩니다. 아래는 팀에서 자주 쓰는 최소 체크리스트입니다.
| 영역 | 운영 관점에서의 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율/지연 분위수, 주요 의존성 타임아웃이 보이는가 |
| 안전성 | 입력 검증·권한·비밀 관리가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등한 연산에만 적용되는가, 서킷 브레이커·백오프가 있는가 |
| 성능 | 캐시 계층·배치 크기·풀링·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리, 마이그레이션 호환성이 문서화되어 있는가 |
운영 환경에서는 “개발자 PC에서는 재현되지 않던 문제”가 시간·부하·데이터 크기 때문에 드러납니다. 따라서 스테이징의 데이터 양·네트워크 지연을 가능한 한 현실에 가깝게 맞추는 것이 중요합니다.
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스 컨디션, 타임아웃, 외부 의존성 불안정 | 최소 재현 스크립트 작성, 분산 트레이스·로그 상관관계 확인 |
| 성능 저하 | N+1 쿼리, 동기 I/O, 잠금 경합, 과도한 직렬화 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 클로저/이벤트 구독 누수, 대용량 객체의 불필요한 복사 | 상한·TTL·스냅샷 비교(힙 덤프/트레이스) |
| 빌드·배포만 실패 | 환경 변수·권한·플랫폼 차이 | CI 로그와 로컬 diff, 컨테이너/런타임 버전 핀(pin) |
권장 디버깅 순서: (1) 최소 재현 만들기 (2) 최근 변경 범위 좁히기 (3) 의존성·환경 변수 차이 확인 (4) 관측 데이터로 가설 검증 (5) 수정 후 회귀·부하 테스트.
자주 묻는 질문 (FAQ)
Q. React와 비교하면 어떤가요?
A. SolidJS가 훨씬 빠릅니다. React는 생태계가 더 큽니다.
Q. 학습 곡선은 어떤가요?
A. React 경험이 있으면 쉽습니다. JSX가 비슷합니다.
Q. Hooks를 사용하나요?
A. 아니요, Signals를 사용합니다. 더 간단하고 빠릅니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, 점점 더 많은 프로젝트에서 사용하고 있습니다.