코규리
article thumbnail

React에 대한 개인학습을 기록합니다.

 

체크리스트

TITLE
연습용 레포 생성
리액트 개요 확인
JSX다루기
리액트 컴포넌트
리액트 스타일링
컴포넌트 복잡하게 다루기
속성 전달
JSX 복잡하게 다루기
상태 다루기, 카운터 설정
데이터를 UI로 불러오기
이벤트 다루기
컴포넌트 생명주기 (생명주기 메소드)
DOM 엘리먼트 접근하기
라우터를 통한 싱글 페이지 앱 구축
Todo list 앱 제작
리액트 개발 환경 구성

 


13. 싱글페이지 앱 제작하기

SPA에선 완전히 새로운 페이지가 로딩될 일이 없다. 동일한 페이지 안에서 인라인으로 뷰가 로딩된다


 

13.1. SPA(Single page app) 기대사항

  • 주소 표시줄에 보이는 URL은 항상 현재 보고 있는 화면의 URL을 유지한다
    • 앱을 네비게이션을 하는 동안 적합한 URL을 보여줘야 함
  • 브라우저의 이전 버튼과 다음 버튼을 사용할 수 있어야 한다
    • 브라우저 방문 기록에 넣어지도록 해 사용자가 이전버튼과 다음 버튼을 제대로 사용할 수 있게 해야 함
  • 적합한 URL을 이용해 특정 뷰(deep link)를 바로 보기를 원한다
    • 사용자가 특정 뷰를 북마크에 저장했을 경우 나중에 선택했을 때 정확히 그 뷰를 보여주도록 해야 함

사항을 SPA에서 직접 구현해야 한다.

13.2. 진행할 사항

이걸 만들 거임.

13.3. 마크업과 코드 준비

<!DOCYPE html>
<html>

<head>
    <title>KGYURY</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>

    <style>

    </style>
</head>

<body>
    <div id="container"></div>
    <script type="text/babel">
        var destination = document.querySelector("#container");

        ReactDOM.render(
            <div>
                <p>I'm KGYURY</p>
            </div>,
            destination
        );
    </script>
</body>
</html>

13.3.1. 참조 스크립트, 리액트 라우터 추가

//script 추가
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/2.8.1/ReactRouter.min.js"></script>
  • 이제 react, reactDOM, babel에서 router library 까지 사용할 수 있음

13.3.2. 초기 프레임 보여주기

  • 항상 정적으로 남아있는 페이지의 일부가 존재할 것이다
    • 이 정적인 부분 = 앱 프레임(app frame)
    • 앱 프레임 ⊂ HTML 엘리먼트, 헤더, 푸터, 네비게이션 등을 포함
var App = React.createClass({
    render: function() {
        return (
            <div>
                <div>
                <h1>KGYURY SPA</h1><ul className="header">
                    <li>Home</li>
                    <li>Next</li>
                    <li>Next2</li>
                </ul>   
            </div>
        </div>
            
        )
    }
});
ReactDOM.render(
    <div>
        <App/>
    </div>,
    destination
);

13.3.3. 라우터 관련 추가하기

ReactDOM.render(
        <ReactRouter.Router>
            <ReactRouter.Route path="/" component={App}>


            </ReactRouter>
        </ReactRouter.Router>,
        destination
    );
</script>
  • Router 컴포넌트: 리액트 라우터 API의 일부
    •     어떤 URL에 어떤 화면을 보여줄지 정의하는데 필요한 여러 속성을 가짐
    •     path 속성:URL경로 지정, component 속성: 보여주고자 하는 컴포넌트의 이름 지정
      •         이곳에서는 path로 ‘/’, component로 ‘App’ 지정
      •         즉, url에 루트가 포함될 경우 App을 보여주겠단 뜻
  • 컴포넌트 안에 라우팅 설정을 하였음
    •     라우팅 설정: URL과 뷰 사이의 매핑

13.3.4. Home 뷰에서 보여줄 콘텐츠 작성

