탄생의 순간, componentDidMount

692025년 10월 23일3

componentDidMount라는 새로운 생명주기 메서드가 팀에 공유되자, 개발자들은 즉시 이 메서드가 가진 가능성을 탐구하기 시작했다. 그들은 마치 새로운 장난감을 얻은 아이들처럼, 다양한 시나리오에 componentDidMount를 적용하며 그 유용성을 시험했다.

한 개발자는 사용자의 활동을 추적하는 분석 스크립트를 연동하는 작업을 하고 있었다. 이전 같았으면 페이지의 모든 <a> 태그에 jQuery를 이용해 클릭 이벤트를 일일이 붙여야 했다.

// 기존 방식 (jQuery)
$(document).ready(function() {
  $('a.trackable-link').on('click', function() {
    var linkId = $(this).data('id');
    Analytics.trackClick(linkId);
  });
});

이 방식은 페이지가 복잡해지면 어떤 링크가 추적되고 있는지 파악하기 어려웠고, 동적으로 새로 생성된 링크에는 이벤트가 적용되지 않는 문제가 있었다.

하지만 리액트와 componentDidMount를 사용하자, 모든 것이 달라졌다. 그는 추적이 필요한 링크를 <TrackableLink>라는 독립된 컴포넌트로 만들었다.

var TrackableLink = React.createClass({
  
  // 컴포넌트가 화면에 나타난 직후, 자신의 DOM 노드에만 이벤트를 건다.
  componentDidMount: function() {
    // React.findDOMNode(this)는 이 컴포넌트의 실제 DOM 노드를 반환한다.
    var linkNode = React.findDOMNode(this);
    
    linkNode.addEventListener('click', this.handleTrackClick);
  },

  handleTrackClick: function() {
    Analytics.trackClick(this.props.linkId);
  },
  
  // ... 컴포넌트가 사라질 때 이벤트를 제거하는 로직도 필요할 것이다.

  render: function() {
    return React.createElement('a', { href: this.props.href }, this.props.children);
  }
});

이제 분석 로직은 더 이상 전역 공간을 떠돌지 않았다. <TrackableLink> 컴포넌트 안에 완벽하게 캡슐화되었다. 이 컴포넌트가 렌더링되는 곳이라면 어디서든, 개발자는 별도의 작업 없이 자동으로 클릭 추적 기능이 적용된다는 것을 보장받을 수 있었다.

또 다른 개발자는 비디오 플레이어 컴포넌트를 만들고 있었다. 그는 componentDidMount 안에서 서드파티 비디오 라이브러리를 초기화했다.

var VideoPlayer = React.createClass({
  componentDidMount: function() {
    // 이 컴포넌트의 루트 DOM 노드를 찾아서,
    var videoContainer = React.findDOMNode(this);
    
    // 외부 비디오 라이브러리를 초기화하고 DOM에 연결한다.
    this.player = new ThirdPartyVideoPlayer(videoContainer, {
      source: this.props.videoUrl
    });
    this.player.play();
  },

  render: function() {
    // 비디오 라이브러리가 채워 넣을 텅 빈 div만 렌더링한다.
    return React.createElement('div', { className: 'video-container' });
  }
});

리액트는 자신이 직접 제어하지 않는 외부 라이브러리와도 자연스럽게 공존할 수 있었다. componentDidMount는 리액트의 통제된 세계와 외부의 예측 불가능한 세계를 잇는 안전한 관문 역할을 했다. 리액트는 UI의 구조와 상태를 책임지고, 외부 라이브러리는 componentDidMount를 통해 전달받은 DOM 노드 안에서 자신의 역할을 수행했다.

componentDidMount의 등장은 리액트의 생태계를 확장할 수 있는 무한한 가능성을 열었다. 리액트는 더 이상 혼자가 아니었다. 세상에 존재하는 수많은 자바스크립트 라이브러리들과 협력할 수 있는 방법을 찾은 것이다.

팀원들은 componentDidMount가 단순히 ‘코드를 넣는 공간’이 아니라는 것을 깨달았다.
그것은 선언적인 세계(리액트)와 명령적인 세계(DOM API, jQuery) 사이의 경계선이었다. render 안에서는 오직 선언적으로 UI를 묘사하고, DOM 조작 같은 명령적인 작업이 꼭 필요하다면, 그 경계선인 componentDidMount 안에서만 격리하여 수행한다.

이 명확한 역할 분리는 코드를 깨끗하고, 예측 가능하며, 안전하게 유지하는 강력한 원칙이 되었다. 컴포넌트의 ‘탄생의 순간’을 포착하는 이 능력은, 리액트를 한 단계 더 성숙한 프레임워크로 만들었다.