React에 대한 개인학습을 기록합니다.
체크리스트
☑ | TITLE |
✔ | 연습용 레포 생성 |
✔ | 리액트 개요 확인 |
✔ | JSX다루기 |
✔ | 리액트 컴포넌트 |
리액트 스타일링 | |
컴포넌트 복잡하게 다루기 | |
속성 전달 | |
JSX 복잡하게 다루기 | |
상태 다루기, 카운터 설정 | |
데이터를 UI로 불러오기 | |
이벤트 다루기 | |
컴포넌트 생명주기 (생명주기 메소드) | |
DOM 엘리먼트 접근하기 | |
라우터를 통한 싱글 페이지 앱 구축 | |
Todo list 앱 제작 | |
리액트 개발 환경 구성 |
1. 리액트 개요
1.1. React 등장 이전, UI 제작 경향
1.1.1. 기존의 멀티 페이지 앱- 여러 개의 개별 페이지로 구성됨
- 앱의 상태관리에 매우 좋음
- 쿠키를 통한 사용자 데이터 저장과 서버 측 매커니즘(그것도 약간)을 제외하면 신경 쓸 게 없음
1.1.2. 최근 싱글 페이지 앱
- 서로 다른 페이지로의 이동이 없음
- 페이지를 리로딩하지도 않음
- 앱의 서로 다른 뷰가 동일한 페이지에서 로딩되거나 언로딩 됨
- 맞닥뜨리는 이슈
- 데이터와 UI 동기화에 많은 시간을 쏟음
- ex1. 사용자가 새 콘텐츠 로딩시 검색 필드를 완전히 초기해야 하는가
- 내비게이션 엘리먼트 활성화 탭을 보이도록 유지할 것인가
- 페이지에 어떤 엘리먼트를 남기고 제거해야하는가
- DOM이 너무 느림
- 엘리먼트 탐색, 자식 엘리먼트 추가, 하위 트리 제거 등의 DOM 작업은 매우 느림
- DOM: 사용자의 행위에 반응하고 새 콘텐츠를 보여주는 주된 방법
- HTML 템플릿 다루는 것은 꼬이기 쉽다
- 템플릿: HTML 코드 조각
- JS를 통해 템플릿 조작 혹은 데이터 채우는 작업은 금방 복잡해짐
- ⇒ 그러나 지금도 미래에도 멀티보단 싱글 페이지를 선호
1.2. React 특징
1.2.1. UI상태 자동 관리
- UI의 마지막 상태만 신경써라
- 시작 상태는 상관없다
- UI변경을 위해 지금까지 어떤 단계를 거쳤는지 상관없다
- 개발자는 상태 관리와 관련된 모든 상항을 더 이상 신경쓰지 않아도 된다
- 리액트가 UI가 제대로 표현되는 것을 보장하기 위해 필요 사항을 알아서 챙기니까.
1.2.2. 결합 용이한 UI를 지원하는 API
- 리액트는 가급적 비주얼한 요소를 여러 컴포넌트로 작게 쪼개어 다루길 권장
- 리액트의 핵심 API는 작은 비주얼 컴포넌트 제작을 쉽게 함
- 다른 컴포넌트의 결합을 통해 더 크고 복잡한 컴포넌트를 만들 수 있도록 지원
1.2.3. JS로 정의하는 비쥬얼
- 기존의 방식
- 특정 조건에 따라 UI를 바꾸고 싶다면 앱의 어딘가에서 반드시 JS를 작성해야 함
- 또는 별도의 프레임워크에 종속적인 템플릿 명령을 사용하여 만들어야 함
- 리액트의 방식
- JS만으로 UI를 정의함
- JS와 호환하면서도 JSX문법을 통한 비주얼 지정 옵션 제공
ReactDOM.render ( <div> <h1> A</h1> <h2> B</h2> </div>, destination );
- 비주얼코드와 JS가 같은 위치에 존재함
- 하나의 비주얼 컴포넌트 모양/동작 정의를 위해 여러 파일을 번갈아 볼 필요가 없음
- mvc 아키텍처의 ‘V’
- 비쥬얼 요소와 그 상태를 최신으로 유지하는데 중점인 View레이어에서 작동함
- 유연성이 있어 이미 익숙한 기술을 자유롭게 채택 가능
- 새로운 웹앱 개발뿐만 아니라 대량 코드 수정 없이고 기존 앱 개선에 유용
2. JSX 다루기 (리액트 웹앱제작)
2.1. 사전배경
• 웹앱: HTML, CSS, JS로 구성
◦ 이 구성이 아니면 브라우저는 뭘 해야하는지 모른다
• 리액트가 낀 웹앱: HTML, CSS, JS + JSX(리액트 코드)
◦ 그런데 브라우저는 JSX를 모른다
2.2. JSX를 브라우저가 이해할 수 있는 JS로 변환시키는 방법
2.2.1. Node.js와 그 외 빌드 툴 등으로 구성된 개발 환경 구축하기
- 빌드를 수행할 때마다 JSX의 모든 사하이 자동으로 JS로 변환됨
- 다른 일반적 JS파일처럼 참조될 수 있도록 파일이 디스크에 저장됨
- 기타 특징
- 초반에 복잡, 시간이 걸림
- 오늘날 현대적인 웹 개발의 대표적인 방식
- 여러 모듈과 빌드 툴, 그 외 복잡한 웹앱 관리의 필요한 많은 기능 이용
2.2.2. JSX를 자동 변환하는 JS라이브러리 사용
- 다른 자바스크립트 경우처럼 JSX를 직접 지정하면 됨
- 나머지 부분은 브라우저가 알아서 처리함
- 기타 특징
- 리액트 입문자가 사용할 방법
- 매번 jsx를 js로 변환하는데 소요되는 시간으로 인해 성능 저하 가능
- 실제 사용을 위한 앱 배포상황에서는 고려해야 함
⇒ 처음에는 두 번째 방법으로 진행, 후에는 첫번째 방법으로 되돌아 갈 예정
2.3. 실전: 시작하기
2.3.1. 시작 지점인 빈HTML페이지 제작 + title밑에 스크립트 추가
<!DOCYPE html>
<html>
<head>
<title>kyu! kyu! kyu!</title>
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
<script src="ttps://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
<script src="https://cdnjs.Cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<script>
</script>
</body>
</html>
- react, react-dom
- 핵심 리액트 라이브러리 추가
- 리액트가 DOM에 대해 작업할 떄 필요한 다양한 기능 추가
- babel-core
- 바벨, 자바스크립트 컴파일러 참조 추가
- 아직 보이는 거 없음.
2.3.1. 화면에 이름 보여주기
//script안에 작성
ReactDOM.render(
<h1>kim kyukyu</h1>,
document.body
);
• render 메소드
◦ 화면에 무언가를 보여주고 싶을 때 사용
<script type="text/babel"> //수정
ReactDOM.render(
<h1>kim kyukyu</h1>,
document.body
);
</script>
- 이 JS 안 HTMl과 같은 문법이 JSX의 전부다.
- document.body 인자
- JSX로부터 변환된 마크업을 DOM 안의 어디에 위치시킬 것인지 지정하는 것뿐임
- render메소드 실행시 h1태그가 문서의 body 앨리먼트에 위치하게 됨
2.3.2. css와 jsx문법을 통해 스타일 입히기
// head영역 안에 CSS 추가
<style>
#container {
padding: 50px;
background-color: #EEE;
}
#container h1 {
font-size:48px;
font-family:sans-serif;
color: #0080A8;
}
</style>
// body영역 안에 container 설정 적용시키기
<div id="container"></div>
<script type="text/babel">
var destination = document.querySelector("#container");
ReactDOM.render(React.createElement("h1", null, "kim kyukyu"), destination);
</script>
2.4. 총정리
- JSX언어
- 비주얼을 정의한다.
- UI요소 정의 외에 앱 빌드 방법을 바꾸게 함
- JSX를 JS결과물로 생성시키는 방법
- 바벨 라이브러리를 사용하기
- 성능이슈로 인해 공개용 앱에는 권장되지 않음
3. 컴포넌트 다루기
3.1. 개론
- 컴포넌트: 사용자가 앱을 사용할 때 보게 되는 비주얼과 그 상호작용 정의의 주된 방법
- JS의 함수
- 중복 코드 제거
- 인자를 통한 커스터마이징 (h1, h2, h3과 같은 것도!)
3.2. 실습: 컴포넌트 만들기
3.2.1. HelloKYU 베이스 버전
<!DOCYPE html>
<html>
<head>
<title>kyu! kyu! kyu!</title>
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
<script src="https://cdnjs.Cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
ReactDOM.render(
<div>
<p>Hello, KYU-Container world!</p>
</div>,
document.querySelector("#container")
);
</script>
</body>
</html>
3.2.2. HelloKYU 컴포넌트 버전
<!DOCYPE html>
<html>
<head>
<title>kyu! kyu! kyu!</title>
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
<script src="https://cdnjs.Cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var HelloKYU = React.createClass({
render: function(){
return(
<p>Hello, KYU-Container world!</p>
);
}
});
ReactDOM.render(
<div>
<HelloKYU/> {/* 컴포넌트 호출 JSX문법 */}
</div>,
document.querySelector("#container")
)
</script>
</body>
</html>
div엘리먼트로 감싼 것이 HelloKYU 컴포넌트
- 3.2.1.과 3.2.2.의 결과는 동일
3.3. KYUContainer (전: HelloKYU) 컴포넌트에서 속성 지정하기
3.3.1. 컴포넌트 정의 변경하기
: 인자를 받아들이도록 할 때 JS함수의 유용성이 명확히 드러난다
Step1. 속성으로 넘어온 값을 리턴할 수 있도록 컴토넌트의 동작을 변경
Step2. KYUContainer호출 부분을 설정하기
<!DOCYPE html>
<html>
<head>
<title>kyu! kyu! kyu!</title>
<script src="https://unpkg.com/react@15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15.3.2/dist/react-dom.js"></script>
<script src="https://cdnjs.Cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var KYUContainer = React.createClass({
render: function(){
return(
<p>{this.props.greetTarget}!, KYU-Container</p> // Step1
);
}
});
ReactDOM.render(
<div>
<KYUContainer greetTarget="Hi"/> {/* Step2 */}
<KYUContainer greetTarget="Bye"/>
<KYUContainer greetTarget="Hey"/>
</div>,
document.querySelector("#container")
)
</script>
</body>
</html>
3.3.2. 컴포넌트의 자식 다루기
<body>
<div id="container"></div>
<script type="text/babel">
var Buttonify = React.createClass({
render: function() {
return (
<div> {/* div -> 버튼 안에 자식 컴포넌트을 가지고 있음 */}
<button type={this.props.behavior}>{this.props.children}</button>
</div>
);
}
});
ReactDOM.render(
<div>
<Buttonify behavior="Sumbit"> KYU-World </Buttonify>
</div>,
document.querySelector("#container")
)
</script>
</body>
- behavior 커스텀 속성
- button 엘리먼트의 type 속성을 지정 함
- 컴포넌트의 render 메소드에서 this.props.behavior를 통해 접근 가능해짐
3.3.3. 컴포넌트 자식 접근 외의 단일/다중 컴포넌트에 대하여
- 현재 위 파일과 같이 단일한 자식 엘리먼트라면?
- this.props.children속성은 배열이 아닌 단일 컴포넌트를 리턴한다.
- 반면에, 자식 엘리먼트가 깊이 중첩된 구조의 최상위에 해당된다면?
- this.props.children속성은 배열을 리턴한다.
3.4. 정리
- 리액트 앱에선 컴포넌트를 사용은 암묵적으로 필수다.
- 불가능 하지 않지만, 리액트를 사용하는 의도에 맞지 않다
nodeJS, Spring, 로그 등에 대해 사전에 정리한 노션글도 포스팅 할 건데 많이 밀린다.