var Home = React.createClass({
    render: function() {
        return(
            <div>
                <h2> 🐶 강아지 </h2>
                <p>어린 개를 일컫는 순 우리말, 소의새끼는 송아지 말의 새끼는 망아지라고 부르는 것과 같은 어법을 따라 만들어진 용어.
                강아지를 줄여 강쥐라고 부르는 경우도 존재하며, 비슷한 단어로서 강아지의 경상도 사투리로 간지가 있다.
                전라도 사투리로는 어원의 개+아지가 그대로 합쳐진 이름인 갱아지가 있으며, 보통 어르신들만 쓴다. </p>
                <p> *'갱얼쥐'라는 말도 있는데, 이는 예부터 쓰인 말은 아니고 젊은 층에서 장난으로 꼬아서 발음하는 것이다. </p>
                </div>
        );
    }
});

//App 컴포넌트에 다음 코드 추가
<div className="content">
    <Home/>
</div>
  • 정상 작동하나 잘못된 방법임
    • 사용자가 앱 내비게이션에 맞춰 콘텐츠의 다른 부분들을 로딩해야함 ⇒ 복잡한 것임
  • 후에 이 문제를 해결할 예정

13.3.5. css 적용하기

body{
    background-color: #a2cfa0;
    padding: 20px;
    margin: 0;
}
h1{
    font-family: 배달의민족 을지로체
}

h2{
    font-family: 정선아리랑 혼
}

ul,ol{
    font-family: 나눔손글씨 다행체; font-size: 20
}

p,li  {
    font-family: 나눔손글씨 범솜체, Helvetica, Arial, sans-serif; font-size:22
}
ul.header li{
    display: inline;
    list-style-type: none;
    margin: 0;
}

ul.header{
    background-color: #111;
    padding: 0;

}
ul.header li a{
    color:#fff;
    font-weight: bold;
    text-decoration: none;
    padding: 20px;
    display: inline-block;
}
.content{
    background-color: #fff;
    padding: 20px;
}
.content h2 {
    padding: 0;
    margin: 0;
}
.content li{
    margin-bottom: 10px;
}

13.3.6. 코드 정리하기

ReactRouter 접두사 생략

//script안 최상단에 작성
var { Router, 
  Route, 
  IndexRoute, 
  IndexLink, 
  Link} = ReactRouter;

13.3.7. 올바르게 Home View 이용하기

//App component의 content div내부 코드 수정
<this.props.children/>

//ReactDOM.render 내부, route 안에 추가
<Router>
    <Route path="/" component={App}>
        <IndexRoute component={Home}/>
    </Route>
</Router>,
  • 리액트 라우터를 통해 현재 URL구조에 맞게 컴포넌트를 처리하도록 함
    • Route컴포넌트 안에 중첩된 또 다른 Route컴포넌트를 통해 URL과 뷰 매핑을 정의

13.4. 네비게이션 링크 만들기

: 이미있는 네비게이션 일레먼트에 링크를 적용하기

13.4.1. 내비게이션 엘리먼트 코드 변경

//App컴포넌트 내의 li엘리먼트 수정
<ul className="header">
    <li><Link t0="/">Home</Link></li>
    <li><Link t0="/Next">Next</Link></li>
    <li><Link t0="/contact">Next2</Link></li>
</ul>

 

  • 리액트 라우터의 Link컴포넌트 사용 (a태그와 동일하나 더 많은 기능을 제공함)
    •     주소 표시줄에 표시될 URL값을 지정함
    •     리액트 라우터에게 네비게이션하라 대상을 알려주는 역할을 함

13.5. 나머지 작업

13.5.1. next, next2 추가

var Next = React.createClass({
	render: function() {
	  return(
	      <div>
	          <h2> 🐱 고양이 </h2>
	          <p> 포유류 식육목 고양잇과의 대표정익 동물이다. 반려동물로써 가축화된 대중적인 동물이지만 그만큼 많은 수가 유기되기도 한다. 이에 따라 도시에 적응하거나 아예
	              야생 생태계까지 영향을 주게되는 들고양이도 생겼다. 현존하는 모든 고양잇과 동물들은 대략 2000만년 전에 하나의 조상으로부터 갈라져 나온 것으로 추측된다. </p>
	          <p> *중현견에 육박하거나 덩치가 큰 품종도 존재한다. 메인쿤이나 랙돌 등. </p>
        </div>
	  );
	}
});

