2. UI 구현하기
프로젝트 준비를 모두 끝마쳤다면 UI를 구현하겠습니다. [할 일 관리] 앱의 UI 구현은 페이지의 전체 레이아웃부터 먼저 만들고, 세부 요소는 순서에 따라 차근차근 만들 예정입니다.
페이지 레이아웃 만들기
다음 그림은 이 프로젝트에서 구현할 [할 일 관리] 앱의 최종 형태를 UI 관점에서 보여 줍니다.

[할 일 관리] 앱의 UI 요소는 마치 핸드폰을 웹 브라우저 위에 올려놓은 것처럼 좌우 여백이 넓으며 페이지의 정중앙에 자리 잡고 있습니다.
먼저 App.js에서 다음과 같이 <h2> 태그를 추가합니다.
코드를 불러오는 중 입니다 ...src/App.js
다음에는 index.css에 작성된 스타일 규칙은 모두 삭제하고 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...① <body> 태그의 margin을 0px로 설정합니다. margin은 여백이라는 뜻으로 0px로 설정하면 페이지의 외부 여백이 전부 사라집니다.
다음에는 App.css에 작성된 스타일 규칙은 모두 삭제하고 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...① [할 일 관리] 앱 페이지의 최대 너비를 500px로 고정합니다
저장하고 레이아웃이 잘 만들어졌는지 확인합니다.

App에는 3개의 자식 컴포넌트 Header, TodoEditor, TodoList를 각각 세로로 배치할 예정입니다. App에 배치할 자식 컴포넌트를 아직 구현하지 않았으므로, 임시 요소를 만들어 대신 배치하겠습니다.
App.js를 다음과 같이 수정합니다.
코드를 불러오는 중 입니다 ...저장하고 렌더링 결과를 확인합니다.

페이지의 요소를 모두 세로로 배치했지만, 요소 사이에 간격이 없어 답답해 보입니다. 이때는 App 컴포넌트의 display 속성을 이용하면, 요소의 배치간격을 좀 더 보기 좋게 만들 수 있습니다.
다음과 같이 App.css를 수정합니다.
코드를 불러오는 중 입니다 ...① display는 페이지의 요소를 브라우저에서 어떻게 보여줄지 결정하는 속성으로, 기본값은 block 입니다. block은 배치 요소들을 한 줄로 꽉 채우며 세로로 배치합니다. display 속성을 flex로 설정하면 요소를 수직이 아닌 수평으로 배치합니다. 그리고 gap과 같이 요소의 간격을 조정하는 속성을 추가로 사용할 수 있습니다. display 속성을 flex로 적용한 요소는 다른 요소를 감싸는 컨테이너라고 하여, 특별히 ‘플렉스 컨테이너(Flex Container)’라고 합니다.
요소의 간격이 잘 설정되었는지 렌더링 결과를 확인합니다.

요소의 간격이 적절히 떨어져 있음을 알 수 있습니다. 이렇게 App 컴포넌트의 스타일링을 모두 마무리하였습니다.
Header 컴포넌트 만들기
이번에는 페이지 최상단에 위치할 Header 컴포넌트를 만들겠습니다.
src에 이 프로젝트의 컴포넌트 파일을 한곳에 모아 둘 component 폴더를 만듭니다. 계속해서 component 폴더에 Header.js를 생성하고 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...src/component/Header.js
Header 컴포넌트를 페이지에 렌더링하려면 App의 자식으로 배치해야 합니다.
코드를 불러오는 중 입니다 ...src/App.js
App 컴포넌트의 return 문 안에 임시로 Header 역할을 수행했던 요소를 제거하고 실제 Header 컴포넌트를 작성했습니다. 저장하고 렌더링 결과를 확인합니다.

