상세 컨텐츠

본문 제목

Architecture, Design, UI(세미나)

공부/안드로이드

by dofury 2024. 1. 29. 15:58

본문

728x90

 

이번 시간에 설명할 주제는 디자인을 중심으로 내용을 구성해보았습니다.

 

 

아키텍처와 디자인 패턴, 머터리얼 디자인,

명령형 UI와 선언형 UI에 대해 다뤄보겠습니다.

 

 

아키텍처와 디자인 패턴은 설계 문제에 대하여 소프트웨어 개발에서 공통적으로 사용되는 구조화된 해결책 입니다.

허나 이 둘의 경계가 흐릿하여 이를 명확하게 구분 하지 않는 것을 보였습니다.

그래서 좀 더 자세히 찾아보니 적용 범위와 추상화 수준에서 차이가 있었습니다. 

 

적용 범위에서는 디자인 패턴은 클래스 레벨에서 부터 객체 간의 상호작용에 이르기까지 다양한 범위이며,

아키텍처 패턴은 시스템 전체의 구조, 모듈 간의 관계 정의, 애플리케이션 전반적인 디자인입니다.

 

또한 추상화 수준에서는 디자인 패턴은 구체적이고 상세한 수준에서 코드 구현에 관여하며,

아키텍처 패턴에서는 시스템의 전반적인 디자인 원칙과 모듈 간의 관계를 다룹니다.

 

즉 디자인 패턴보다 아키텍처패턴이 더 큰 개념이라고 보면 될 것 같습니다.

 

 

아키텍처쪽에 속하는 패턴들을 가져와봤습니다.

MVC, MVP ,MVVM, MVI 등이 있는데

이중에서 MVVM과 MVI가 중요한 것 같아서 좀더 자세히 다뤄보겠습니다.

 

 

MVVM은 모델과 뷰모델 뷰로 구성되어있으며, 후에 언급할 옵저버 패턴을 이용합니다.

또한 MVCMVP 문제를 해결하기 위해 도입되어서 안드로이드 개발 시 주로 사용합니다.

 

허나 상위호환이라는 개념은 아니고 각자 장단점이 있어 맞게 사용해야 합니다

 

MVVM는 사용자가 View를 통해 애플리케이션과 상호작용 즉

입력을 하면 이벤트가 발생하고 이벤트는 뷰로 전달됩니다.

그 다음 뷰에서 발생한 이벤트는 뷰 모델에 전달이 됩니다.

뷰 모델은 이벤트를 수신하고 필요에 따라 모델에 데이터를 요청하거나,

모델의 상태를 업데이트 하는 식으로 데이터 흐름이 이루어집니다.

 

양방향 데이터 바인딩은 뷰에서 입력을 하면 뷰 모델이 처리하고 변경된 데이터를 반영합니다.

반대로 모델에 데이터가 업데이트 되면 뷰 모델이 이를 감지하고 뷰에 데이터를 업데이트 합니다.

 

쉽게 생각하면 아이디를 입력하면 입력과 동시에 보이는 것 뿐만 아니라 내부의 모델의 데이터도 변경이 됩니다.

반대로 내부의 입력된 아이디를 수정하게 되면 아이디 입력창에 아이디가 변하게 되는 것입니다.

이것이 양방향 데이터 바인딩입니다.

 

장점으로는 뷰와 모델이 독립되고 유닛 테스트에 용이하며,

단점으로는 컴포즈방식을 제외하고 데이터 바인딩이 필수적으로 요구되며,

뷰에 대한 처리가 복잡할수록 뷰모델이 커집니다

 

 

MVI는 유저가 모델 뷰 인텐르로 구성되어 있으며,

뷰에서 인텐트를 발생시켜 모델에 전달하고, 모델에서 처리한 결과를 다시 뷰로 전달하는 방식입니다.

 

동작 흐름은 모델은 상태변화를 처리하고 데이터를 뷰에 전달한다음, 뷰에서 유저가 인텐트를 발생시켜 모델로 전달합니다.