var Next2 = React.createClass({
	render: function() {
	  return(
	      <div>
	          <h2> 🐹 햄스터 </h2>
	          <p> 설치류 쥣과 동물이며 쥐목 비닫ㄴ털주시과 비단털쥐아과에 속한 포유류를 뜻한다. 건강한 햄스터는 비단처럼 털이 곱고 부드럽다. 기르는 주인들은 애정으로 햄쥐 또는 햄찌라는 귀여운 어감의
	              애칭으로 부른다. 1990년대에 들어서부터 흔히 볼 수 있게 되었으며, 2000년 방가방가 햄토리 애니메이션으로 방송 방영 이후 대중적 인지도가 상승했다. 특유의 귀여운 외형, 작고 동글
	              동글한 체형 때문에 비교적 인기가 많으나 모든 애완동물이 그렇듯이 철저한 관리가 필요하다. </p>
	          <p> 실험용으로 쓰기 위해 야생의 햄스터를 잡아서 기르기 시작했던 것이 최초의 햄스터 사육이었다.</p>
        </div>
	  );
	}
});

13.5.2. 액티브 링크

//css추가
.active{
    background-color:#6f946e
}

//App컴포넌트를 다음과 같이 수정
<li><IndexLink to="/" activeClassName="active">Home</IndexLink></li>
<li><Link to="/Next" activeClassName="active">Next</Link></li>
<li><Link to="/Next2" activeClassName="active" >Next2</Link></li>

//ReactDOM.render 수정하기
<Route path="/" component={App}>
    <IndexRoute component={Home}/>
    <Route path="Next" component={Next} />
    <Route path="Next2" component={Next2} />
</Route>

  • Link인스턴스에 activeClassName이라는 속성 설정하기
    • 링크가 액티브하게 되면 CSS클래스의 이름을 지정
  • IndexLink엘리먼트에서 Home 콘텐츠를 지정하도록 바꾸기    

 


14. Todo List 앱 만들기


사용자가 원하는 텍스트 필드에 입력 Add 누르면 화면에 나타나도록 할 것임.

14.1. 초기상태

<!DOCYPE html>
<html>

<head>
    <title>To KYU List</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>
    <style>

    </style>
</head>

<body>
    <div id="container"></div>
    <script type="text/babel">
        var destination = document.querySelector("#container");
        ReactDOM.render(
            <div>
                <p>To-KYU List</p>
            </div>,
            destination
        );
    </script>
</body>
</html>

14.2 UI꾸미기

14.2.1. To Kyu List 컴포넌트

var TodoList = react.createClass({
            render: function() {
                return(
                    <div className = "tokyuListMain">
                        <div className="header">
                            <form>
                                <input placeholder="enter task">
                                </input>
                                <button type="submit">add</button>
                            </form>
                        </div>
                    </div>
                )
            }
        })

14.2.2. css

body{
    padding: 50px;
    background-color: #9ce4a0;
    font-family: 나눔명조 에코 Bold;
}
.tokyuListMain .header input{
    padding: 10px;
    font-size: 16px;
    border: 2px solid #fff;
    
}
.tokyuListMain .header button {
    padding: 10px;
    font-size: 16px;
    margin: 10px;
    background-color: #20b179;
    color: #FFF;
    border: 2px solid #20b179;
}
.tokyuListMain .header button:hober{
    background-color: #009959;
    border:2px solid #009959;
    cursor: pointer;
}

14.3. 기능구현

14.3.1. 사용자의 텍스트 필드 입력 제출 기능

  • 텍스트 입력 후, 폼 제출마다 이전에 존재하는 텍스트에 더해야 함
  • 배열에 새로 제출된 텍스트가 추가될 때마다 그 텍스트를 화면에 보이도록 해야 함
  • 이벤트와 이벤트 핸들러를 이용하여 사용자가 제출한 텍스트를 정확히 배열에 추가해야 함

14.3.2. 상태 객체 초기화하기

