서비스의 SignalStore
signal 기반 서비스에 앱 상태를 보관합니다.
서비스의 SignalStore은(는) CoddyKit의 무료 Angular Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Angular Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Angular Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
상태로서의 신호
Angular의 신호는 변경될 때 소비자에게 알리는 반응형 값입니다. 신호는 값을 보유하며, 해당 신호를 읽는 모든 계산이나 템플릿을 다시 실행합니다.
@Injectable 서비스 내부에 신호를 저장하면 여러 컴포넌트가 동일한 반응형 상태를 공유할 수 있습니다.
최소 신호 저장소
서비스를 만들고 signal()에 상태를 저장하십시오. 쓰기 가능한 신호는 비공개로 유지하고 읽기 전용 뷰를 노출하십시오.
import { Injectable, signal } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class CounterStore {
private _count = signal(0);
readonly count = this._count.asReadonly();
increment() { this._count.update(c => c + 1); }
}providedIn root를 사용하는 이유
providedIn: 'root'는 전체 앱에서 서비스가 싱글턴이 되도록 합니다. 서비스를 주입하는 모든 컴포넌트가 정확히 같은 신호 인스턴스를 공유하므로 상태가 동기화된 상태로 유지됩니다.
신호 읽기
신호를 함수처럼 호출하여 값을 읽으십시오. 템플릿 안에서 읽으면 Angular가 해당 읽기를 추적하고 값이 변경될 때 DOM을 자동으로 업데이트합니다.
import { Component, inject } from '@angular/core';
import { CounterStore } from './counter.store';
@Component({
selector: 'app-counter',
template: '<button (click)="store.increment()">{{ store.count() }}</button>'
})
export class CounterComponent {
store = inject(CounterStore);
}asReadonly로 상태 보호하기
asReadonly()는 읽을 수 있지만 쓸 수 없는 신호를 반환합니다. 컴포넌트가 실수로 set() 또는 update()를 호출할 수 없으므로 모든 변경이 저장소 메서드를 통해 이루어집니다.
set과 update
다음 값을 직접 알고 있다면 set(value)을 사용하십시오. 다음 값이 현재 값에 따라 달라진다면 update(fn)을 사용하십시오.
private _user = signal<User | null>(null);
setUser(u: User) { this._user.set(u); }
clearUser() { this._user.set(null); }
touch() { this._user.update(u => u ? { ...u, seen: true } : u); }저장소에서 여러 신호 사용하기
저장소는 서로 다른 상태 조각을 나타내는 여러 신호를 보유할 수 있습니다. 각 쓰기 가능한 신호는 비공개로 유지하고 읽기 전용 대응 항목을 노출하십시오.
private _items = signal<Item[]>([]);
private _loading = signal(false);
readonly items = this._items.asReadonly();
readonly loading = this._loading.asReadonly();메서드로 로직 캡슐화하기
비즈니스 규칙은 컴포넌트가 아니라 저장소 메서드에 둡니다. 컴포넌트는 addToCart(item)처럼 의도를 드러내는 메서드를 호출하고, 상태를 어떻게 변경할지는 저장소가 결정합니다.
addToCart(item: Item) {
this._items.update(list => [...list, item]);
}
removeFromCart(id: string) {
this._items.update(list => list.filter(i => i.id !== id));
}구독 불필요
RxJS 기반 서비스와 달리 신호 저장소에는 subscribe()나 수동 구독 해제가 필요하지 않습니다. 템플릿에서 신호를 읽으면 반응성이 연결되고, 컴포넌트가 제거될 때 Angular가 이를 정리합니다.
inject()로 주입하기
inject() 함수는 생성자, 필드 초기화 구문 및 팩토리 함수에서 사용할 수 있습니다. 저장소 인스턴스를 가져오는 현대적인 방법입니다.
export class CartComponent {
private store = inject(CartStore);
items = this.store.items; // read-only signal
}신호 저장소 테스트하기
신호 저장소는 일반 클래스이므로 테스트가 간단합니다. 인스턴스를 만들고 메서드를 호출한 다음 신호 값을 동기적으로 읽으면 됩니다. 비동기 처리가 필요하지 않습니다.
it('increments', () => {
const store = new CounterStore();
store.increment();
expect(store.count()).toBe(1);
});빠른 확인
신호 저장소에 대한 이해도를 확인해 보십시오.
요약
쓰기 가능한 신호를 비공개로 유지하고, asReadonly() 뷰를 노출하며, 메서드 내부에서 set/update를 통해 변경하고, inject()로 싱글턴을 주입하는 신호 기반 저장소를 만드는 방법을 배웠습니다. 구독이 필요 없고 테스트하기 쉬우며 반응형 상태를 공유할 수 있습니다.
자주 묻는 질문
“서비스의 SignalStore” 강의는 무료인가요?
네 — “서비스의 SignalStore” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Angular Academy 강의 전체를 잠금 해제할 수 있습니다. Angular Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“서비스의 SignalStore”에서 뭘 배우나요?
signal 기반 서비스에 앱 상태를 보관합니다. 브라우저에서 직접 실행하는 실습 코드로 Angular Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Angular Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Angular Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“서비스의 SignalStore” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Angular Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Angular Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 서비스의 SignalStore
- computed로 상태 파생하기
- 불변 방식으로 상태 업데이트하기
- Signals와 RxJS 연결하기