즉 뷰에서 유저가 발생시킨 사용자 액션이라는 인텐트를 모델에 전달하는 것 입니다.

그리고 인텐트나 모델 데이터들은 불변 구조를 가집니다.

 

또한 말한 순서와 사진과 같이 데이터는 단방향으로 흐릅니다.

장점으로는 코드의 안정성이 높으며, 뷰모델 사이 인터페이스가 단순화 되어있고, 성능적으로 개선됩니다.

허나 러닝 커브가 높고 구현이 복잡해 가벼운 애플리케이션에는 사용하지 않는 것이 좋습니다.

 

 

그 다음으로는 디자인 패턴입니다.

- Creational Patterns

- Dependency Injection

- Observer Pattern

- Repository Pattern

등이 있습니다.

 

 

크리에이셔널 패턴들은 안드로이드 개발에서 인스턴트 생성시에 사용합니다.

여러 패턴들이 있으나 이번시간에는 싱글톤, 빌더 ,팩토리에 대해서 설명해보겠습니다.

 

 

싱글톤 패턴은 객체의 인스턴트가 하나만 생성되도록 보장하여 전역적인 접근 점을 제공하는 디자인 패턴입니다.

 

특징으로는 인스턴트를 하나만 생성하게 되니 메모리 낭비 방지를 할 수 있고,

이미 생성된 인스턴트가 있다면 생성된 인스턴트에 접근하니 속도가 빠르게 됩니다.

 

또한 전역으로 사용하는 인스턴트 이기 때문에 또한 여러 클래스에서 데이터 공유가 쉽습니다.

허나 동시성 문제 발생 염려가 있습니다.

 

밑에 자바 코드를 보시면 static으로 선언한 함수를 통해 늘 인스턴트를 얻어오게 설계 되어 있으며,

없으면 새로 만들고 있으면 기존 것을 불러옵니다.

 

 

빌더 패턴은 복잡한 객체 생성 과정을 추상화하여 객체를 단계적으로 생성하고 구상하는 디자인 패턴 입니다.

빌더 패턴은 생성자가 많거나 객체의 속성이 다양한 복잡한 객체에 사용하기 좋습니다.

 

아래와 같이 다이얼로그 클래스를 만들 때 빌더 클래스에서 데이터를 생성해서 다이얼로그 생성자에 넣어줍니다.

이 때 다이얼로그 클래스 생성자는 private라 당연히 빌더 없이 생성은 불가능 합니다.

 

 

팩토리 패턴은 객체 생성을 캡슐화 하여 클라이언트 코드에서 구체적인 클래스의 인스턴트를 직접 생성하지 않고,

팩토리에게 생성을 요청하는 디자인 패턴입니다.

 

특징으로는 확장성과 유연성을 제공 합니다.

원공장과 사각형 공장은 모양공장 인터페이스를 구현하는 클래스이고 원공장은 원을 찍어내고,

사각형 공장은 사각형 클래스를 찍어냅니다.

만약 삼각형이 필요하다면 삼각형 공장을 새로 추가하면 됩니다.

 

 

의존성 주입은 객체 생성 의무를 클래스 외부로 이전하는 것 입니다.

Hilt, Dagger, Koin 같은 라이브러리를 사용해서 주로 구현합니다.

이는 특정 클래스의 변경이 다른 클래스에 영향을 주지 않게 클래스 간 느슨하게 결합한다는 뜻입니다.

 

예를들어 유저서비스 클래스 내부에 로그를 찍는 클래스가 있다면 내부에서 구현하지 않고,

생성자를 통해 외부에서 주입 받게 끔 설계를 하면 혹여나 다른 로그클래스를 사용하게 된다 하더라도

유저서비스 클래스 내부를 수정하지 않고 변경할 수 있는 것입니다.

 

보일러 플레이트 코드 감소(별 수정 없이 반복적 사용하는 코드)
단위 테스트 쉽게 작성
클래스 재사용성이 높아짐
 

장점으로는 위와 같이 있습니다

 

 

옵저버 패턴은 관찰하고 있는 대상 상태 변화 시 대상자는 관찰자에게 알리고 관찰자는 조치하는 패턴입니다.

