이번 섹션에서는
꽤 간단한 데모 프로젝트를 준비했습니다
이전 강의들에서 언급한
좀 더 내부적인 주제들에 대해
더 자세히 다뤄볼 수 있을 것 같습니다
간단한 카운터 프로젝트입니다
카운터를 설정하는 건 아직 가능하지 않지만
당연히 이번 섹션을 통해 배워보도록 하겠습니다
이 프로젝트를 쓰겠습니다
늘 그랬듯 로컬과 코드샌드박스 버전이 첨부되어 있습니다
이 프로젝트들을 사용해 제가 이전 강의들에서
언급한 중요한 주제들을 다뤄보겠습니다
자, 이 중요한 주제들을 다루기 위해서
핵심 질문들을 먼저 답해볼 텐데요
바로 리액트는 어떻게 DOM을 업데이트 하는가
리액트는 사용자가 보는 화면을 어떻게 업데이트하는가
그것과 관련해서, 컴포넌트 함수들을 어떻게 실행되는가 입니다
당연히 컴포넌트의 내용이
결국 화면에 보여지는 것이기 때문에
리액트가 어떻게 컴포넌트를 확인하는지
그리고 어떻게 실제 DOM을 그 컴포넌트들로부터 불러오는지
리액트 개발자로서 꼭 이해해야 하는 내용입니다
왜냐하면 그런 부분들이 여러분이
더 나은 코드와 앱을 쓸 수 있도록 해주기 때문입니다
그럼 이제 데모 앱을 시작해 봅시다
여러분을 위해 미리 준비해놨습니다
개발 서버를 켜고 여기서 실행 중입니다
이 코드샌드박스의 로컬 프로젝트 안에 있습니다
물론 아무것도 설치하거나 실행할 것이 없습니다
전부 잘 작동됩니다
이 프로젝트 안에는 여러 컴포넌트가 있습니다
늘 그렇듯 컴포넌트가 묶음으로 함께 작동됩니다
그리고 언제든 이 프로젝트 코드와
컴포넌트 구조를 살펴보시기 바랍니다
하지만 결과적으로 남는 컴포넌트들은
여기 이 버튼들과, 버튼 위에 아이콘
카운터 값과 헤더를
렌더링 하는 데에 필요한 것들입니다
자, 물론 여기 있는 모든 컴포넌트들이
예를 들어 앱 컴포넌트가 화면에
렌더링되고 있고 화면에 보이고 있습니다
그리고 이전 과정에서 배웠듯
컴포넌트를 화면에 렌더링한다는 말은 즉
리액트가 먼저 컴포넌트 함수들을 실행한다는 뜻입니다
예를 들어 앱 컴포넌트는
이 프로젝트의 앱 컴포넌트 함수로 시작합니다
왜냐하면 앱 컴포넌트가
가장 첫 번째 컴포넌트이자, 유일하게
메인 파일(main.jsx)에 참조되어있는 컴포넌트이기 때문에
가장 먼저 실행되는 코드 파일입니다
웹사이트가 로딩되는 시점의 이야기입니다
그리고 여기서는, 루트(root) 객체를 생성하고
앱 컴포넌트를 화면에 렌더링합니다
그리고 여기 이 코드 때문에
이 앱 컴포넌트 함수가 리액트를 통해 실행될 수 있는 겁니다
자, 제가 이전에 설명드렸듯이
즉 이 코드들은 전부 순차적으로 실행된다는 것입니다
앱 컴포넌트 함수 같은 경우에는
예를 들어 두 개의 상태가
컴포넌트에 등록되어 있다가
다른 코드들이 전부 실행되면
예를 들어 이런 함수들이 생성됩니다
중요한 건 이들은 실행되지 않고 그저 생성만 됩니다
그리고 나서는 이 JSX 코드가 실행되고
결과적으로 이 컴포넌트를 통해 반환합니다
전에 배웠듯이, 모든 컴포넌트 함수들은
렌더될 수 있는 것들만 반환해야 합니다
특히 JSX 코드, 가끔은 포털과 비슷한 것도
쓰이지만, 하지만 여기서는 JSX 코드입니다
그렇기 때문에 이 JSX 코드는 결과적으로
자바스크립트 코드로 변환되어야 하고
화면에 렌더될 수 있는 실제 요소로 변환되어야 합니다
그게 리액트가 하는 일입니다
자, 이 JSX 코드 안에를 보시면
내장 컴포넌트와 HTML 요소들이 있습니다
예를 들어 main, section, h2 같은 것들이 있죠
이 파란 컴포넌트들은
소문자 문자들부터 시작합니다, 기억나시죠?
그리고 여기 직접 쓴 컴포넌트들도 있습니다
대문자로 시작하는 Header와 Counter 같은 것들이죠
직접 쓴 컴포넌트들이
JSX 코드 내에서 실행될 때면
이런 식으로 이 코드를 반환하고, 리액트가 먼저
마찬가지로 이 컴포넌트들을 처음부터 끝까지
실행하는데 먼저는 Header 컴포넌트 함수부터입니다
나머지 코드를 실행하기 전에
리액트는 Header 컴포넌트 함수에 도달하여
함수들과 그 안에 코드들을 전부 실행시킵니다
이 경우에는 아주 간단한 함수입니다
오로지 내장된 요소를 갖고 있는
JSX 코드들만을 반환하기 때문에
컴포넌트 트리 내 이 부분에서의 리액트의 역할은 끝입니다
이 부부이 기억나시나요?
리액트는 컴포넌트 트리를 생성합니다
예를 들어, 이 앱에서는 무슨 뜻이냐면
상위에 앱 컴포넌트가 있고
하나의 자녀 컴포넌트인 이 Header 컴포넌트가 있습니다
하지만 이 Header 컴포넌트가
그 어떤 사용자 정의 컴포넌트도 갖고 있지 않기 때문에
트리의 가지는 여기서 끊기고 맙니다
하지만 트리가 궁극적으로 끝나는 것은 아닙니다
왜냐하면 앱 컴포넌트 안에는
이 Counter 컴포넌트가 있기 때문입니다
그렇기 때문에 리액트는, 마찬가지로
먼저 미리 이 컴포넌트를 실행시키고
이 컴포넌트도 속성을 받기 때문에
리액트는 이 chosenCount 라는 값을 전달합니다
이 앱 컴포넌트 안에서 다루는 상태 중 하나입니다
리액트는 이 값을 속성을 통해 컴포넌트에 전달하고
이 Counter 컴포넌트 함수가 실행될 때
실행되는 것이 여기
이 Counter 컴포넌트 함수여야 합니다
그리고 다시, 처음부터 끝까지 실행됩니다
예를 들어 이 함수는
이 initialCount의 값이
소수인지 아닌지 판단하는 함수인데, 실행된다고 해 봅시다
상태가 등록되고, 함수들이 생성되지만
아직 실행되지는 않습니다
그리고 이 JSX 코드가 실행됩니다
그래서 Counter 컴포넌트가 이 컴포넌트 트리에 추가됩니다
하지만 당연하게도, 이 JSX 코드 내 Counter 컴포넌트는
다른 컴포넌트들도 갖고 있으며
마찬가지로 리액트를 통해 실행되며
컴포넌트 트리에 추가됩니다
이 두 버튼은 IconButton 컴포넌트이며
Counter 컴포넌트 밑에 있는 트리에 추가되었고
CounterOutput 컴포넌트도 추가되었습니다
자, 이 IconButtons는 또 다른 컴포넌트를 받는데
속성을 통해 입력값으로 전달 받습니다
이 IconButton 컴포넌트나
이 컴포넌트 파일 안에서, 이 부분이
사용자 정의 컴포넌트로 렌더되고
이 전달받은 icon도 사용자 정의 컴포넌트로 렌더됩니다
그렇기 때문에, 이 icon 컴포넌트도 마찬가지로
컴포넌트 트리에 추가됩니다
트리는 여기서 끝이 나고
CounterOutput도 보시면 여기도 트리가 끝났습니다
왜냐하면 이제 더 이상 그 안에 사용자 정의 컴포넌트들이 없기 때문입니다
하지만 보시다시피, 여러 묶음의 컴포넌트들이 실행되는 중이고
이를 기록할 수 있는 기능도 제가 추가했습니다
여기 있는 모든 컴포넌트들에 말이죠
그래서 이 앱을 새로고침해서
개발자 도구을 열어보면
여기 기록된 로그가 보입니다
여기 보시면, 앱 컴포넌트로 시작해서
밑에는 Header와 Counter 컴포넌트
그리고 Counter 컴포넌트 안에는 IconButton도 보입니다
CounterOutput와 또 다른 IconButton이네요
IconButtons 밑에는 이런 Icon들이 있습니다
그리고 이게 결과적으로 컴포넌트 트리입니다
지금까지 보여드린 과정입니다
자, 아마도 전부 새로운 정보는 아니었겠지만
이 과정이 어떻게 작동하는지 알기 위해 꼭 필요한 시간이었습니다