var toKyuList = React.createClass({
		getInitialState: function() {
		    return{
		        items: []
		    };
		},
  • getInitialState메소드는 컴포넌트가 렌더링되기 전에 호출됨
  • items배열은 this.state.items를 통해 컴포넌트 어디서든 접근 가능함

14.3.3. 제출 처리

//getInitialState 함수 밑에 작성
addItem: function(e) {
},

//ToKyuList의 render안 form엘리먼트 수정
<form onSumbit={this.addItem}>
  • onSubmit이벤트를 리스닝 하도록 작성함 (form엘리먼트의 onSumit이벤트에 addItem 핸들러를 링크)
    • 폼이 제출될때마다 이 이벤트가 발동

14.3.4. 상태 채우기: 배열에 텍스트 넣기

//form엘리먼트 내부에 작성
<input ref={(task) => this._inputElement =task} 
    placeholder="enter task">
</input>
  • ToKyuList컴포넌트가 마운트 되고 해당 코드 실행시, 생성된 input 엘리먼트의 참조가 _inputElement속성에 저장됨
//addItem 이벤트 핸들러 채우기
addItem: function(e) {
	    var itemArray = this.state.items;
	    itemArray.push(
	        {
	            text:this._inputElement.value,
	            key:Date.now()
	        }
	    );
	
	    this.setState({
	        items: itemArray
	    });
	
	    e.preventDefault();
	},
  • itemArray 배열 변수를 만듦
  • text와 key로 구성된 객체를 추가했음
    •     text: input엘리먼트의 텍스트 값 저장
    •     key: 현재 시간을 저장
      •         제출되는 모든 데이터에 대한 유일한 key값을 갖도록 하는 것이 목적임
  • state객체의 items속성에 itemArray를 설정함
  • e.preventDefault()
    •     기본 onSubmit이벤트를 오버라이드, 즉 동작을 재정의하게 해줌
    •     onSubmit이벤트의 기본 동작 수행을 막고, 불필요하게 페이지 refresh를 유발하는 POST동작의 부작용 없이 addItem 메소드만 호출되도록 하였음

14.3.5. 보여주기

  • 속성 하나를 지정하여 ToKyuList 컴포넌트의 state객체에 있는 items배열을 전달해야 한다
  • toKyuEntries변수를 추가,
  • ToKyuList컴포넌트의 this.state.Item값을 기반으로 하는 entries속성 값을 이 변수에 저장
  • toKyuEntries변수는 각 ‘할 일’과 그 키를 갖는 객체의 배열을 저장함

14.3.6. CSS추가

.tokyuListMain .header button:hober{
            background-color: #009959;
            border:2px solid #009959;
            cursor: pointer;
        }
        .toKyuListMain .theList{
            list-style: none;
            padding-left: 0;
            width: 255px;
        }
        .toKyuListMain .theList li{
            color: #333;
            background-color: rgba(255,255,255,.5);
            padding: 15px;
            margin-bottom:15px;
            border-radius: 5px;
        }

14.3.7. 입력 필드 텍스트 초기화

//ToKyuList의 addItem 함수 안에 코드 추가
this._inputElement.value="";

 


15. 개발환경


15.1. nodeJS

  • JSX를 JS로 변환하는 데 필요한 단계를 엮는 목적으로 노드를 사용

15.2. Babel

  • JS 트랜스파일러
  • 최신식 JS 혹은 JSX를 대부분의 브라우저가 이해할 수 있는 자바스크립트로 변환해줌

15.3. Webpack

  • 모듈 번들러
  • 앱에 필요한 관련 코드들만을 포함시키게 함
    •     앱에 사용되는 여러 프레임워크/라이브러리는 각 컴포넌트의 일부에 불과한 서로 다른 많은 기능에 의존
      •         이러한 사용하지 않을 모든 코드를 앱에 포함시키기 않게끔 함.
    •     여러 곳으로부터 모든 관련된 코드들을 하나의 파일로 꾸려 줌
  • 리액트 라이브러리, JSX파일, JS 관련된 부분들을 하나의 파일로 묶는데에 웹팩 이용