다음으로 Header 컴포넌트가 오늘의 날짜를 렌더링 하도록 다음과 같이 수정합니다.
코드를 불러오는 중 입니다 ...① 문자열 ‘오늘은’ 옆에 있는 달력 모양의 이모지는 윈도우 이모티콘으로 <window>+<.>(마침표) 키를 누르면 나옵니다. 여기서 적절한 이모지를 골라 사용하면 됩니다. 이모지는 문자열로 취급하므로 일반 문자열을 입력해도 상관없습니다.
계속해서 component 폴더에 Header 컴포넌트를 스타일링하기 위한 Header.css를 생성하고 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...① <h1> 태그 요소의 여백을 0으로 하고 글꼴 색을 지정합니다.
작성한 스타일 규칙을 컴포넌트에 적용하려면 Header.css를 Header.js에서 불러와야 합니다.
코드를 불러오는 중 입니다 ...src/component/Header.js
① Header.css 파일을 불러와 작성한 스타일 규칙을 적용합니다.
저장한 다음, 스타일을 잘 변경 했는지 렌더링 결과를 확인합니다.

페이지에 렌더링한 날짜는 여러분이 실습하고 있는 당일 날짜가 표시됩니다. 이 책의 결과와는 다르다는 점에 주의합니다.
TodoEditor 컴포넌트 만들기
계속해서 할 일 아이템을 생성하는 TodoEditor 컴포넌트를 만듭니다.

component 폴더에 컴포넌트와 스타일을 정의할 TodoEditor.js와 TodoEditor.css 를 각각 생성합니다.
그리고 TodoEditor 컴포넌트에 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...src/component/TodoEditor.js
다음에는 App에 TodoEditor 컴포넌트를 자식으로 배치합니다.
코드를 불러오는 중 입니다 ...src/App.js
저장한 다음, TodoEditor 컴포넌트를 페이지에 잘 렌더링하는지 확인합니다.

렌더링 오류가 발생한다면 파일명을 제대로 작성했는지, 스타일 파일을 바른 경로로 불러오는지 확인하길 바랍니다.
다음으로 TodoEditor의 UI를 만듭니다.
코드를 불러오는 중 입니다 ...src/component/TodoEditor.js
TodoEditor 컴포넌트의 UI를 만듭니다. 컴포넌트는 요소의 제목, 할 일 아이템을 생성하는 입력 폼, 클릭하면 실제 할 일 아이템을 생성하는 버튼으로 구성되어 있습니다.
다음에는 TodoEditor 컴포넌트를 스타일링하기 위한 스타일 규칙을 작성합니다
코드를 불러오는 중 입니다 ...src/component/TodoEditor.css
① 입력 폼과 버튼을 감싸는 요소에 스타일을 설정합니다. 너비 100%, display는 flex 속성을 적용합니다. 자식 요소의 간격은 10px입니다.
저장한 다음, 페이지에서 렌더링 결과를 확인합니다.
코드에서는 입력 폼을 클릭하면 폼의 경계선을 푸른색으로 표시(input:focus)하도록 구현했습니다. 입력 폼을 클릭해 푸른색 경계선이 나타나는지도 확인합니다.

