[React 1] 본질과 기본 구조

김헤일리·2022년 12월 3일
0

React

목록 보기
1/10

1. React App 둘러보기

📌 React 실행 시 처음에 나오는 UI 요소들은 어디서 왔을까?

  1. 터미널에서 "$ npm start" 혹은 "$ yarn start"와 같은 명령어를 사용해서 React 앱을 구동시키면, 이 도구는 src 폴더에서 index.js 라는 파일을 찾고, 거기에 적혀있는 코드대로 동작하게 된다.


  2. index.js 파일 오픈 시, < App / > 이라는 코드를 찾을 수 있는데, 이 코드를 삭제할 경우 Default UI도 함께 삭제되는 것을 알 수 있다.

    • < App / > App.js 로부터 온 태그이고, App.js에 있는 함수에서 Return되는 부분이 화면에 그려지는 UI인 것이다.

    • 즉, index.js 파일은 입구의 역할을 하는 것이다.

    • index.js 파일엔 전역적인 설정이 들어가있고, 그 중 App.js 함수에서 리턴되는 부분을 이용해 하나의 서비스를 제작할 수 있는 것!


  3. 그렇다면 index.js 파일에 있는 < id="root" > 인 부분은 어디서 왔을까?

    • index.html 파일을 보면, App 태그가 있는 부분에 ID Value가 "root"인 태그로 렌더링되라는 코드가 있다.
    • 예시:
    ReactDOM.render ( 
    //ReactDOM 파악 시, 렌더링 해라
    	<React.StrictMode> 
          <App />
          // App 컴포넌트에 있는 내용을, 
        </React.StrictMode>,
    	document.getElementById('root')
    	// document에 있는 id값이 root인 요소 안에
    • Id값이 root인 요소는 public directory라는 폴더에 있는 index.html 파일에 있다.

    • 해당 파일에서 "root"는 index.html에 있는 div 태그인데, React는 기본적으로 이 div 구역 안에 다양한 코드를 추가해서 화면에 출력하는 것이다.


📌 배포할 때 최적화를 하는 법

  1. 서비스를 배포한다면 배포하기에 가장 최적화된 배포본을 만들어서 배포를 해야한다.

    • 이 작업을 "빌드 (Build)"라고 한다

    • $ npm run build라는 코드를 터미널에 사용 시, Build라는 폴더가 생긴다

      • 폴더엔 많은 파일이 있는데 index.html과 같이 태그들 사이에 인덴트나 공백이 없는 파일이 있다.
      • 이것은 컴퓨터 파일을 읽어드릴 때 파일의 용량을 줄이기 위해서 가장 효율적으로 최적화한 것

  2. 빌드 명령 실행 시, 빌드 결과물을 서비스하게 되는데, 이때 serve라는 앱을 사용하기를 REACT에선 권장하고 있다.

    • serve는 웹서버이고, 해당 웹서버의 옵션 중 "-s"라는 옵션을 주게되면, 사용자는 어떤 경로로 들어와도 index.html 파일로 이동하게 된다.

    • 이때 경로에 build를 추가하면, 사용자가 이동하게 될 index.html 파일은 Build 폴더에 있는 최적화된 파일이다.



2. React의 본질:

📌 사용자 정의 태그 (Component)

  • REACT는 "사용자 정의 태그를 만드는 기술"이고, 이것이 REACT의 본질이다

  • 복잡한 코드를 하나의 태그로 이름을 붙여서 사용자 정의 태그를 만드는 것이다.

    • 사용자 정의 태그는 함수를 선언해서 만든다. 함수 생성 시, 함수의 이름은 대문자로 시작해야 한다. (ex. function Header() {})

    • 만들어진 함수가 리턴하는 내용은 html의 태그들이다.

    • 기본적으로 함수이기 때문에, 사용자 정의 태그들은 재사용성이 매우 뛰어나다.

  • 만들어진 함수를 다른 함수에 html 태그 형식으로 추가하면, 사용자 정의 태그의 내용이 그대로 그려진다.

    • 예시:
function Header(){ 
  // 3. App() 안에 모든 코드를 넣지 않고, 코드의 일정 부분을 따로 뺄 수 있다.
  // 이 따로 뺀 코드를 담고 있는 함수가 사용자 정의 태그로 사용되는 함수이다.
  return (
    <header>
      <h1><a href="/">WEB</a></h1>
    </header>
  )
}

function App() { // 1. 리액트에서 기본으로 제공하는 함수
  return (
    <div> // 2. 리턴되는 부분이 웹페이지에 그려지는 UI다.
      <Header></Header> 
      // 4. 위에 함수로써 빠졌던 부분을 태그로 만들어서 사용하고 있다.
      // Header()가 리턴하는 html 태그가 화면에 문제없이 그려진다.
      <Header></Header> 
      // 5. 만들어진 사용자 정의 태그는 재사용성이 뛰어나다.
      <Header></Header> 
      // 6. 이때 Header() 내용이 바뀐다면, App() 안에 있는 태그들의 내용도 자동적으로 일괄 수정된다.
    </div>
  );
}
  • React에선 사용자 정의 함수를 "컴포넌트 (Component)"라고 부른다.

    • 컴포넌트를 사용할 경우, 코드의 복잡도가 낮아지는 장점이 추가된다.

    • 일괄 수정이 가능하기 때문에, 유지보수 측면에도 편리성이 크다.

  • 컴포넌트는 일종의 부품이기 때문에, 외부에 공유하고, 공유받을 수 있다.

    • 부품을 나눠 사용할 수 있기 때문에 생산성이 획기적이고, 리액트의 생태계가 거대하게 성장하였다.


3. Component에 속성 추가하기

📌 React에서 속성(props) 전달하기

  • React는 컴포넌트에 속성을 줄 때, props 라는 단어에 담아서 전달한다.

    • props는 그냥 이름이기 때문에 아무 이름이나 사용해도 된다.
    • 보편적으로 사용하는 용어가 props 인 것.
  • 컴포넌트로 빼놓은 함수의 내용을 직접 수정하지 않고, 해당 함수를 태그로서 갖고 있는 메인 함수에서 해당 태그에 속성을 props를 통해 부여함으로서, 리턴되는 값을 바꿀 수 있다.

    • 예시:
function Header(props) { 
  // 2. <Header> 태그에 해당하는 함수의 첫번째 매개변수로 props를 주고
  console.log('props',props);
  // 3. props에 어떤 내용이 있는지 콘솔에서 확인하면
  // props 라는 객체의 title은 "React"라는 것을 확인할 수 있다. 
  // 그리고 props라는 객체가 갖고 있는 요소는 매우 많다. title은 그 중 하나일 뿐
  // title에서 "react"라는 값만 출력하고 싶다면, console.log('props', props, props.title) 이라고 했을 때 값만 출력할 수 있다.
  return (
    <header>
      <h1><a href="/">{props.title}</a></h1>
      // 4. return 값에 들어가는 구문에 {}을 이용해서 텍스트를 전달하면, 표현식으로 해석되기 때문에 props에서 추출한 값인 "React"가 출력된다.
    </header>
  )
}

function App() {
  return (
    <div> 
      <Header title="React"></Header> 
      // 1. 태그를 사용하는 함수에서 해당 태그의 title에 "React"라는 값을 준다면:
      <Header title="리액트"></Header>
      // 5. 동일한 <Header> 태그를 사용하지만, 해당 태그가 props로 전달받는 값은 "리액트"이다.
      // 그래서 최종 출력되는 값은 "React"라고 쓰여진 h1 태그와 "리액트"라고 적혀진 h1
      // 각각 다른 값을 가진 h1 태그가 2개 생성되는 것.
    </div>
  );
}

📌 props를 어떻게 사용하면 좋을까?

  • 함수 내부에 있는 태그에 props를 주입했을 때, 외부 컴포넌트의 리턴 값들이 주입되는 props의 값에 따라서 자동적으로 생성된다면?

  • 어떤 내용을 props로 줬을 때 내가 구현하고자 하는 부분이 자동 생산이 될 수 있을지 생각해야 한다.

    • 예시:
function Nav(props) {
// 3. App()에서 topics라는 이름으로 전달하는 배열을 props를 이용해서 옮겨 받는다.
  const lis = [] 
  // 4. topics에 들어있는 요소가 여러개기 때문에 빈 배열을 생성하고,
  for(let i = 0; i <props.topics.length; i++){
  // 5. 반복문을 돌려서 props로 받은 topics의 길이만큼 안에 있는 요소를 모두 확인한 후에, 
    let t = props.topics[i];
    // 6. props로 받은 topics의 특정 요소인 [i]를 t라는 변수에 담는다.
    lis.push(<li key={t.id}><a href={'/read/'+t.id}>{t.title}</a></li>
    // 7. 비어있던 배열 lis에 <li></li>를 추가한다.
  
    // 8. <li>의 제목을 동적으로 구성하기 위해 App()으로부터 받은 props 중 title을 {} 안에 추가한다.
  	// 8-1. props로 받은 topics의 특정 요소는 t라는 변수에 담겨있기 때문에, title이라는 topics의 특정 요소는 t.title로 접근할 수 있다.
  
  	// 9. <li>는 기본적으로 링크의 역할을 할 의도로 작성되었기 때문에 <a> 태그를 갖고 있다.
  	// 9-1. <a> 태그에서 href 속성을 통해 페이지를 이동하는데, 이때 각 <li> 마다 이동하는 고유 경로를 만들어야 한다.
  	// 9-2. 고유 경로를 동적으로 구성하기 위해 각 <li>의 고유값이 될 id를 경로에 심고 {} 안에 추가한다.
  	// 9-3. id 또한 props로 받은 topics의 특정 요소는 t라는 변수에 담겨있기 때문에, id라는 topics의 특정 요소를 t.id로 지정된다.

 	// 10. 각 <li>는 App()의 자식 객체이다.
  	// 10-1. 자식 객체는 고유 키값이 지정되어야 하기 때문에, 각 <li>마다 키(key)라는 고유값을 가진 프롭이 부여되야 한다.
  	// 10-2. key라는 prop에 id를 부여한다. (보통 id값을 unique값으로 사용한다.)
  return ( 
    <nav>
    	<ol>
    		{lis} 
    		// 그리고 완성된 배열 lis를 넣는다. 자바스크립트의 내용을 html 부분에 넣을 땐 {}사용 필수
          
          	/*
            <li><a href='/read/1'>html</a></li>
            <li><a href='/read/2'>css</a></li>
            <li><a href='/read/3'>javascript</a></li>
            */
    	</ol>
    </nav>


function App() {
  const topics = [
    {id:1, title:'html', body: 'html is...'},
    {id:2, title:'css', body: 'css is...'},
    {id:3, title:'javascript', body: 'javascript is...'}
  ]
  // 2. topics라는 상수 안에 배열을 만들고, <Nav> 안에 들어갈 카테고리들의 정보를 객체로 정리한 다음 배열에 집어넣는다.
  // 2-1. 각각의 카테고리는 id라는 고유값을 갖는다.
  return (
    <div>
    	<Nav topics = {topics}/>
      	// 1. <Nav>에 들어갈 카테고리는 각각 카테고리의 이름과 상세페이지의 내용이 들어갈 것이다.
      	// 1-1. 이 <Nav>라는 컴포넌트에 카테고리를 여러개 만들고 싶다고 가정했을 때, 
	</div>
  )
}

🔑 key prop의 용도 (간단 설명)

  • 리액트는 자동으로 생성하는 태그의 경우에는 리액트가 이 태그들을 추적해야 한다.

  • 태그를 추적할 때 근거가 필요한데, 이 근거로서 key라는 약속된 prop을 자동 생성하는 태그에 부여한다.

    • 예시의 < li > 같은 태그가 자동 생성 태그이다.
  • 리액트가 추적할 수 있도록 key라는 prop을 추가함으로서, 리액트의 성능을 높이고 리액트가 정확한 동작을 하는 것에 협조할 수 있다.



4. 리액트에 이벤트 기능 넣기

  • 컴포넌트에 이벤트를 추가할 경우, 특정 prop의 값으로 함수를 전달한다.
    • 예시: 태그 클릭 시 경고문 뜨기
function Header(props){
  return <header>
    <h1><a href="/" onClick={(event)=>{
      // 2. <a> 에 onClick이라는 이벤트를 건다. 리액트에 있는 html 태그는 유사 html태그기 때문에, 문법이 다르다. (카멜케이스와 중활호 사용)
      // 2-1. onClick의 콜백 함수로 들어가는 함수가 호출될 때, event라는 객체를 콜백함수의 첫번째 매개변수로 준다.
      // 2-2. 이벤트 객체는 이벤트 상황을 제어할 수 있는 여러 기능이 있다.
      event.preventDefault();
      // 3. 그 중, 기본적으로 제공하는 <a> 클릭 시 이동하는 것과 같은 기본 이벤트를 방지할 수도 있다.
      // 3-1. <a> 태그의 기본 동작을 방지할 경우, 클릭해도 reload가 일어나지 않는다.
      props.onChangeMode();
      // 4. 기본 이벤트가 방지되었을 때 비로소 App()에서 <Head>에서 props로 전달한 onChangeMode가 가르키는 함수를 호출할 수 있다.
      // 4-1. props로 onChangeMode를 가르키고, ()를 이용해서 함수를 실행하는 것이다.
    }}>{props.title}</a></h1>
  </header>
}

function App() {
  const topics = [
    {id:1, title:'html', body:'html is ...'},
    {id:2, title:'css', body:'css is ...'},
    {id:3, title:'javascript', body:'javascript is ...'}
  ] 
  return (
    <div>
      <Header title="WEB" onChangeMode={()=>{
        alert('Header');
      }}></Header>
      // 1. <Header> 링크를 클릭할 때 실행되는 함수를 만든다.
      <Nav topics={topics} onChangeMode={(id)=>{
        alert(id);
      }}></Nav>
    </div>
  );
}
  • 또 다른 예시: 경고문에 고유값 담기
function Nav(props){
  const lis = []
  	for(let i=0; i<props.topics.length; i++){
   		let t = props.topics[i];
    	lis.push(<li key={t.id}>
      	<a id={t.id} href={'/read/'+t.id} onClick={event=>{
        // 3. 링크 클릭 시 경고창이 뜨도록 하기 위해서 <a> 태그에 onClick 이벤트를 추가한다.
        // 3-1. onClick 이벤트가 일어날 때 이벤트가 감지되도록 첫번째 매개변수로 event를 준다.
        event.preventDefault();
        // 4. <a> 태그가 갖고있는 기본 기능을 끄기 위해서 preventDefault() 함수를 먼저 실행 시키고, 
        props.onChangeMode(event.target.id);
        // 5. App()에서 props로 전달해준 onChangeMode를 추가하고, 매개변수에 고유 id값을 주입해야한다
        // 5-1. 고유 id값을 주입하기 위해서 <a> 태그 내부에 id값을 부여한다.
        // 5-2. t라는 변수에 App()에서 보낸 props의 요소가 담겨있고, App()으로 부터 오는 id 값도 t에 담겨있기 때문에 {t.id}를 <a> 태그에 심는다.
       // 5-3. Nav() 함수 안에 있는 event를 일으키는 요소를 지정하기 위해 event.target을 설정하고, 그 target의 id를 가져오기 위해 매개변수는 결과적으로 event.target.id가 된다.
      }}>{t.title}</a>
    </li>)
  }
  return (
    <nav>
    	<ol>
      		{lis}
    	</ol>
  	</nav>
}


function App() {
  const topics = [
    {id:1, title:'html', body:'html is ...'},
  ] 
    return (
      <div>
        <Header title="WEB" onChangeMode={()=>{
          alert('Header');
        }}>
        </Header>
        <Nav topics={topics} onChangeMode={(id)=>{
        // 1. onChangeMode라는 prop을 만든다.
        // 1-1. props를 통해서 전달하는 함수의 첫번째 매개변수로 id를 전달한다.
          alert(id);
        // 2. 고유 값을 이용해서 각 <li>별로 고유값이 적혀있는 경고창을 리턴한다.
        }}>
        </Nav>
      </div>
  )
}

출처: 생활코딩 React 2022년 개정판 1~6

profile
공부하느라 녹는 중... 밖에 안 나가서 버섯 피는 중... 🍄

0개의 댓글