FE

선언형 UI 개발

지희욱 프로필 이미지

지희욱

2024.05.14

5 min read

선언형 UI 개발

요즘 웹에서는 React와 Vue, 모바일에서는 Flutter와 Swift UI, Android Jet Compose 등을 통해 UI가 개발되고 있습니다. 이 프레임워크, 라이브러리들의 공통점은 무엇일까요?

바로 선언형 UI 개발 방식이라는 점입니다.

선언형 프로그래밍은 프로그램이 어떤 방법으로 해야 하는지(Imperative programming)보다는 프로그램이 무엇과 같은지(Declarative programming)에 대해 설명합니다.

이러한 선언형 프로그래밍을 이용해 기존 UI 개발의 문제점을 해결하는 것이 선언형 UI 개발입니다.

기존 명령형 UI 개발에서는 UI 엔티티를 만들고, UI가 바뀔 때마다 메서드를 이용해서 직접 mutate 해주었습니다. 하지만 웹이 복잡해지면서 UI mutation은 점점 부담되었고, 이에 따라 직접적인 부분은 프레임워크에 맡기고 상태에 따른 UI를 서술만 하는 UI 개발방식이 대두되었습니다.

그렇다면 명령형 UI 개발과 다르게 어떻게 구현이 되는 걸까요?

명령형 UI 개발과의 비교

간단한 counting 코드로 jQuery와 React를 비교해볼 수 있습니다.

const $countButton = $('#countButton');
const $clickCount = $('#clickCount');

$countButton.on('click', (e) => {
    let newCount = $clickCount.html() + 1;
    $clickCount.html(newCount);
});

위와 같이 jQuery에서는 원하는 카운트 값을 UI에 출력하기 위해서 ‘명령’을 내려 직접 DOM을 조작합니다. Selector를 이용해 UI 요소를 찾고, 직접 변화를 적용합니다.

class CountButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
    }
    click() {
        const { count } = this.state;
        this.setState({ count: count + 1 });
    }
    render() {
        const { count } = this.state;
        return (
            <button onClick={this.click.bind(this)}>
            	{count} Clicks
            </button>
        );
    }
}

ReactDOM.render(
    <CountButton />,
    document.getElementById('countButton')
);

반면 React에서는 count라는 state 값을 정의하고, count가 어떻게 출력될 것인지 ‘선언’만 합니다. 그 이후 React 내부에서는 자잘한 ‘명령’을 통해 DOM을 조작하여 원하는 결과물을 만들어줍니다. (내부에서는 imperative하게 작동됩니다)

위 공식은 선언형 UI의 방식에 대해 잘 보여줍니다. React를 대입해보자면 render()에서 상태 값에 따라 어떻게 출력될 것인지 ‘선언’만 해두면 어떤 state가 들어오든 간에 원하는 UI가 출력되게 됩니다.

장점

Selector로 기존 요소를 찾아 변경만 해주는 것과 달리 선언형 UI 개발에서는 state와 관련된 요소를 새로 그리게 됩니다. 이렇게 되면 지금 출력되는 UI를 파악하기 위해서 state와 선언부만 보면 됩니다. UI 요소를 ‘직접 명령' 하는 다른 곳이 있는지 신경 쓸 필요가 없지요. 새로 만드는 리소스에 대한 최적화는 프레임워크가 handling하기 때문에 개발자는 마음 놓고 state와 선언부만 신경 쓸 수 있습니다.

또한, 명령형 UI 개발에 비해 코드양이 적고 직관적입니다. 아래는 Flutter에서 homePage를 출력하는 코드입니다.

Flutter 에서 build는 UI 요소를 리턴하는 메서드입니다. 이 메서드 안에서 beverageList와 auth의 상태 값을 watch하고, 상태 값이 특정 값일 때 ( auth.when == unknown ) 특정 UI를 출력하는 것을 알 수 있습니다.

명령형 개발과 달리 서술적 문장은 인간에게 친숙하여 직관적으로 보입니다. 여기서는 Functional programming 방식의 라이브러리도 적용되어 각 상태에 대한 처리 또한 명확합니다.

마무리

선언형 UI 개발 프레임워크를 사용하고 있더라도, 종종 직접 명령을 내려 UI 요소를 다룰 일들이 생깁니다. 그때마다 지양해야 한다는 것은 인지하고 있지만 왜 지양해야 하는지에 대해서는 많이 생각해보지 않았던 것 같습니다.

이번에 정리하며, 앞으로는 예외 상황 속에서도 ‘지향’해야할 방식으로 개발하도록 노력해야겠다는 생각을 가졌습니다.

참조

https://ko.wikipedia.org/wiki/선언형_프로그래밍

https://www.reddit.com/r/javascript/comments/4kim6p/is_jquery_imperative/

https://docs.flutter.dev/development/data-and-backend/state-mgmt/declarative


커리어의 성장을 돕는 코멘토에서 언제나 함께 성장할 개발자를 기다리고 있습니다. 채용 페이지에서 코멘토가 어떤 회사인지, 어떤 사람을 찾는지 더 자세히 확인해보세요. 😊