[230103 - TIL] angular service와 @skipself

Dongwoo Kim·2023년 1월 3일
0

TIL / WIL

목록 보기
68/112

1. 프로젝트 셋업

아래에서 작성한 프로젝트 이어서 작업


2. 프로젝트 구조

ng generate service service/app
ng generate component user/user-info/user-info-detail

AppModule
    ├── (AppService)
	│	
    ├── HomeModule
	│
	└── UserModule
        │
    	└── UserInfoComponent
        	│
           	└── UserInofDetailComponent
  • 유저 정보를 각각 UserComponent, UserInfoCoponent, UserInfoDetailCoponent에서 표시하고 싶은 경우

3. 개선 전

  • User 관련 메소드를 User 클래스에서 관리한다.
  • UserComponent에서 User 정보를 가져오고 자식컴포넌트들에게 바인딩한다.

UserComponent

# user/user.component.ts

export class UserComponent implements OnInit {
  user: User = new User(this.http);

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.user.get_user();
  }
}
# user/user.component.html

<h1>User Component</h1>
<p *ngIf="user">{{ user.id }}</p>
<app-user-info [user]="user"></app-user-info>

UserInfoComponent

# user/user-info/user-info.component.ts

export class UserInfoComponent {
  @Input() user?: User;
}
# user/user-info/user-info.component.html

<h1>User Info Component</h1>
<p *ngIf="user">{{ user.username }}</p>
<app-user-info-detail [user]="user"></app-user-info-detail>

UserInfoDetailComponent

# user/user-info/user-info-detail/user-info-detail.component.ts

export class UserInfoDetailComponent {
  @Input() user?: User;
}
# user/user-info/user-info-detail/user-info-detail.component.html

<h1>User Info Detail Component!</h1>
<p *ngIf="user">{{ user.created_at }}</p>

문제점

  • 컴포넌트의 종속관계가 깊어질수록 User 프로퍼티 바인딩(@Input)를 계속 진행해야한다.
  • 하위 컴포넌트에서 User 데이터를 변화시켜 상위 컴포넌트까지 이벤트 바인딩(@Output)를 해야한다면 더욱 복잡해진다.
  • 프로퍼티로 전달하거나 매개변수로 사용한 User 객체의 메소드는 사용할 수 없다.

4. service와 @SkipSelf를 이용한 개선

AppService

  • 종속관계에 상관없이 직접적으로 접근할 수 있는 AppService를 만들고 AppService에서 User 데이터를 관리한다.
  • User에 관한 메소드도 AppService에서 관리한다.

@SkipSelf

AppServiceAppComponent에 제공하지만 하위 컴포넌트에서도 @SkipSelf를 통해 AppComponent가 제공받은 AppService를 바라볼 수 있다.

AppComponent

# app.component.ts

@Component({
  selector: 'app-root',
  providers: [AppService],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  title = 'App Component';

  constructor(@Self() public appServic: AppService) {}
	
  ngOnInit(): void {}
}

UserComponent

# user/user.component.ts

export class UserComponent implements OnInit {
  constructor(@SkipSelf() public appService: AppService) {}

  ngOnInit(): void {}
}
# user/user.component.html

<h1>User Component</h1>
<p>{{ this.appService.user.id }}</p>
<app-user-info></app-user-info>

UserInfoComponent

# user/user-info/user-info.component.ts

export class UserInfoComponent implements OnInit {
  constructor(@SkipSelf() public appService: AppService) {}

  ngOnInit(): void {}
}
# user/user-info/user-info.component.html

<h1>User Info Component</h1>
<p>{{ this.appService.user.username }}</p>
<app-user-info-detail></app-user-info-detail>

UserInfoDetailComponent

# user/user-info/user-info-detail/user-info-detail.component.ts

export class UserInfoDetailComponent implements OnInit {
  constructor(@SkipSelf() public appService: AppService) {}

  ngOnInit(): void {}
}
# user/user-info/user-info-detail/user-info-detail.component.html

<h1>User Info Detail Component!</h1>
<p>{{ this.appService.user.created_at }}</p>

5. 적용 화면



구현 코드

https://github.com/kimphysicsman/TIL-230103

참고

profile
kimphysicsman

0개의 댓글