한 객체의 상태가 변경되면 그 객체에 의존하는 다수의 객체들에게 알림이 전달되어 자동으로 상태를 갱신할 수 있게 합니다.

특징으로는 일대다 의존성을 가집니다.

 

 

레포지토리 패턴은 데이터 저장소에서 데이터를 읽고 쓰는 작업을 캡슐화하는 디자인 패턴 입니다.

 

레포지토리 패턴은 비즈니스 로직과 데이터 액세스 코드를 분리하여 코드 유지보수성 향상이 됩니다.

또한 단일 책임 원칙 준수로 코드가 간결화 되며,

데이터 변경시 레포지토리만수정하면 되서 다른 부분에 영향을 주지 않는 이점이 있습니다.

 

 

머터리얼 디자인은 다양한 디바이스들을 아우르는 하나의 일관된 디자인 가이드 라인입니다.

2014년에 구글이 안드로이드 스마폰에 적용 되면서 널리 퍼지기 시작했습니다.

 

특징으로는 이와 같이 있습니다.

  • 질감이 느껴지는 표면
  • 대담하고 선명한 그래픽 디자인
  • 아름답고 직관적인 사용자 경험을 위한 자연스러운 애니메이션

 

 

머터리얼 디자인에는 테마, 애니메이션, 드로어블이 있습니다.

해당 요소들은 머터리얼 디자인을 손쉽게 적용할 수 있게 도와줍니다.

 

 

머터리얼 디자인에는 타이포 그래피를 제공합니다.

타이포 그래피는 글꼴, 글자 크기, 간격 및 줄간격과 같은 텍스트 시각적인 표현을 다루는 디자인 분야입니다.

머터리얼 디자인3에서 15가지 타이포 그래피 스케일을 제공하여 원하는 세트를 필요에 따라 사용하면 됩니다.

 

 

머터리얼 디자인은 카드 스톡기반 이기 때문에 Z축이 존재합니다.

이 때 뷰의 엘레베이션 값을 조정하면 Z축을 조절할 수 있습니다.

엘레베이션 값이 변경되면 그림자 크기나 그리기 순서가 달라집니다.

 

 

명령형 UI는 기존의 UI를 만드는 방식 입니다.

기존 안드로이드는 트리형태로 뷰를 구성합니다.

쉽게 말해 레이아웃을 맨 아래 깔고 그 위에 버튼 넣고 텍스트 넣다가 다시 레이아웃 넣고 하는 개념 입니다.

 

허나 이 방식은 XML이라는 리소르를 반복적으로 낭비하고

한 노드에 대한 업데이트의 충돌이 발생할 확률이 높다는 문제점이 있습니다.

 

 

선언형 UI는 새로나온 UI를 만드는 방식입니다.

화면 전체를 개념적으로 재생성 한후 필요한 변경사항만 적용합니다.

또한 각 뷰마다 상태라는 개념이 존재합니다.

선언형 UI방식은 상태변화에만 집중할 수 있어서 개발 시 편리 합니다.

젯팩 컴포즈를 통해 선언형 UI방식을 사용할 수 있습니다.

 

그리고 아래 공식은 선언형 UI의 공식 같은건데,

위젯이나 함수 매개변수로 상태를 넘겨주면 뷰를 반환 한다는 기본 원리를 표현하고 있습니다.

 

 

그럼 두 방식을 실제로 사용한다면 어떤 느낌이고 무엇을 사용 하는 게 좋을까 하는 생각이 들었습니다.

위 이미지와 같이 우선 선언형 UI방식이 간결하게 작성할 수 있고 가독성도 좋습니다.

허나 유연성이 높은 명령형 UI방식을 사용해야 하는 경우도 존재할 수 있습니다.

 

그러면 섞어서 사용할 수 있기에 두 방식을 이해하고,

이를 혼용해서 사용해 두 가지 이점을 다 가지는 게 좋다고 판단했습니다.

 

 

세미나 내용은 해당 링크를 참고했습니다

728x90

관련글 더보기

댓글 영역