본문 바로가기
프로그래밍/Angular

앵귤러 기초(Angular basic) 19. 컴포넌트간 데이터 통신

by 신나요 2022. 1. 28.

애플리케이션을 작성할 때는 중첩된 컴포넌트 요소는 부모 컴포넌트와 통신 해야 하는 경우가 많습니다.

컴포넌트 간의 통신에 대해 알아보겠습니다.

 

이번 포스트에선 아래의 내용을 다루고 있습니다.

  1. 컴포넌트 간의 통신
  2. @input 사용법
  3. @output 사용법

컴포넌트간의 통신

컴포넌트 간에는 데이터를 주고받는 통신이 필요합니다.

부모 컴포넌트에서는 자식 컴포넌트에서 필요로 하는 데이터를 건네주어야 하고,

자식 컴포넌트에선 특정 처리된 결과 값을 다시 부모 컴포넌트에 보내줘서 일련의 처리가 이뤄지게 해야 합니다.

컴포넌트간의 통신

앵귤러에서는 중첩된 컴포넌트(자식 컴포넌트)는 input 프로퍼티를 사용하여 부모 컴포넌트에서 정보 수신이 가능하고,

output프로퍼티를 사용하여 데이터의 발신이 가능합니다.

차근차근 input, output에 대해 알아보도록 하겠습니다.

현재 문제점

지난 포스트에서다룬 현재 개발중인 컴포넌트는 문제점을 다시 한번 살펴 보겠습니다.

 

현재 영화 리스트를 보여주는 화면을 개발하고 있습니다.

원래 숫자였던 평점의 표기를 지난 포스트에서 컴포넌트로 부품화하여 화면과 같이 별점 표시로 바꿨습니다.

별 개수의 판단이 되는 데이터는 부모 컴포넌트가 가지고 있는데, 별점을 표시하는 자식 컴포넌트인 StarScoreComponent에는 데이터를 건네주고 있지 않아 별점이 하드코딩 된 5개로 항상 보여지고 있는 상황입니다.

 

이제 부모컴포넌트(MovieListComponent)가 가지고있는 평점 데이터를 자식컴포넌트(StarScoreComponent)에 건네주어 별을 적절하게 표시하도록 바꿔 주어야 합니다.

@input 사용법

자식 컴포넌트(하위 컴포넌트, 중첩 컴포넌트)가 부모 컴포넌트(상위 컴포넌트, 컨테이너)에서 데이터를 수신하려면 @Input 데코레이터를 사용하여 자식 컴포넌트 클래스의 Input 프로퍼티를 만들어야 합니다.

input 프로퍼티 rating

@Input데코레이터는 객체를 포함한 모든 속성 유형에서 작동합니다.

위 예에서는 중첩된 컴포넌트에  rating값을 전달하기 위해 @Input데코레이터로 해당 프로퍼티를 정의하였습니다.

 

그런 다음 컨테이너(부모 컴포넌트) 템플릿에서 프로퍼티 바인딩을 사용하여 자식 컴포넌트의 프로퍼티로 데이터를 전달합니다.

영화 목록 템플릿(부모 템플릿)에서 프로퍼티 바인딩을 사용하여 movie의 rate을 StarScoreComponent에 전달하였습니다.

여기서 컨테이너 컴포넌트는 @Input 장식기로 표시된 중첩 컴포넌트 프로퍼티에만 바인딩할 수 있으니 주의해 주세요.

현재 코드는 @Input decorator로 자식 컴포넌트의 프로퍼티(rating) 하나만을 지정했지만, @Input은 하나로 제한하지 않고 필요에 따라 여러 input프로퍼티를 만들어 상위에 노출시킬 수 있습니다.

 

부모의 movie.rate는 이제 자식 컴포넌트의 rating 입력 속성에 바인딩되었습니다.

부모 컴포넌트의 데이터가 변경될 때마다 OnChanges 라이프사이클 이벤트가 생성되고 cropWidth가 다시 계산되며 적절한 별이 표시하게 될 것입니다.

 

브라우저로 확인해보겠습니다.

별이 우리가 원하는 대로 잘려서 표시가 되네요. 

참고로 각각 rating 값은 4.5와  3.2입니다.

 

부모 컴포넌트에서 자식 컴포넌트로 데이터 전달을 해보았습니다

그럼 반대로 자식 컴포넌트에서 부모 컴포넌트로 다시 데이터를 보내려면 어떻게 해야 할까요?

 

@Output 사용법

자식 컴포넌트의 데이터를 부모 컴포넌트로 보내려는 경우에는 이벤트를 생성해야 합니다.

그때 사용하는 것이 @Output데코레이터 입니다.

@OutPut데코레이터는 오직 프로퍼티가 이벤트일 때만 적용이 가능합니다.

다시 말해 자식 컴포넌트가 데이터를 부모에게 보내는 유일한 방법은 이벤트를 내보내는 것입니다.

위와 같이 앵귤러에서는 이벤트를 EventEmitter객체로 정의합니다.

EventEmitter를 만들 때 인수는 이벤트와 함께 전달되는 데이터의 유형을 식별해야 합니다.

예를 들어  컨테이너에 문자열을 전달하려면  제네릭타입을<string>이라고 정의해야 합니다.

여러 값을 전달하는 경우에는 객체를 지정할 수도 있습니다.

만든 이벤트를 호출할 때는 EventEmitter의 emit을 호출하면서 인수로 전달 값을 넣어주면 됩니다.

 

사용법을 알아봤으니 코드에서 살펴보겠습니다.

사용자가 별을 클릭하면 부모가 이벤트를 수신하여 평점의 값을 로그로 출력하도록 코드를 수정해 보겠습니다.

 

자식 컴포넌트 수정입니다.

템플릿에서 보면 click시 이벤트 바인딩으로 starClick을 호출하게 바꿨습니다.

starClick메서드에서는 Output프로퍼티인 call을 이용해서 이벤트를 호출하면서 별의 점수를 인수로 넘겨주고 있습니다.

 

부모 컴포넌트 수정입니다.

부모의 템플릿에서  이벤트 바인딩을 사용하여 StarScoreComponent에서 생성된 이벤트를 바인딩합니다.

자식에서 만든 call을 이벤트 바인딩하고 싶으니 이벤트 바인팅 표기인 괄호를 써서 (call)이라고 적어줍니다.

그리고 이벤트가 발생하면 callFromStar메서드를 호출하게 됩니다.

call이벤트를 발생시킬 때 number를 전달하고 있으므로 해당 값을 callFromStar메서드에 전달해 줘야 합니다.

전달할 때는 $event를 사용하면 생성된 이벤트와 관련된 모든 데이터가 전달 가능합니다.

그리고 callFromStar메서드에서는 console.log로 전달받은 값을 출력하게 됩니다.

 

다 됐네요. 결과를 살펴보겠습니다.

모두 잘 작동하네요.🎉

자식 컴포넌트에서 별을 클릭할 때마다 이벤트를 발생시키면, 부모 컴포넌트에서 이벤트 바인딩을 통해 이를 캐치하고 rating값을 콘솔로 출력하였습니다.

 

여기까지 수고하셨습니다.

이것으로 @Input @Output을 통한 데이터 간의 통신을 알아봤습니다.

다음 포스트부터는 앵귤러에서 빼놓을 수 없는 핵심 기능인 service에 대해 알아보겠습니다.

댓글