TodoList, TodoItem 컴포넌트 만들기
[할 일 관리] 앱의 `TodoList에는 TodoItem 컴포넌트가 여러개 있습니다. 따라서 이 두 컴포넌트를 함께 만들겠습니다.
TodoList 컴포넌트 만들기
먼저 TodoList 컴포넌트부터 만들겠습니다.

컴포넌트와 스타일을 정의하는 TodoList.js와 TodoList.css를 각각 생성합니다. 다음과 같이 TodoList 컴포넌트를 작성합니다.
코드를 불러오는 중 입니다 ...src/componen/TodoList.js
TodoList를 App 컴포넌트의 자식으로 배치합니다.
코드를 불러오는 중 입니다 ...src/App.js
저장한 다음, TodoList 컴포넌트가 페이지에 나타나는지 렌더링 결과를 확인합니다.

TodoList 컴포넌트는 크게 할 일 아이템을 조회하는 검색 폼과 조회한 할일 아이템을 목록 형태로 보여주는 리스트 두 부분으로 구성되어 있습니다. 검색 결과에 따라 TodoItem 컴포넌트를 리스트로 페이지에 렌더링해야 합니다.
먼저 TodoList 컴포넌트 상단에 위치할 검색 폼부터 만들겠습니다.
코드를 불러오는 중 입니다 ...src/component/TodoList.js
TodoList 검색 폼의 스타일링을 위해 TodoList.css를 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...src/component/TodoList.css
저장하고 페이지에서 렌더링 결과를 확인합니다.

검색 폼에서 검색어를 입력하면 조건에 일치하는 할 일 아이템이 하단에 리스트로 출력됩니다. 아직 TodoItem 컴 포넌트를 만들지 않았으므로 할 일 아이템을 출력하지는 못합니다.
TodoItem 컴포넌트 만들기
다음 그림과 같이 TodoList에서 낱낱의 할 일 아이템을 표현하는 TodoItem 컴포넌트를 만들겠습니다.

component 폴더에서 컴포넌트와 스타일을 정의하는 TodoItem.js와 TodoItem.css를 각각 생성합니다.
TodoItem.js에서 다음과 같이 작성합니다.
코드를 불러오는 중 입니다 ...src/component/TodoItem.js
① 할 일 아이템 가장 왼쪽에는 할 일 완료 여부를 표시하는 체크박스를 배치합니다.
TodoList에 TodoItem 컴포넌트 배치하기
TodoItem에 스타일을 적용하기 전에 TodoList에 이 컴포넌트를 배치해야 합니다. 다음과 같이 TodoList.js를 수정합니다.
코드를 불러오는 중 입니다 ...src/component/TodoList.js
① 여러 개의 할 일 아이템을 리스트로 보여줄 <div> 태그 요소를 배치합니다. 지금은 리스트로 보여 줄 할 일 아이템이 없습니다. 따라서 임시로 그 역할을 수행할 컴포넌트 TodoItem을 3개 배치합니다.
3개의 TodoItem을 TodoList 컴포넌트의 자식으로 배치했습니다.
저장한 다음, 페이지에서 렌더링 결과를 확인합니다.

결과를 보니 리스트로 배치한 3개의 아이템은 간격이 없어 답답 해보입니다.
아이템 사이에 적절한 간격을 주려면 부모 컴포넌트인 TodoList에서 여러 개의 TodoItem을 감싸고 있는 ‘list_wrapper’ 요소에 스타일링을 적용해야합니다.
TodoList.css 파일에 다음 내용을 추가합니다.
코드를 불러오는 중 입니다 ...src/component/TodoList.css
저장한 다음, 개발자 도구에서 스타일링이 바르게 적용되었는지 렌더링 결과를 확인합니다.
[Element] 탭에서 class="list_wrapper"를 찾아 클릭하면 할 일 리스트가 모두 하이라이트되는 것을 확인할 수 있습니다.

이제 TodoItem 개별 요소의 스타일링을 위해 TodoItem.css에서 다음과 같은 스타일 규칙을 작성합니다.
코드를 불러오는 중 입니다 ...src/component/TodoItem.css
마지막으로 렌더링 결과를 확인합니다.
이렇게 [할 일 관리] 앱의 UI 구현을 모두 완료하였습니다. 이제 App 컴포넌트에서 경계를 확인할 필요가 없으니, App.css의 border 속성은 제거 또는 주석 처리합니다.

src/App.css
최종적으로 완성된 UI는 다음과 같습니다.

UI 구현을 흔히 ‘퍼블리싱’ 또는 ‘UI 개발’이라고 합니다. UI 개발은 데이터를 가공하고 상태를 관리하는 구현 기능과 더불어 프론트엔드 엔지니어의 기본 소양 중 하나입니다. 가볍게 여기지 말고 꾸준히 학습하면서 충분한 경험을 쌓는 게 꼭 필요합니다.