컴포넌트
컴포넌트 : 재사용이 가능한 구성요소.
: 전반적인 UI(=컴포넌트의 결합) 구축 가능. 복잡도와 상관없이 모든 리액트 애플리케이션에서 사용됨.
-Header (헤더)
-Care Concept Items (주요 개념 항목)
-Interactive Tabs (상호작용 탭)
장점
: 복잡한 사용자 인터페이스를 관리하기 쉽도록 작게 분해하여 UI의 다른 위치에도 사용할 수 있게 해준다.
: 비슷한 코드는 함께 저장된다.
: 디자인과 개발 원칙을 따른다. 각 컴포넌트는 다른 기능이 있으므로 UI의 다른 부분을 처리한다.
JSX
JSX : 비표준의 자바스크립트 문법을 사용하기 때문에 사용한다. JavaScript 문법 확장자.
: 자바스크립트 파일 내에 html 마크업 코드를 작성해 요소를 생성하도록 함. 리액트에서 사용되는 JSX는 브라우저에 도달하기 전 개발서버에서 사용가능한 코드로 변환됨. 리액트 컴포넌트라는 점이 가장 중요. 이 확장자를 처리하는 것은 그 빌드 프로세스뿐이라는 것을 이해하는 것이 중요.
리액트에서 컴포넌트로 인식되기 위한 중요 규칙
1. 함수 제목 대문자 (내장된 요소가 아님을 알리기 위해, 구분 목적)
2. 함수에서 렌더링 가능한 값 반환. 대체로 HTML 마크업이 반환됨.
따라서 평범한 자바스크립트 함수를 만들고 함수 이름을 대문자로 하면 JSX코드가 반환된다.
컴포넌트 생성
예를들어,
헤더의 내용을 컴포넌트로 만들기 위하여 새로운 자바스크립트 함수를 만들어 주고 대문자로 시작하는 함수이름을 부여한 후 헤더 내용을 새로만든 함수 안에 괄호로 묶어서 넣어준다.
위의 헤더 내용을 커스텀 컴포넌트로 만들려면 아래의 코드처럼 만들어 주면 된다.
JSX의 강점은 JSX 코드 안에 html코드 같이 컴포넌트 함수를 사용할 수 있다는 점이다.
이제 리액트 컴포넌트를 App의 일부로 출력하고 싶다면 App컴포넌트에서 html 요소를 정의한 것과 같이 헤더 컴포넌트 함수 사용이 가능하다.
따라서 정의한 Header 함수 태그를 App컴포넌트에 작성해주면 된다.
컴포넌트 처리 과정
컴포넌트가 웹사이트에 어떻게 구현이 되었는지 완벽히 이해해보자.
웹사이트에서 소스코드를 보면 웹사이트 내용이 없는 것을 확인할 수 있다.
<script type="module" src="/src/index.jsx"></script> 코드로 index.jsx 파일을 받아오고 다시 App.jsx 파일에서 import 해온다. 정확히 말하면 앱 컴포넌트를 가져온다.
JSX 코드는 함수로 전환되지 않는다. 대신 값으로 사용되어 호출된 다른 메소드의 인수로 쓰인다. (ex. 렌더링 메소드)
import로 jsx 파일을 가져온 파일 위치에서 리액트 앱이 부팅된다. 즉, import로 불러들인 파일의 전반적 리액트 라이브러리에 속한 특별한 리액트 DOM 라이브러리에 있으며, 이로 인해 앱 컴포넌트가 결과적으로 렌더링 된다. 앱 컴포넌트의 내용을 화면에 출력하는 것을 담당한다.
위 코드는 html의 id=root안에 컴포넌트를 넣는 것을 의미한다. 따라서 커스텀 헤더 컴포넌트는 id=root안에 함께 존재하며, 이와 같이 createRoot와 렌더링 메소드가 단 하나의 루트 컴포넌트를 렌더링 하는 것이다.
앱 컴포넌트는 중첩된 컴포넌트가 있을 수 있고, 중첩된 컴포넌트는 자식 컴포넌트를 또 다수 갖고 있을 수 있다.
이런 방식으로 컴포넌트 계층구조가 설립되며, 컴포넌트 트리라고 칭한다.
또한 앱 컴포넌트와 커스텀 컴포넌트는 실제로 렌더링된 DOM에 나타나지 않는다. 기본 HTML 요소만 보여진다.
결국 컴포넌트 트리는 리액트가 분석만 하며, 컴포넌트에서 나온 모든 JSX 코드를 결합하여 전반적인 DOM을 생성한다.
즉, 화면에 보이는 요소를 말한다.
동적 값 출력
예를 들어,
세가지 용어를 임의로 선택하여 변동되게 하려고 한다.
그렇다면 내용을 동적으로 출력하는 과정이 필요하다.
위의 코드를 통해 랜덤으로 단어에 접근하는 함수를 정의하고 헤더 컴포넌트에 불변의 값이 아닌 무작위로 동적인 값이 들어가도록 해야한다.
위의 헤더 컴포넌트에서 <p>태그 안에 있는 Fundamental 부분을 동적인 값으로 랜덤으로 출력되도록 하려면 { }를 작성해주면 된다.
중괄호 사이에는 원하는 자바스크립트 표현을 자유롭게 추가할 수 있다. 그러면 표현코드가 실행이 되고 표현의 값, 계산 결과가 화면에 출력된다.
예를 들어,
중괄호 사이에 1+1을 넣으면 화면에 2라고 출력이 된다.
{ } : 불변동 내용과 동적 값을 혼합하는 문법
따라서 위의 코드를 실행시키면 웹페이지에서 새로고침을 할 때마다 배열에 저장된 단어들이 무작위로 변동되는 것을 확인할 수 있다.
또한 자바스크립트 표현을 상수나 변수에 저장하여 활용할 수도 있다.
JSX 안의 코드를 밖으로 옮겨주면 좀 더 간단한 코드를 작성할 수 있어 일반적으로 좋다.
동적 HTML 속성 & 이미지 로딩
위에서 동적인 값을 불러온 것처럼 이미지 로딩도 동적으로 가능하다.
그러나 아래의 코드처럼 파일 경로를 이용한 이미지 로딩은 페이지를 배포할 때 묶이는 과정에서 이미지가 사라질 수 있다는 위험이 존재한다.
따라서 다른 방법으로 import를 활용할 수 있다.
import를 활용해 파일을 선택하고 { }를 통해 소스의 속성 값으로 이미지를 로딩할 수 있다.
위에서 학습한 동적인 값 문법을 사용하는 것이다.
Prop (속성)
Props : 데이터를 컴포넌트로 전달하고 그 데이터를 재사용하는 곳에 사용할 수 있는 것.
1. 컴포넌트 재사용
매개변수 개념 덕분에 일반적인 자바스크립트 함수를 한번 정의하고 여러번 사용할 수 있는 것과 같다.
따라서 다른 데이터로 자바스크립트 기능을 구축하고, 재사용할 수 있듯 입력데이터가 다른 특정 리액트 컴포넌트를 구축하고 재사용할 수 있다.
예를들어,
새로운 컴포넌트를 정의하고, 새로 추가한 컴포넌트를 ul 리스트에 사용하려 한다.
목표는 여러번 재사용하는 것이나 사용할 때마다 다른 데이터를 전달하려 한다.
Props 개념을 활용하여 쉽게 작성이 가능하다.
커스텀 컴포넌트에 커스텀 속성을 추가할 수 있고, 속성은 원하는대로 정할 수 있다.
위의 코드에서 title, description 등을 props라 한다.
정말 모든 종류의 값을 props 값으로 전달할 수 있어 매우 중요하다.
따라서 리액트는 props 매개변수에 대한 값을 전달하고, 리액트 의해 매개변수를 위해 함수에 전달되는 값은 객체가 되어 모든 키 값의 쌍들을 보유하는 객체가 된다.
모든 커스텀 특성은 키(key)로, 속성(props)의 값은 값으로 그룹화된다.
따라서 키값 쌍들을 모두 가진 하나의 객체를 props 매개변수를 통해 얻는다.
이제 속성을 이용하여 동일한 컴포넌트를 다른 데이터가 있는 위치에서 사용이 가능하다.
2. props 대체 문법
동적인 값을 이용하여 속성을 설정할 수 있다.
아래의 코드를 통해 동일한 컴포넌트를 접근하는 항목의 인덱스에 따라 입력데이터가 달라져 동적인 설정이 된다.
따라서 속성 덕분에 컴포넌트를 재사용할 수 있다는 것을 확인할 수 있다.
그러나 이는 코드를 많이 작성해야함을 볼 수 있다.
최적의 상황을 만들기 위해 단축키가 존재한다.
코드를 위처럼 길게 작성하지 않고 스프레드 연산자를 사용하여 객체의 키값 쌍들을 뽑아내어 같은 결과를 도출할 수 있다.
아래의 코드를 활용하면 간단하게 코드를 작성할 수 있다.
또한 컴포넌트 함수 내에서도 짧은 방식으로 코드를 작성할 수 있다.
컴포넌트 분리 & 스타일 파일 저장
컴포넌트의 연관성이 매우 높거나 함께 있는 경우가 아니면 컴포넌트는 분리해 저장하는 것이 좋다.
컴포넌트를 분리하기 위해서는 해당 파일을 export하고 import해주어야한다.
예를들어,
헤더 컴포넌트를 다른 파일로 분리한다고 하면 다음과 같이 코드를 작성하면 된다.
새로운 Header.jsx 파일을 만들어 주고 함수를 옮긴 후 export한다.
옮겨온 파일에는 import를 이용해 헤더 파일을 불러오면 된다.
다음으로 분리한 컴포넌트 파일 옆에 해당 스타일 파일을 저장하려 한다.
헤더에 해당하는 모든 스타일 코드를 새로운 파일을 만들어 저장한다.
스타일 파일도 컴포넌트와 마찬가지로 import를 이용해 새로운 파일을 적용해주어야한다.
또한 스타일 파일은 분리하더라도 해당 컴포넌트에만 제한된 것이 아닌 모든 해당 코드에 적용이 된다.
이렇게 컴포넌트와 스타일을 분리하면 조절하는 것이 훨씬 쉬워진다.
"children" Prop
새로운 버튼을 만들기 위해 코드를 작성해주고 반복되는 버튼 컴포넌트를 새로운 파일로 형성해 분리한다.
아래와 같이 코드를 작성하면 오류는 생기지 않으나 TabButton 태그 사이에 존재하는 텍스트가 화면에 출력되지 않는다.
리액트가 텍스트를 출력할 위치를 모르기에 무시된다.
따라서 텍스트를 출력하기 위해 children prop을 사용해야한다.
children prop : 컴포넌트 텍스트 사이 내용을 의미한다.
이제 children prop을 사용해서 텍스트가 출력될 위치를 지정해주면 화면에 정상적으로 버튼이 만들어 진다.
또한 TabButton은 <Tabbutton label='Components' />로 코드를 작성해도 된다.
대신 label을 사용했으므로 동적인 값을 받는 부분도 children이 아닌 label로 바꾸어야 한다.
이벤트
버튼을 누르면 발생하는 이벤트를 만들기 위해 onClick prop을 사용한다.
onClick은 함수이기 때문에 함수를 먼저 미리 정의해두고 함수 이름을 받아서 사용하는 것이 좋다.
또한 버튼 아래의 콘텐츠 영역에 누르는 버튼에 따라 서로 다른 내용을 저장하고 싶다면 외부에 있는 컴포넌트에서 onClick을 받아와야 한다.
받아오는 prop의 이름은 자유롭게 정할 수 있다.
예를 들어,
onSelect라고 정해주고 정의한 함수를 내부 컴포넌트가 있는 파일로 옮겨 주고 onSelect에서 함수를 받아 사용하면 된다.
다음으로 정의한 함수에서 매개변수를 받아야한다.
예를들어,
selectedButton이라고 하고 onSelect에 함수를 만들어 주면 누르는 버튼에 따라 handleSelect에 다른 식별자를 수행할 수 있게 된다.
State
버튼의 콘텐츠 부분에 처음 표시될 문자를 아래와 같이 설정해주면 버튼을 눌러도 UI가 업데이트 되지 않는 것을 확인할 수 있다.
UI를 업데이트하려면 코드가 리액트에 의해 재평가 되어야한다.
그러나 현재의 컴포넌트 코드는 한번만 실행되기 때문에 UI가 업데이트 되지 않는 것이다.
데이터가 변하는 것을 리액트에게 알려주기 위해 사용하는 것이 state이다.
State : 리액트에서 처리되는 변수를 등록하는 것. 리액트가 제공하는 함수의 도움을 받아 업데이트된다.
이 변수들은 리액트 라이브러리에서 불러와야하는 특별한 함수인 useState의 도움으로 생성된다.
따라서 import 해줘야 하며, useState는 리액트 Hook이라 한다.
리액트 Hook : 일반함수이지만 리액트 컴포넌트 함수 또는 다른 리액트 Hook 안에서 호출되어야 한다는 점이 특별하다.
리액트 Hook에는 다음과 같이 두가지 규칙이 있다.
1. 컴포넌트 함수 안에서 바로 호출해야하며, 다른 코드 안에 중첩되면 안된다.
2. 컴포넌트 함수의 최상위에서 호출해야한다. (if문, loop도 불가능)
이제 데이터가 변경되면 Hook이 자긴이 속한 컴포넌트 함수를 활성화해 리액트에 의해 재검토된다.
useState가 반환하는 값은 변수나 상수에 저장한다.
반환되는 값은 배열이며, 이 배열에는 요소가 2개 존재한다.
따라서 요소이름은 원하는 대로 정할 수 있으며
예를들어,
첫번째 요소는 selectedTopic, 두번째 요소는 setSelectedTopic라 하겠다.
배열의 첫번째 요소는 컴포넌트 실행주기의 현재 데이터 스냅샷이 된다. 따라서 실행이 될때 초기값이 selectedTopic에 저장된다.
useState에서 반환된 배열의 두번쨰 요소는 항상 함수이다. 이는 상태를 업데이트하기 위해 실행되어 저장된 값을 업데이트한다. 또한 컴포넌트 함수를 다시 실행해야함을 리액트에 알려준다.
마지막으로 버튼을 누르지 않았을 때 초기에 콘텐츠 내용으로 사용할 문자를 지정하려고 한다.
방법으로는 3가지가 존재한다.
1. 삼항 연산자 사용
버튼이 선택되지 않으면 Please select a topic 이라는 문자가 뜨고 버튼이 선택되었다면 버튼에 대한 내용이 출력되도록 하는 방법이다.
2. && 사용
else의 내용을 제거하여 사용 가능하다.
3. 변수 사용
변수에 JSX코드를 저장한다. tabContent 변수에 초기 문자열을 저장한다.
이제 변수가 출력될 위치에 동적인 값을 받기 위한 아래의 코드를 적어주면 된다.
동적 CSS
리액트에서 클래스를 지정할 때는 className prop을 사용한다.
버튼을 선택했을 때 선택한 버튼을 구분하기 위해 동적으로 css를 구성하려한다.
먼저 탭버튼 jsx파일에 클래스를 지정한다.
그리고 컴포넌트의 버튼에 isSelected prop을 주어 동적으로 스타일이 적용되도록 해주면 된다.
리스트 동적 출력
현재 코드의 문제점은 리스트 데이터 중 손실이 생기면 앱이 오류가 생겨 망가진다는 것이다.
따라서 CoreConcept 컴포넌트 수를 동적으로 만들어 손실이 생겨도 자동으로 다시 화면이 정리가 되도록 하려한다.
map을 이용하여 함수가 자동적으로 새로운 배열을 입력받도록 한다.
따라서 이전에 인덱스별로 수동으로 접근했던 것을 map메소드를 통해 단계별로 접근할 수 있다.
또한 key prop을 이용하여 목록항목을 식별할 수 있는 고유한 값을 가지도록 해야한다.
'공부 > React' 카테고리의 다른 글
[React] 연습 프로젝트 1 (0) | 2024.01.17 |
---|---|
[React] Fragments, Feature, 틱택토 게임 등 (0) | 2024.01.16 |
[React] 자바스크립트 복습 2 (0) | 2024.01.10 |
[React] 자바스크립트 복습 1 (0) | 2024.01.09 |
[React] 시작하기 (0) | 2024.01.09 |