[F-Lab 모각코 페이백 18일차] 팀코칭 질문 (인터뷰 준비 및 개념 학습), MVVM 패턴, MVP 패턴
학습 목표
- 팀코팅 질문 답변
- MVVM 패턴
- MVP 패턴
TIL
- MVVM
- View Model
- 데이터 바인딩
- Command 패턴
- Pull 방식
- View Model
- MVP
- Presenter
- Push 방식
- Presenter
동기화 문제는 왜 발생하나요?
동기화 문제는 주로 여러 프로세스나 스레드가 동시에 실행될 때 데이터를 공유하거나 통신할 때 발생하는 문제를 말합니다.
동기화 문제의 원인으로는 경쟁 조건, 데드락, 자원 스타베이션 ,동시성 문제가 있습니다.
i++은 단일 연산 같은데 왜 동기화 문제가 발생하나요?
i++ 같은 연산은 보통 단일 연산으로 생각될 수 있지만, 실제로는 여러 단계로 이루어진 복합 연산입니다.
- 메모리에서 변수 i의 현재 값을 읽습니다.
- 그 값을 증가시킵니다.
- 증가된 값을 메모리에 다시 씁니다.
임계 영역에 대해서 설명해주세요
임계 영역(Critical Section)은 다중 프로세싱 환경에서 두 개 이상의 프로세스나 스레드가 동시에 접근하면 문제를 일으킬 수 있는 공유 데이터나 자원에 대한 코드 부분을 말합니다.
임계 영역에서 일반적으로 세 가지 속성이 유지 되는 것이 중요합니다.
상호 배제, 진행, 한정 대기 속성입니다.
리소스 누수에 대해 설명해 주세요
리소스 누수는 프로그램이 필요 없는데도 불구하고 계속해서 시스템 리소스를 점유하는 현상을 말합니다.
이런 현상은 주로 프로그램이 할당한 리소스를 제대로 해제하지 않았을 때 발생합니다.
이로 인해 시간이 지남에 따라 사용 가능한 리소스가 줄어들어 성능이 저하되거나, 최악의 경우 프로그램이 비정상적으로 종료되는 등의 문제가 발생할 수 있습니다.
메모리 누수, 파일 누수, 스레드 누수 등이 있습니다.
리소스를 꼭 close() 해줘야 하는 이유가 뭔가요?
close() 해야하는 이유에는
리소스 누수방지, 데이터 무결성 보장, 시스템 한계 대응이 있습니다.
이러한 이유로 사용이 끝난 리소스는 반드시 close()를 호출하여 제대로 해제하여하고
자동화 하는 방법 중 하나로 자바에서는 try-with-resources가 있습니다.
락 스트라이핑에 대해서 아는 만큼 설명해보시고 예시를 들어주세요
락 스트라이핑은 동시성을 관리하고 성능을 향상시키기 위한 기법 중 하나로, 여러 스레드가 동시에 데이터 구조에 엑세스할 때 경쟁 조건을 줄이는데 사용됩니다.
사용 예시에는 해시 테이블이 있겠습니다.
CAS 알고리즘이란?
메모리위치(혹은 변수)의 값에 연산을 하고 이것을 예상 값이라고 합니다. 이 값을 현재 값에 대입하고 대입 한 후 예상 값과 갱신 된 현재 값이 예상 값과 다르다면 다른 스레드가 도중에 개입했다고 보고 다시 값 반영을 시도합니다.
컨텍스트 스위칭이란?
하나의 CPU는 하나의 프로세스만 실행할 수 있는데
다중 프로세스 처리를 위해서 현재 프로세스의 컨텍스트를 저장 후 다음 프로세스의 컨텍스트를 로드 후 처리합니다.
이러한 과정을 컨텍스트 스위칭이라고 합니다.
컨텍스트 스위칭이 성능에 영향을 주는 이유는?
컨텍스트 스위칭은 시스템의 효율성을 높이고, 다수의 프로세스가 공정하게 CPU를 사용할 수 있게 해주지만 그 자체로도 비용이 발생합니다.예를 들면 CPU에서 컨텍스트 스위칭을 하면서 CPU 사이클을 소모하고, 새로운 프로세스의 컨텍스트를 처리 하기 위해서 캐시를 갱신하고, 이와 비슷하게 메모리 액세스 비용도 들어갑니다.
쓰레드 생성이 많이 일어나면 어떤 일이 발생할까요?
적절한 수의 쓰레드는 작업 효율을 증가시키지만, 많이 생성하게 되면 여러 가지 문제가 발생할 수 있습니다.
자원 소모, 컨텍스트 스위칭 오버헤드,동기화 복잡성, 스케쥴링 복잡성등의 문제가 있을 수 있습니다.
ConcurrentHashMap 이란 무엇인가?
ConcurrentHashMap은 java.util.concurrent 패키지에 있는 클래스로서, 여러 스레드에서 동시에 접근할 수 있는 스레드 안전한 해시 맵 구현입니다. ConcurrentHashMap은 여러 스레드가 동시에 해시 맵에 접근 할 수 있도록 허용하면서도 스레드 안전성을 유지합니다. 이는 세그먼트 락이라는 개념을 도입했기 때문에 가능합니다.
MVVM 패턴
MVVM(Model-View-ViewModel)은 소프트웨어 아키텍처 디자인 패턴 중 하나로, 특히 사용자 인터페이스를 구성하는데 있어 유용하게 사용됩니다. 이 패턴은 주로 마이크로소프트의 WPF(Windows Presentation Foundation)와 Silverlight, 그리고 Google의 Android Architecture Components 등에서 널리 사용됩니다.
MVVM은 이름에서 알 수 있듯이 세 가지 주요 구성 요소인 Model, View, ViewModel로 이루어져 있습니다:
- Model: 이것은 애플리케이션의 정보(데이터)와 비즈니스 로직을 나타냅니다. 대체로 데이터베이스 액세스 레이어와 통신하거나 API 호출 결과를 저장하는 등의 역할을 수행합니다.
- View: 사용자 인터페이스(UI)를 나타내며, 사용자가 볼 수 있는 화면 요소들을 표현합니다. 사용자 입력을 받아 처리하고, 사용자에게 정보를 표시하는 역할을 합니다.
- ViewModel: View와 Model 사이의 연결 고리 역할을 합니다. View에 표시될 데이터를 준비하고, 사용자의 액션을 Model로 전달하며, 이를 통해 View는 Model을 직접 알지 못하고 ViewModel을 통해서만 데이터를 전달받게 됩니다. 이렇게 함으로써 View와 Model 사이의 의존성이 감소하고, 코드의 재사용성과 테스트 용이성이 증가합니다.
MVVM 디자인 패턴의 핵심 목표는 UI 로직을 UI 코드로부터 분리하여 관리하기 쉽고 테스트하기 쉬운 애플리케이션을 개발하는 것입니다. 이는 특히 복잡한 사용자 인터페이스를 가진 애플리케이션에 유용합니다.
Command 패턴
Command 패턴은 객체지향 디자인 패턴 중 하나로, 요청 자체를 객체로 캡슐화하여 서로 다른 사용자의 파라미터화, 요청 저장 또는 로깅, 그리고 작업 취소 기능을 지원합니다. 이 패턴은 요청을 발생시키는 객체와 요청을 수행하는 객체를 분리하여 코드의 유연성을 증가시킵니다.
Command 패턴의 핵심은 Command 인터페이스(또는 추상 클래스)와 그 구현체입니다. Command 인터페이스는 일반적으로 execute()라는 메소드를 정의하며, 구현체는 이 메소드를 통해 실제로 어떤 작업을 수행할지 정의합니다. 이렇게 하면 Command 객체를 사용하는 클라이언트는 Command 객체가 어떤 작업을 수행하는지 알 필요 없이 execute() 메소드를 호출하기만 하면 됩니다.
Data Binding
Data Binding은 View와 ViewModel 사이의 의존성을 줄이는데 사용되는 기술입니다. 일반적으로 View는 ViewModel에 의존하며 ViewModel은 Model에 의존합니다. 이렇게 되면 View와 ViewModel 사이에는 강력한 의존성이 생기게 됩니다.
하지만 Data Binding을 사용하면 이런 의존성을 끊을 수 있습니다. Data Binding은 ViewModel의 상태 변화를 자동으로 View에 반영하고, 반대로 사용자의 입력을 ViewModel에 자동으로 전달해주는 방식입니다. 이렇게 함으로써 View는 ViewModel을 직접 알 필요 없이 UI 상태를 관리할 수 있게 되며, ViewModel은 View의 상세 구현을 알 필요 없이 사용자 입력을 처리하고 상태 변화를 관리할 수 있게 됩니다.
MVVM 아키텍처에서 Command 패턴과 Data Binding은 주로 ViewModel이 View에 액션을 알리거나, View의 상태 변화를 ViewModel에 알리는데 사용됩니다. 이를 통해 View와 ViewModel 사이의 의존성이 줄어들고, 각 구성 요소의 재사용성과 테스트 용이성이 향상됩니다.
MVVM에서의 바인딩 중요성
MVVM 패턴에서는 일반적으로 데이터 바인딩이 중요한 역할을 합니다. 데이터 바인딩은 View와 ViewModel 사이의 통신을 담당하는데, 이것이 잘 구현되어야 View와 ViewModel 사이의 결합도를 낮출 수 있습니다.
데이터 바인딩을 구현하는 방법은 여러 가지가 있지만, 대부분의 UI 프레임워크나 라이브러리에서는 데이터 바인딩을 지원합니다. 예를 들어, WPF나 Silverlight, Angular, Vue.js, React 등은 데이터 바인딩을 위한 기능을 제공합니다.
그리고 일반적인 단방향 데이터 바인딩 뿐만 아니라 양방향 데이터 바인딩도 지원하는 프레임워크나 라이브러리가 많습니다. 양방향 데이터 바인딩은 View에서 발생하는 변경사항이 ViewModel에 자동으로 반영되고, 반대로 ViewModel에서의 변경사항이 View에 자동으로 반영되는 방식입니다. 이를 통해 View와 ViewModel 사이의 동기화를 쉽게 유지할 수 있습니다.
하지만 양방향 데이터 바인딩은 상태 관리를 복잡하게 만들 수도 있으므로, 어떤 경우에는 단방향 데이터 바인딩을 선택하는 것이 더 적합할 수 있습니다. 예를 들어, React는 주로 단방향 데이터 플로우를 지향하며, 상태 관리 라이브러리인 Redux와 함께 사용되어 복잡한 상태 관리를 해결합니다.
따라서 어떤 데이터 바인딩 방식을 사용할지는 사용하는 프레임워크나 라이브러리, 그리고 애플리케이션의 요구 사항에 따라 달라질 수 있습니다.
데이터 바인딩 구현 방법
데이터 바인딩은 일반적으로 프레임워크나 라이브러리를 통해 구현되며, 이들 각각은 데이터 바인딩을 구현하는 방식이 조금씩 다릅니다. 그러나 기본적인 개념은 아래와 같습니다.
데이터 바인딩은 두 데이터나 정보 소스가 서로 연결되는 것을 의미합니다. 이 경우 View와 ViewModel이 바로 그 두 데이터 소스입니다. 뷰모델에서 정의한 데이터가 변경되면 해당 변경사항이 바인딩된 뷰에 자동으로 업데이트됩니다. 이것이 단방향 데이터 바인딩입니다.
양방향 데이터 바인딩은 이보다 더 복잡합니다. 뷰에서 발생하는 이벤트(예: 사용자 입력)도 뷰모델에 반영됩니다. 예를 들어, 사용자가 텍스트 입력 필드에 값을 입력하면 해당 값이 뷰모델에도 자동으로 업데이트되는 것입니다.
구체적인 예를 들면, AngularJS에서는 이렇게 데이터 바인딩을 구현할 수 있습니다:
<div ng-app="" ng-controller="myCtrl">
Name: <input ng-model="name">
</div>
<script>
function myCtrl($scope) {
$scope.name = "John Doe";
}
</script>
여기서 ng-model은 AngularJS의 데이터 바인딩 디렉티브입니다. name이라는 속성은 뷰모델($scope)에 정의되어 있으며, 이것이 input 태그와 연결(bind)되어 있습니다. 따라서 name 속성의 값이 변경되면 자동으로 input 필드의 값도 변경되며, 반대로 사용자가 input 필드에 값을 입력하면 name 속성의 값도 변경됩니다. 이것이 바로 양방향 데이터 바인딩입니다.
AngularJS와 데이터 바인딩
AngularJS는 기본적으로 데이터 바인딩 기능을 제공합니다. 데이터 바인딩은 AngularJS의 핵심 특징 중 하나이며, 이를 통해 개발자는 DOM을 직접 조작하지 않고 데이터와 뷰 사이의 동기화를 유지할 수 있습니다.
AngularJS에서는 다음과 같이 데이터 바인딩을 구현할 수 있습니다.
<div ng-app="" ng-controller="myCtrl">
Name: <input ng-model="name">
</div>
<script>
function myCtrl($scope) {
$scope.name = "John Doe";
}
</script>
이 예제에서 ng-model 디렉티브는 input 필드와 $scope 객체의 name 속성을 연결합니다. 이 연결은 양방향이므로, name 속성의 값이 변경되면 input 필드의 값도 변경되고, 반대로 사용자가 input 필드에 값을 입력하면 name 속성의 값도 변경됩니다.
이처럼 AngularJS를 이용하면 별도의 라이브러리나 도구 없이도 간편하게 데이터 바인딩을 구현할 수 있습니다.
React에서 데이터 바인딩
React는 데이터 바인딩을 지원하긴 하지만, 이는 React에서 주로 사용되는 패턴인 단방향 데이터 플로우와 다소 다른 개념입니다. React는 일반적으로 View와 Model 사이에 명확한 경계를 그리기보다는, component-based 아키텍처를 통해 UI를 구성하는 것에 초점을 맞춥니다.
React에서 데이터를 바인딩하는 일반적인 방법은 "props"와 "state"를 사용하는 것입니다. "props"는 부모 컴포넌트로부터 자식 컴포넌트로 데이터를 전달하는 데 사용되고, "state"는 컴포넌트 내에서 데이터를 관리하는 데 사용됩니다.
예를 들어, 사용자의 입력을 받아 상태를 관리하는 React 컴포넌트는 다음과 같이 작성할 수 있습니다:
React에서 데이터를 바인딩하는 일반적인 방법은 "props"와 "state"를 사용하는 것입니다. "props"는 부모 컴포넌트로부터 자식 컴포넌트로 데이터를 전달하는 데 사용되고, "state"는 컴포넌트 내에서 데이터를 관리하는 데 사용됩니다.
예를 들어, 사용자의 입력을 받아 상태를 관리하는 React 컴포넌트는 다음과 같이 작성할 수 있습니다:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' };
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({ name: event.target.value });
}
render() {
return (
<input type="text" value={this.state.name} onChange={this.handleChange} />
);
}
}
위의 예제에서 handleChange 메서드는 사용자 입력에 응답하여 상태를 업데이트합니다. 이렇게 React에서는 컴포넌트의 상태를 업데이트함으로써 UI를 자동으로 업데이트합니다.
그러나 React 자체는 MVVM(Model-View-ViewModel) 패턴을 명시적으로 지원하지 않습니다. React는 주로 View를 구성하는 데 사용되며, Model과 ViewModel에 해당하는 부분은 별도의 상태 관리 라이브러리(예: Redux, MobX)나 Context API, React Hook 등을 통해 구현할 수 있습니다.
따라서 React는 MVC, MVVM 등의 구조를 강제하지 않는, 뷰를 구성하는 데 초점을 맞춘 라이브러리라고 볼 수 있습니다.
MVP 패턴
MVP (Model-View-Presenter)는 소프트웨어 설계 패턴 중 하나로, 주로 사용자 인터페이스를 구성하는 데 사용됩니다. 이 패턴은 Model, View, Presenter 세 가지 구성 요소로 이루어져 있습니다:
- Model: 이는 데이터와 비즈니스 로직을 처리하는 부분입니다. 데이터베이스 연동, 네트워크 통신 등 애플리케이션의 '엔진' 역할을 합니다.
- View: 이는 사용자에게 보여지는 UI 부분입니다. 사용자의 입력을 받아들이고, 사용자에게 정보를 보여줍니다. MVP 패턴에서 View는 일반적으로 인터페이스를 통해 구현되며, Presenter가 View를 조작할 수 있게 합니다.
- Presenter: 이는 View와 Model 사이의 '중개자' 역할을 합니다. View로부터 사용자 입력을 받아 Model을 업데이트하고, Model로부터 데이터를 가져와 View를 업데이트합니다.
MVP 패턴의 핵심은 View와 Model 사이에 직접적인 연결이 없다는 것입니다. 이 둘 사이의 모든 상호 작용은 Presenter를 통해 이루어지며, 이로써 View와 Model 사이의 결합도를 낮춥니다. 이렇게 하면 각 구성 요소를 독립적으로 개발하고 테스트할 수 있어 유지보수성이 향상됩니다.
MVP는 MVC (Model-View-Controller) 패턴의 변형 중 하나로 볼 수 있습니다. MVC에서 Controller는 View와 Model 사이의 중개자 역할을 하지만, View와 직접적인 연결이 있을 수 있습니다. 반면에 MVP에서 Presenter는 View와 Model 사이의 연결을 완전히 차단하여 각 구성 요소간의 독립성을 더욱 강화시킵니다.
Presenter 역활과 기능
MVP(Model-View-Presenter) 패턴에서의 Presenter는 중개자 역할을 하는 중요한 구성 요소입니다. Presenter의 주요 역할과 기능은 다음과 같습니다:
- 사용자 입력 처리: View가 사용자로부터 입력을 받으면, 이를 Presenter에 전달합니다. 예를 들어, 사용자가 버튼을 클릭하면 View는 이 정보를 Presenter에 알립니다. 그런 다음 Presenter는 이 정보를 기반으로 적절한 작업을 수행합니다.
- Model 업데이트: Presenter는 사용자 입력을 기반으로 Model을 업데이트합니다. 예를 들어, 사용자가 폼에 정보를 입력하면 Presenter는 이 정보를 Model에 저장합니다.
- View 업데이트: Model에서 데이터를 가져와 View를 업데이트합니다. 예를 들어, Presenter는 Model에서 데이터를 검색하고 이 데이터를 사용하여 View를 업데이트할 수 있습니다.
- View와 Model 분리: Presenter는 View와 Model 사이의 연결을 완전히 차단합니다. 이는 View와 Model이 서로에 대해 알 필요가 없도록 하여 결합도를 최소화합니다. 이로 인해 각 구성 요소를 독립적으로 개발하고 테스트할 수 있습니다.
따라서 Presenter는 MVP 패턴에서 중심적인 역할을 수행하며, 사용자 입력 처리, Model과 View의 업데이트, 그리고 View와 Model의 분리라는 핵심 기능을 담당합니다. 이를 통해 View와 Model이 각각의 역할에 집중할 수 있도록 돕고, 애플리케이션의 구조를 체계적으로 관리할 수 있게 합니다.
Command 패턴
커맨드 패턴(Command Pattern)은 객체지향 디자인 패턴 중 하나로, 요청 자체를 객체로 캡슐화함으로써 클라이언트를 서로 다른 요청에 따라 매개변수화하고, 요청을 큐에 저장하거나 로그에 기록하며, 지원 가능한 작업을 취소할 수 있도록 합니다.
커맨드 패턴의 핵심 구성 요소는 다음과 같습니다:
- Command: 모든 명령을 나타내는 인터페이스입니다. 이 인터페이스는 'execute' 메소드 등 명령을 실행하는 메소드를 정의합니다.
- ConcreteCommand: Command 인터페이스를 구현하는 클래스입니다. 이 클래스는 실제로 실행될 명령의 로직을 포함합니다.
- Invoker: 이 객체는 명령을 실행시킵니다. Invoker는 Command 객체를 저장하고, 필요한 시점에 그 명령을 실행시킵니다.
- Receiver: 이 객체는 명령의 실행에 필요한 실제 로직을 수행합니다.
다음은 커맨드 패턴의 간단한 예입니다:
// Command 인터페이스
public interface Command {
void execute();
}
// ConcreteCommand 클래스
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
}
// Receiver 클래스
public class Light {
public void on() {
System.out.println("Light is on");
}
// ... 다른 메소드들
}
// Invoker 클래스
public class SimpleRemoteControl {
Command slot;
public SimpleRemoteControl() {}
public void setCommand(Command command) {
slot = command;
}
public void buttonWasPressed() {
slot.execute();
}
}
위의 예제에서 SimpleRemoteControl은 invoker, Light는 receiver, LightOnCommand는 ConcreteCommand 역할을 합니다. SimpleRemoteControl에서 버튼을 누르는 메소드(buttonWasPressed)가 호출되면, 해당 메소드는 설정된 커맨드의 execute 메소드를 호출합니다. 이렇게 커맨드 패턴을 사용하면 요청을 발생시키는 객체와 요청을 수행하는 객체 사이의 결합을 줄일 수 있습니다.
Presenter와 View Model의 공통점과 차이점
Presenter와 ViewModel은 둘 다 View와 Model 사이에서 데이터의 흐름을 관리하고 사용자 인터페이스와 관련된 비즈니스 로직을 처리합니다. 이 두 개념은 서로 매우 비슷하며, 이들 간의 주요한 차이는 사용자 인터페이스와 상호작용하는 방식과 역할에 있습니다.
- 공통점: Presenter와 ViewModel 모두 Model과 View 사이의 인터페이스 역할을 합니다. 그들은 Model에서 데이터를 가져오고 이를 View에 제공합니다. 이 둘은 모두 Model과 View를 분리하여 응용 프로그램 코드의 구조화와 테스트 용이성을 증가시키는데 도움을 줍니다.
- 차이점:
Presenter: Presenter는 View에 대한 참조를 유지하고, Model의 데이터를 가져와 View가 이해할 수 있는 형식으로 변환합니다. Presenter는 사용자의 인터랙션에 반응하여 Model을 업데이트하고, Model의 변경 사항을 감지하여 이를 View에 반영합니다. 이는 전통적인 '푸시' 모델을 따릅니다.
ViewModel: 반면에 ViewModel은 View에 대한 참조를 보유하지 않습니다. 대신 ViewModel은 View에 의해 관찰되는 데이터를 노출합니다. View는 ViewModel의 데이터 변화를 구독하고 자동으로 업데이트합니다. 이는 '풀' 모델을 따르며, 데이터 바인딩을 활용한 자동 업데이트를 가능하게 합니다. ViewModel은 종종 View의 상태도 관리하는데 이는 View의 라이프사이클과 독립적으로 관리되므로, 구성 변경(예: Android에서의 화면 회전)과 같은 문제에서 View의 상태를 유지할 수 있게 합니다.
간단히 말하자면, Presenter는 View와 Model 사이의 직접적인 다리 역할을 하며, ViewModel은 데이터 바인딩을 사용하여 View에 데이터를 '풀'하는 역할을 합니다.
View Model에서 Pull 이란?
'풀'하는 역할이라는 말은 ViewModel이 데이터의 변화를 알리는 것이 아니라, View가 필요한 데이터를 ViewModel로부터 '끌어오는(pull)' 역할을 하는 것을 의미합니다. 이것은 주로 데이터 바인딩을 통해 구현됩니다.
데이터 바인딩은 View와 ViewModel 사이의 통신 방식을 단순화하며, 두 요소를 직접적으로 연결합니다. View는 ViewModel의 데이터 변화를 구독하고(View가 ViewModel을 '관찰'하고 있다고도 표현합니다), ViewModel에서 데이터가 변경되면 View는 자동으로 업데이트됩니다.
즉, ViewModel이 데이터를 변경하면, 이 변경 사항이 View에 자동으로 반영되는데, 이것이 바로 '풀'하는 역할을 하는 것입니다. 이 과정은 실시간으로 일어나며, 개발자가 수동으로 View를 업데이트하는 코드를 작성할 필요가 없습니다. 이러한 방식은 코드의 복잡성을 줄이고, 코드의 가독성을 향상시키며, 버그 발생 가능성을 줄이는 등의 장점이 있습니다.
이와 달리, Presenter는 View와 Model 사이에서 데이터를 '푸시(push)'합니다. 즉, Model에서 데이터를 가져와 View에 전달하고, 사용자의 인터랙션에 응답하여 Model을 업데이트하는 등의 작업을 수행합니다. 이는 데이터 변경을 View에 알리는 '푸시' 모델을 따르며, 이 경우 개발자가 직접 View를 업데이트하는 코드를 작성해야 합니다.
Push 방식과 Pull 방식의 기본적인 특징
푸시(push) 방식과 풀(pull) 방식은 데이터의 전송 방향과 관련된 개념입니다.
푸시 방식은 데이터를 가지고 있는 주체가 다른 주체에게 데이터를 직접 전달하는 방식입니다. 즉, 데이터 소스가 수신자에게 데이터를 "푸시"합니다. 이 방식은 데이터 변경이 일어날 때마다 바로 수신자에게 알려주기 때문에, 데이터의 실시간성을 유지하는 데 유리합니다. 하지만 수신자가 그 데이터를 필요로 하지 않아도 데이터 소스는 수신자에게 데이터를 계속 푸시하게 됩니다.
풀 방식은 데이터를 필요로 하는 주체가 데이터 소스에게서 직접 데이터를 가져오는 방식입니다. 즉, 수신자가 데이터 소스로부터 데이터를 "풀"합니다. 이 방식은 수신자가 데이터를 필요로 할 때만 데이터를 가져오기 때문에, 효율적인 리소스 사용에 유리합니다. 하지만 데이터 소스의 변경을 수신자가 알아채는 데에는 약간의 지연이 발생할 수 있습니다.
각 방식의 장단점은 다음과 같습니다:
푸시 방식
- 장점: 데이터 변경이 실시간으로 반영되므로, 항상 최신 데이터를 유지할 수 있습니다.
- 단점: 데이터를 필요로 하지 않는 수신자에게도 데이터가 전송되므로, 네트워크 트래픽과 리소스 낭비가 발생할 수 있습니다.
풀 방식
- 장점: 데이터를 필요로 하는 경우에만 데이터를 요청하므로, 리소스를 효율적으로 사용할 수 있습니다.
- 단점: 데이터의 변경을 감지하는 데에 지연이 발생할 수 있으며, 수신자가 데이터를 주기적으로 체크해야 할 필요가 있습니다.
데이터 바인딩을 활용한 MVVM(Model-View-ViewModel) 패턴 등은 풀 방식을 활용합니다. 이 패턴에서, ViewModel의 데이터 변경이 발생하면 View는 자동으로 업데이트되는데, 이는 View가 ViewModel의 데이터 변화를 구독('풀'하는 방식)하고 있기 때문입니다. 이런 방식은 코드의 복잡성을 줄이고, 가독성을 향상시키며, 버그 발생 가능성을 줄이는 등의 장점을 제공합니다.