Skip to main content

R3S

R3S는 R3를 사용할 때 반복되는 코드를 Roslyn Source Generator로 자동 생성해 보일러플레이트를 크게 줄여주는 SDK입니다.

핵심은 매우 간단합니다.

  • 필드/메서드에 Attribute를 붙인다.

  • Generator가 프로퍼티 노출, 커맨드 실행 메서드, Subscribe 연결 코드를 만든다.

  • 런타임 코드는 더 짧고 읽기 쉬워진다.

잠깐, 알고 가셔야 합니다.

R3S기본적으로 R3를 익힌 프로그래머를 대상으로 제작되었습니다.
R3동작 원리관련 펑션해당 WIKI에서 다루지 않습니다.


왜 사용해야 하나요?

  • 압도적인 라인 절약 : 반복적인 래퍼/구독/Dispose 코드를 직접 작성하지 않아도 됩니다.

  • 실수 방지 진단 : R3Gen001~012 진단으로 partial, Awake/OnDestroy 호출 누락 등컴파일 시점에 잡습니다.

  • 규칙 기반 일관성 : 네이밍과 라이프사이클 규칙이 고정되어 팀 코드 품질을 유지하기 쉽습니다.


보일러플레이트 절감 비교

동일한 ViewModel 코드 비교

기존보일러플레이트 방식
Before.cs
public class PlayerViewModel : MonoBehaviour
{
private readonly ReactiveProperty<int> _hp = new(100);
public ReadOnlyReactiveProperty<int> Hp => _hp;

private readonly ReactiveProperty<int> _mp = new();
public ReactiveProperty<int> Mp => _mp;

private readonly Subject<Unit> _onDead = new();
public Observable<Unit> OnDead => _onDead;

private readonly ReactiveCommand<Unit> _attack = new();
public Observable<Unit> Attack => _attack;
public void ExecuteAttack() => _attack.Execute(Unit.Default);

private CompositeDisposable _disposable = new();

private void Awake()
{
_hp.Subscribe(OnHpChanged).AddTo(_disposable);
}

private void OnHpChanged(int hp) => Debug.Log(hp);
private void OnDestroy() => _disposable.Dispose();
}
R3SAttribute 선언 방식
After.cs
[AutoDispose]
public partial class PlayerViewModel : MonoBehaviour
{
[ReactiveProperty]
private ReactiveProperty<int> _hp = new(100);

[ReactiveProperty(ReadOnly = false)]
private ReactiveProperty<int> _mp = new();

[Subject]
private Subject<Unit> _onDead = new();

[ReactiveCommand]
private ReactiveCommand<Unit> _attack = new();

[AutoSubscribe(nameof(_hp))]
private void OnHpChanged(int hp) => Debug.Log(hp);

private void Awake() => R3Awake();
private void OnDestroy() => R3OnDestroy();
}

Generator 자동 생성 코드

PlayerViewModel.R3Generated.cs
// PlayerViewModel.R3Generated.cs (auto-generated)
public partial class PlayerViewModel
{
private CompositeDisposable _disposable = new();

public ReadOnlyReactiveProperty<int> Hp => _hp;
public ReactiveProperty<int> Mp => _mp;
public Observable<Unit> OnDead => _onDead;
public Observable<Unit> Attack => _attack;
public void ExecuteAttack() => _attack.Execute(Unit.Default);

private void R3Awake()
{
_hp.Subscribe(OnHpChanged).AddTo(_disposable);
}

private void R3OnDestroy() => _disposable.Dispose();
}

효율 지표

38
기존 방식 라인 수
16
R3S 작성 라인 수
-58%
코드 감소율
12
진단 코드 수 (R3Gen)

핵심

3가지의 명확한 기능을 제공합니다.

1. 코드를 얇게 유지 : 사용자가 작성하는 코드는 필드 선언 + 어트리뷰트 + 엔트리, 아웃 총 3가지만 남습니다.

note

매우 간단하고 얇은 컨베션만 따르면 내부의 모든 기능을 100% 활용할 수 있습니다.

2. 명확한 소유권 보장 : Generaotr가 생성한 코드와 사용자 코드가 충돌할 여지가 존재하지 않습니다.

tip

만에 하나, 충돌할 가능성이 발생한 경우에는 R3Gen001 ~ 012 오류가 이를 컴파일 단계에서 감지합니다.

3. 우상향 효율성 : 코드 규모가 커질수록 격차가 매우 크게 벌어집니다.

note

필드가 10개인 클래스라면 기존 방식60 ~ 80 라인, R3S 방식20라인 수준이 됩니다.


지원하는 자동화 범위

info
  • [ReactiveProperty]

  • [ReactiveCommand]

  • [Subject]

  • [AutoSubscribe]

  • [AutoDispose]