-
(React) 6 - React 학습 정리 및 복습개발/React 2024. 2. 7. 10:58
■ React 란?
: 리액트란 Facebook 에서 만든 JavaScript 사용자 인터페이스(UI) 라이브러리이다.
■ React 를 사용하는 이유
그렇다면 기존 웹개발에서 왜 React 가 주목을 받고 있을까?
1. 화면 전환의 부드러움 (SPA + Virtual DOM)
현재 토스, 인스타크램, Naver Vibe(Vue) 사이트를 들어가면 화면 전환이 부드럽게 진행된다.
이는 React 나 Vue 와 같이 SPA 의 특징이다.
SPA 는 최초 생성된 DOM (Document Object Model) 을 유지하면서 변경 사항만 업데이트를 한다.
여기서 이를 도와주는 것이 바로 Virtual DOM 이다.
Virtual DOM 은 실제 DOM 의 복제본(자바스크립트 객체로 표현된 DOM)으로,
웹 개발자들이 변화를 주고 싶은 부분만 Virtual DOM 에서 수정하게 된다.
그 후, React는 Virtual DOM 과 실제 DOM 사이의 차이점을 찾아내어,
그 차이점만 실제 DOM 에 반영하여 불필요한 화면의 갱신을 최소화하여 성능을 향상시킨다.
React 는 이처럼 html 하나만 이용하고 그 안에는 Component 를 활용하여 UI 에 변동을 준다.
이는 지속적으로 데이터를 UI 에 나타내는 애플리케이션에 유리하다.
하나의 예시로 오프라인 교육 당시 프로젝트를 가져왔다.
해당 사진은 프로젝트 root app의 layout.js 이다.
여기서 RootHeader 와 RootSideMenu 는 레이아웃으로 고정시킬 부분이다.
이 부분은 각각 RootHeader.js 과 RootSideMenu.js 파일에 함수형으로 컴포넌트하여 위치에 맞게 넣어주었다.
그렇다면 우리가 페이지 전환은 어떻게 할까?
페이지 전환은 레이아웃은 고정한 채 page 에 해당하는 부분만 변경시킬 예정이다.
※ layout.js 와 page.js
● layout.js
- 모든 페이지에 공유되는 루트 레이아웃 파일: 반드시 <html> <body> 태그가 있어야 된다.
● page.js
- 프로젝트의 루트 경로(라우팅)의 페이지 컴포넌트 정의 파일사진과 같이 빨간 표시를 한 부분만 클릭 시 전환이 되는 것이다.
이는 위에 layout.js 사진에 {children} 을 통해 라우팅되는 페이지 컴포넌트가 들어가게 된다.
첫화면의 경우 루트의 page.js 가 들어가게 되고, 이후에는 각 조건에 맞는 page.js 가 들어가게 돼서 화면이 전환된다.
이처럼 변하지 않는 부분은 그대로 두고 변화하는 부분만
각 컴포넌트의 변화를 주는 방법을 사용하는 것이 바로 react 이고
react 는 이런 부분으로 화면 깜빡임 없이 부드럽게 페이지가 전환된다.
2. 편의성
React 는 JSX 문법을 사용한다.
JSX 는 JavaScript 를 확장한 문법으로, 하나의 파일에 자바스크립트와 HTML 을 동시에 작성한다.
더불어 자바스크립트에서 HTML 작성하듯 작성하므로 가독성이 높고 작성하기 편한 부분이 있다.
다음 코드처럼 JavaScript 안에서 함수형 프로그래밍으로 코딩을 하고 HTML 요소를 추가할 수 있다.
이렇게 만들어진 코드는 export default 를 통해 하나의 함수형 컴포넌트가 될 수 있다.
※ JSX(JavaScript XML)
- 자바스크립트에 XML 을 추가한 코드
- 컴포넌트의 UI 부분을 정의할 때 작성
- JSX 는 모두 JavaScript 로 변환된다.
따라서 사용 시 자바스크립트가 읽을 수 있도록 { } 표시를 해줘야 한다.
3. 재사용 및 다양성
이렇게 만들어진 컴포넌트를 사용할 수 있다.
컴포넌트를 사용하면 각 부분 부분을 컴포넌트화할 수 있으며
다양하게 UI를 구성하고 다른 곳에 필요하다면 재사용도 가능하다.
※ 컴포넌트란?
: 재사용 가능하고 조립 가능한 독립적인 UI 객체
- 클라이언트 컴포넌트와 서버 컴포넌트(Next.js 13버전부터 지원) 로 나뉜다.
- app 폴더 안 컴포넌트는 기본 서버 컴포넌트이며, 상단에 'use client' 작성 시 클라이언트 컴포넌트가 된다.
4. React Native
리액트의 UI 를 만드는 기능이 웹이 아닌 플랫폼에서도 활용할 수 있다.
따라서 React Native 를 통해 안드로이드와 아이폰 모바일 앱을 만드는 대표적 기술로 널리 쓰인다.
※ 단 React 와 React Native 가 같다는 것이 아니다.
결론적으로 시대에 변화에 맞춰 사용자가 보기 편한 리액트를 요구하는 프로젝트에 대비하고,
모바일 회사로서 React Native 를 통한 앱개발도 대비해야 하기 때문에 React 를 학습해야 한다.
※ DOM 이란?
: 문서 객체 모델(Document Object Model) 로 웹페이지(HTML 이나 XML) 의 콘텐츠 및 구조, 스타일 요소의 문서를
트리 구조의 노드로 표현하고 프로그래밍 언어가 해당 문서에 접근하여 읽고 조작할 수 있도록
API 를 제공하는 일종의 인터페이스이다.
JavaScript(스크립팅 언어) 를 사용하여 이러한 노드를 조작할 수 있다.
DOM 은 웹페이지의 요소에 동적으로 접근하고 수정하는데 사용되며,
웹어플리케이션 동적 기능 구현에도 중요한 역할을 한다.
※ React 와 React Native 의 공통점과 차이점
● 공통점
- JavaScript 언어 사용
- 컴포넌트 기반으로 개발
- JSX 문법 사용
● 차이점
=> React 의 방식으로 네이티브 앱을 만들기 위해 React Native 가 등장한 것
문서 객체 모델 DOM 과 자바스크립트 JavaScriptㅣ생성 방식 및 접근 방법 - 코드스테이츠 공식 블로그 (codestates.com)
리액트(React)를 왜 사용해야 할까? - 리액트가 강력한 이유 (modulabs.co.kr)
React란, 프론트엔드 대표 개발 도구 리액트의 특징과 이점 I 이랜서 블로그 (elancer.co.kr)
React 배우기 전에 쓰는 이유부터 알아야 - 코딩애플 온라인 강좌 (codingapple.com)
■ JSX 작성 방법
1. 컴포넌트에 여러 요소 있을 경우 감싸야 한다.
오른쪽과 같이 div 하나의 부모 요소로 감싸야 한다.
2. 끝 태그 작성
3. JSX 내부에 출력할 내용이 있는 경우 { } 표현식 사용
● { } 표현식에서 작성 가능한 것
- 실행문(변수 및 상태값 읽기, 연산식, 함수호출)
- 컴포넌트 또는 JSX 태그● { } 표현식에서 작성할 수 없는 것
- 제어문(if, for, while)은 올 수 없음따라서 if 문 대신에 삼항 연산자 또는 &&, || 연산자를 활용한다.
4. class 대신 className 사용
5. 스타일은 객체 형태 / 카멜 표기법으로 작성
6. 주석 작성도 { } 안에 작성해야 한다. return 윗부분은 // 로 작성 가능
■ props 와 state
리액트에서 중요한 개념은 props 와 state 이다.
● props
props 는 컴포넌트 태그의 속성들로 구성된 객체로, 부모가 설정하는 값이다.
따라서 다음 코드에서 각각의 속성이 props 객체로 생성된 것을 볼 수 있다.
컴포넌트 내 내용은 children 으로 전해진다.
이렇게 생성된 props 객체는 자식 컴포넌트에서 함수의 매개값으로 사용된다.
● state
react 는 상태를 불변성을 지킨다.
불변성이란 어떤 값을 직접적으로 변경하지 않고 새로운 값을 만들어내는 것이다.
즉 필요한 값을 변형해서 사용하고 싶다면 어떤 값의 사본을 만들어서 사용해야 한다.
그렇다면 왜 상태를 그대로 사용하는 것이 아니라 복제하여 사용하는지 의문이 든다. (객체, 배열)
그 이유는 앞선 DOM 이야기와 연결된다.
React는 Virtual DOM 과 실제 DOM 사이의 차이점을 찾아내어, 그 차이점만 실제 DOM 에 반영한다.
따라서 DOM 비교를 위해 이전 상태를 보존해야 하기 때문에 원본은 보존하고 깊은 복제를 하여 사용한다.
컴포넌트의 상태와 관련된 Hook 은 다음과 같다.
● useState(): 상태 생성 및 초기화
● useEffect(): 상태 변경 후 콜백되는 함수 등록
상태는 다음과 같이 선언한다.
1. 기본타입
const [상태변수, 상태변경함수] = useState(초기값)
상태의 경우에 반드시 상태 변경 함수를 이용해 상태값을 변경해야 한다.
왜냐하면 react 가 상태가 변경된 것을 인지하고 리렌더링하여 새로운 변경값을 보여줘야 하기 때문이다.
2. 객체타입
const [상태변수, 상태변경함수] = useState({...})
여기서는 상태 변경 시 복제 객체를 생성하고 수정한 값을 제공해야 한다.
...state 를 통해 복제된 객체를 생성하여 사용한다.
다음과 같이 입력을 받아 변경값을 넣어주는 이벤트를 위해서는 두 가지 방법이 있는데
밑줄친 내용은 이전 객체 값을 받아 복제하고 달라진 값만 업데이트 하는 방법이다.
※ 참고로 이벤트 속성 값은 함수 호출
코드가 아니라 함수 자체를 전달해야 한다.
- onChange={handleChange()} (x)
- onChange={handleChange} (o)
- onChange={() => {handleChange();}} (o)
상태 변경 시 주의할 점은 매개값으로 값이나 객체를 주는 경우 연이은 상태 변경이 안된다.
다음 코드를 봤을 때도 위에는 값을 통해 전달했기 때문에
상태 변경 시 2 가 돼야 하는데 마지막 업데이트만 적용된 것을 확인할 수 있다.
따라서 연이은 상태 변경을 하고자 한다면 매개값을 아래와 같이 함수로 전달해야
우리가 원하는 값 2를 얻을 수 있다.
React에서 불변성을 지켜야 하는 이유 (tistory.com)
■ state 와 props 연동
state 와 props 에 대해 알아봤다.
먼저 부모 컴퍼넌트에 있는 상태값을 자식 컴포넌트 UI 에 사용하고자
한다면 반드시 props 로 전달하고 사용해야 한다.
다음과 같이 부모 컴퍼넌트에서 자식 컴포넌트로 imgFile 를 props 객체를 통해 전달한다.
그러면 아래와 같이 props.imgFile 을 통해 화면 UI 에 보여줄 수 있다.
그렇다면 자식 내부에서 props 를 통해 이미지를 변경하고자 하면 어떻게 할까?
자식은 부모가 전달한 props 를 직접 변경할 수 없다.
따라서 같이 부모 컴포넌트에서 자식 컴포넌트에 props 로 상태 변경 함수를 전달해준다.
부모가 props 로 전달한 상태 변경 함수 호출을 onClick 이벤트를 통해 진행해준다.
이렇게 이벤트로 상태 변경 함수가 호출되면 조건에 따라 이미지를 변경할 수 있게 된다.
setImgFile 을 통해 상태를 변경해주면 정상적으로 이미지 변경이 가능하다.
■ 컴포넌트 라이프 사이클
● 컴포넌트 세 가지 상태
1. 마운트
- 컴포넌트 DOM 이 최초로 생성되는상태
- 페이지에 컴포넌트 추가
2. 업데이트
- DOM 이 수정되는 상태
- State 가 변경될 때
- props 가 변경될 때
- 부모 컴포넌트가 리렌더링 될 때
3. 언마운트
- DOM 이 제거되는 상태
- 페이지에 컴포넌트가 제거
■ useEffect() 를 이용한 콜백 등록
이러한 라이프사이클에서 useEffect() 를 이용한 콜백 등록도 가능하다.
return 위 함수 코드에 작성하면 마운트 혹은 업데이트 후 실행되며,
return 안 함수코드에 작성 시 언마운트 혹은 업데이트 전 실행이 된다.
두 번째 매개값을 생략하면 마운트/언마운트
업데이트 전/후로 매번 실행된다.
※ 매번 그런것이 아니고 만약 리턴 함수 밑에 console.log 코드가 없다면
언마운트/업데이트 전에는 실행되지 않는다.
두 번째 매개값을 빈 배열로 주면 마운트 혹은 언마운트 될 때 한 번만 실행한다.
다음과 같이 매개값이 배열로 전해지면 마운트/언마운트
관심 값이 업데이트 전/후 될 때 실행된다.
이도 위와 같이 위치에 따라 실행 여부가 달라진다.
■ 실습해보기 (Legacy)
public 안에 index.html 파일이 바로 우리가 보여지는 화면이다.
해당 화면에는 id root 값이 있다.
index.js 파일을 가면 다음과 같이 ReactDOM.createRoot 가 있다.
ReactDOM.createRoot 를 통해 루트 트리를 생성하고 이 트리는 DOM 에 대한 렌더링 작업을 수행한다.
root 라는 위에서 본 ID를 가진 DOM 요소를 루트로 설정하는 것이다.
그리고 이 루트를 렌더링 할 때 아래 <APP/> 이라는 컴포넌트를 넣는다.
즉, ROOT를 랜더링할 때 아래 APP 도 렌더링 하게 돼 APP 에 있는 부분이 보이는 것이다.
따라서 우리는 APP.js 를 통해 우리가 원하는 작업을 하면 된다.
index.html 이라는 하나만 이용하고 그 안에 컴포넌트들로 화면을 구성하는 SPA 방식인 것이다.
나의 경우 실습을 위해 간단하게 만들어 보았다.
클래스 컴포넌트 생성을 위해 Component 를 상속받는다.
상속을 받으면 React 라이브러리에서 제공하는 기능과 메서드 이용이 가능하다.
※ 최근에는 함수형 컴포넌트와 훅을 받는 오프라인 교육이 일반적으로 바뀌었다고 한다.
그리고 상태를 정의해준다.
앞에서 말한 것처럼 변수가 아닌 상태로 정의하여 리렌더링 될 수 있게 설정해주고,
변경이 있을 경우 반드시 상태값을 복사해서 변경해준다. (DOM 객체 비교 필요)
나의 경우 기본 페이지를 welcome 으로 지정하여 첫 화면을 출력해 주었다.
getContent() 함수를 통해 화면을 불러왔다.
모드별 화면 출력을 다르게 설정하기 위해 if 조건문을 걸어주었다.
welcome 모드일 경우에는 welcome 상태의 제목, 상세, 사진을 넘겨주었다.
부모 컴포넌트에서 사용한 내용을 자식 컴포넌트에서 사용하기 위해서는 props 사용이 필요하다.
각 항목이 눌리면 하단에 문구가 바뀌도록 설정해본다.
부모 컴포넌트에서 props 로 ChangeMiddle 과 data 를 전달한다.
새로운 배열을 선언하고 while 반복문을 통해 배열안에 값을 넣어준다.
여기서 각 항목을 클릭했을 때 이벤트 함수를 실행시켜주는데,
SPA 특성상 화면 전환을 없게 하기 위해 e.preventDefault() 로 막아준다.
ChangeMiddle 인자로는 구분할 수 있는 id 값을 넣어준다.
아래 return 을 통해 해당 배열이 나오게 된다.
자식 컴포넌트에서 받아온 값을 우리가 위에서 state 에서 정의한 selected_middle_id 상태로 바꿔준다.
이는 다음에 나올 함수에서 변화한 id 값에 해당하는 contents 내용을 보여줄 때 사용할 것이다.
참고로 넘어온 값은 String 으로 넘어오므로 Number 함수를 통해 숫자로 바꿔준다.
getcontent 함수가 실행되면 read 모드이기 때문에 다음의 else if 가 작동한다.
getReadContent() 를 보면 상태의 contents에 있는 data[i].id와 우리가 앞서 저장했던 선택했던 id this.state.selected_middle_id 를 비교하게 된다.
while 문을 돌면서 우리가 선택한 값과 id 값이 일치하는 i 를 반환하게 되고 그에 맞는 contents 를 보여준다.
따라서 최종적으로 우리는 목록 클릭 시 그에 맞는 값을 반환하게 되고,
그 값은 _content 에 담기게 되어 article 안에 있는 ReadContent 의 prps 로 전달되어
최종적으로 _article 을 출력하게 된다.
따라서 우리는 목록 클릭 시 화면이 전환 되는 것을 확인할 수 있다.
■ Next.js 기반 실습
다음과 같이 Next.js 기반으로 변경했다.
이전과 다르게 클래스가 아닌 함수형 컴포넌트를 사용했다.
하단에는 화면을 새로고침하면 랜덤하게 사진이 나오는 컴포넌트를 추가했다.
사진이 나오는 부분만 컴포넌트화 시켰다.
따라서 만약 내가 다른 곳에서 랜덤으로 사진이 나오길 희망한다면 해당 부분을 재사용 할 수 있게 된 것이다.
'개발 > React' 카테고리의 다른 글
(React) 9 - 감정 일기장 프로젝트 1 (0) 2024.02.14 (React) 8 - 간단한 일기장 프로젝트 (0) 2024.02.13 (React) 5 - React 오프라인 교육 2 (0) 2024.02.05 (React) 4 - React 오프라인 교육 1 (1) 2024.02.01 (React) 2 - 생활코딩(React) 2 (0) 2024.01.23