티스토리 뷰

※ react 폴더 구성 ※

react 폴더 구성

-package.json 의존성 파일 설정

-node_modules : 의존성 파일 다운로드 폴더. package.json에 설정된 것이 저장됨.

-public 폴더는 안 건드림

-src 폴더

 

1. 리액트의 기초 개념

-리액트 : 컴포넌트를 여러 개 생성하여 컴포넌트를 조합해 하나의 화면을 구성

 jsp나 spring에서 header, footer를 미리 만들어 놓고 필요할 때, 로딩(include)하여 사용하는 것과 동일

 

(1) 리액트의 기본 구성요소 3

컴포넌트 JSX props
실제 구현될 화면, js 파일 html과 js가 합해진 형태의 문법 각 컴포넌트끼리
데이터를 주고 받기 위한 객체.
일종의 매개변수

-기존에 jsp, html 역할을 컴포넌트가 함. 페이지 구성.

그런데, 화면을 그리기 위한 소스 코드를 전부 순수 자바스크립트로 생성하기 힘들기 때문에

JS + XML로 이루어진 JSX라는 문법을 사용하여 html 화면을 쉽게 구성

 

 

(2) 컴포넌트

-public index.html : 메인 화면

 (src / index.js에서 설정)

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <!-- ★ 리액트에서 사용하는 index.js 파일이 찾는 id 값-->
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

 

-index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App'; //App.js 파일을 App이라는 이름으로 불러왔음.
import reportWebVitals from './reportWebVitals';

/*DOM 객체 : $(document)ready(function(){});
              document는 현재 html 
  reactDOM 가상 html 문서 만듦.
  document.getElementById를 기준으로
  reactDOM : 리액트의 가상돔 의미
  createRoot : 리액트의 가상돔 생성
*/
/*
render : 리액트의 가상돔을 사용하여 실제 화면을 그려줌
StrictMode : 기본 자바스크립트는 느슨한 언어 문법을 사용하는데, StrictMode는 강력한 규칙을 적용함. 타입 맞춰주는 것 등. ex) '5' == 5 연산
<App /> : 사용자 컴포넌트, 실제 리액트를 이용하여 생성한 화면
*/
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
  //App이라는 이름으로 불러온 App.js. 그 안의 <div class="App">의 내용이 호출되고 출력됨.
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

-App.js

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    //div안의 내용이 index.js에 불려감.
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

 

>> 내용 수정해보기_변경사항 바로 적용되는지

App.js

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    //div안의 내용이 index.html의 <App /> 부분에 그려짐
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>처음 사용하는 리액트</h1>
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

>> 추가로 입력한 '처음 사용하는 리액트' 내용이 바로 적용된 것을 확인할 수 있음.

 

(2) 새로운 App 생성

-App2.js 생성

-src 아래에 파일 생성

function App2(){
    return (
        <div>
            <h1>App2 파일 생성</h1>
            <h2>추가로 한번 만들어 보았음 :)</h2>
        </div>
    );
}
export default App2;

 

-index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App'; //App.js 파일을 App이라는 이름으로 불러왔음.
import reportWebVitals from './reportWebVitals';

import App2 from './App2'; //★

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <App />
    <App2 /> //★
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

(+) App.js에 임포트(import)

import logo from './logo.svg';
import './App.css';
//import './App2'; 보통은 여기에 import 해서 사용함.

function App() {
  return (
    //div안의 내용이 index.html의 <App /> 부분에 그려짐
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>처음 사용하는 리액트</h1>
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
//export 빼먹으면 import로 뭘 가져와야 하는지 모르기 때문에 누락하면 안 됨.

 

(3) JSX

-Potato.js 생성

import React from 'react'; //이 코드가 있어야 리액트가 JSX를 이해

function Potato(){
    return <h3>I love potato</h3>;
}

//export : 해당 파일을 외부에서 import할 경우 외부에서 지정한 함수, class, 변수 등을 사용할 수 있도록 설정하는 명령어
//default : 해당 파일을 import할 경우 기본적으로 사용할 수 있는 함수, class, 변수로 등록

//export 설정
export default Potato;
//1번 방식
//export {Potato} from Potato;
//2번 방식
//export {Potato};

 

-index.js에서  import

import Potato from './Potato';

 

(?!) 어떨 때, 변경사항이 바로 적용되지 않는다고...?

그럴 때, CMD가서 yarn start 새로 해주면 됨(컴파일 새로)

 

(3-2) 

-포테이토.js를 App2.js에서 임포트(import)하고 App2.js를 index.js에 임포트(import)

-App2.js : Potato.js 임포트

import React from "react";
import Potato from "./Potato";

function App2() {
  return (
    <div>
      <h1>1줄로 죽 표현할 수 있음.</h1>
      <Potato/>
    </div>
  );
}
export default App2;
//export 빼먹으면 import로 뭘 가져와야 하는지 모르기 때문에 누락하면 안 됨.

 

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App'; //App.js 파일을 App이라는 이름으로 불러왔음.
import reportWebVitals from './reportWebVitals';

import App2 from './App2';
//import Potato from './Potato';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <App2 />
    {/* <Potato/> */}
    <App />
  </React.StrictMode>
);

reportWebVitals();

 

-Named Export

//Potato.js에서 Export 

export {Potato};

//App2.js에서 import할 때,
import {Potato} from "./Potato";

 

-변수 사용

Potato.js

import React from 'react'; //이 코드가 있어야 리액트가 JSX를 이해

function Potato(){
    return <h3>I love potato</h3>;
}

let name = '감자';

/*
Named Export 방식 사용 시, import할 때, 이름을 그대로 사용해야 함.  {함수명, class명, 변수명}
*/
//1번 방식
// export {Potato} from Potato;
//2번 방식
export {Potato};
export {name};

//export할 때, 한꺼번에 할 수 있음.
// export {Potato, name};

 

App2.js

import React from "react";
import {Potato} from "./Potato"; //★
import {name} from "./Potato"; //★
//import {Potato, name} from "./Potato"; //import도 한꺼번에 입력할 수 있음.

/*
컴포넌트의 부모 태그는 1개만 존재.
return 아래에 <div> 태그 1개만 존재해야 함. 같은 레벨에 다른 태그 존재 불가.

return 뒤에 사용되는 JSX 문법 중 단일 코드로 사용되는 경우에는 괄호를 사용하지 않아도 됨.
코드가 2줄 이상일 때, 괄호를 사용하여 감싸야 함.
*/
function App2() {
    console.log(name); //★ 이거는 변수라서 로그로 찍음.
  return (
    <div>
      <h1>1줄로 죽 표현할 수 있음.</h1>
      <Potato/> //★
      <p>바로바로 적용?</p>
    </div>
  );
}
export default App2;
//export 빼먹으면 import로 뭘 가져와야 하는지 모르기 때문에 누락하면 안 됨.

>> 웹브라우저 [f12]의 콘솔 창에 로그 찍히는 것을 확인할 수 있음.

 

(4) props

각 컴포넌트끼리 데이터를 주고 받기 위한 객체. 데이터 변경 가능.

-App2.js

import React from "react";
import {Potato, name} from "./Potato";
//import {name} from "./Potato"; //해당 모듈에서 제공하는 함수, class, 변수 등을 한번에 import 할 수 있음.

/*
컴포넌트의 부모 태그는 1개만 존재.
return 아래에 <div> 태그 1개만 존재해야 함. 같은 레벨에 다른 태그 존재 불가.

return 뒤에 사용되는 JSX 문법 중 단일 코드로 사용되는 경우에는 괄호를 사용하지 않아도 됨.
코드가 2줄 이상일 때, 괄호를 사용하여 감싸야 함.
*/
function App2() {
    console.log(name);
  // return (
  //     <div>
  //         <h1>App2 파일 생성</h1>
  //         <h2>추가로 한번 만들어 보았음 :)</h2>
  //     </div>
  // );
  return (
    <div>

      <h1>1줄로 죽 표현할 수 있음.</h1>
        {/* Props를 사용하여 해당 컴포넌트에 데이터 전달. >>Potato.js 이동 
            props를 통해서 하위 컴포넌트로 데이터 전달 시
            -문자열은 ""로 감싸서 전달
            -숫자, 논리형, 배열, object 타입은 {}로 감싸서 전달
        */}
      <Potato fav="kimchi" something={true} papapa={['hello', 1,2,3,4, true]}/>
      <p>바로바로 적용?</p>

    </div>
  );
}
export default App2;
//export 빼먹으면 import로 뭘 가져와야 하는지 모르기 때문에 누락하면 안 됨.

└props를 통해서 

-Potato.js

function Potato(props){ //props
    console.log(props); //App2.js에서 보낸 데이터 콘솔에 찍기
    return <h3>I love potato</h3>;
}

-실행 : 웹브라우저에서 검사

[ >> ] 버튼 누르면 component 

└component : 컴포넌트와 그 구성 확인할 수 있음.

└props : 들어온 데이터 데이터 확인 가능

 

-

      <Potato fav="kimchi" 
        something={1} 
        papapa={['hello', 1,2,3,4, true]} 
        objA={{name:'ROBIN', age:20}}
        booltype={true}
      />

-

function Potato(props) {
  console.log(props);
  console.log(props.fav);
  console.log(props.something);
  console.log(props.papapa);
  console.log(props.objA);
  console.log(props.bootype);
  return <h3>I love potato</h3>;
}

-결과

 

-포테이토.js

import React from 'react'; //이 코드가 있어야 리액트가 JSX를 이해

function Potato(props) {
  console.log(props);
  console.log(props.fav);
  console.log(props.something);
  console.log(props.papapa);
  console.log(props.objA);
  console.log(props.bootype);
  return <h3>I love potato</h3>;
}
function SweetPotato(props){
    return <h3>I Love SweetPotato!!</h3>
}

let name = '감자';

//export : 해당 파일을 외부에서 import할 경우 외부에서 지정한 함수, class, 변수 등을 사용할 수 있도록 설정하는 명령어
//default : 해당 파일을 import할 경우 기본적으로 사용할 수 있는 함수, class, 변수로 등록

//default를 사용하면 import할 때 이름을 원하는 대로 붙여서 사용할 수 있음.
// export default Potato;

/*
Named Export 방식 사용 시, import할 때, 이름을 그대로 사용해야 함.  {함수명, class명, 변수명}
*/
//1번 방식
// export {Potato} from Potato;
//2번 방식
export { Potato, SweetPotato };
export { name };
// export {Potato, name};

-App2.js

import React from "react";
import {Potato, name, SweetPotato} from "./Potato";
//import {name} from "./Potato"; //해당 모듈에서 제공하는 함수, class, 변수 등을 한번에 import 할 수 있음.

/*
컴포넌트의 부모 태그는 1개만 존재.
return 아래에 <div> 태그 1개만 존재해야 함. 같은 레벨에 다른 태그 존재 불가.

return 뒤에 사용되는 JSX 문법 중 단일 코드로 사용되는 경우에는 괄호를 사용하지 않아도 됨.
코드가 2줄 이상일 때, 괄호를 사용하여 감싸야 함.
*/
function App2() {
    console.log(name);
  // return (
  //     <div>
  //         <h1>App2 파일 생성</h1>
  //         <h2>추가로 한번 만들어 보았음 :)</h2>
  //     </div>
  // );
  return (
    <div>

      <h1>1줄로 죽 표현할 수 있음.</h1>
        {/* Prop를 사용하여 해당 컴포넌트에 데이터 전달. >>Potato.js 이동 
            props를 통해서 하위 컴포넌트로 데이터 전달 시
            -문자열은 ""로 감싸서 전달
            -숫자, 논리형, 배열, object 타입은 {}로 감싸서 전달
        */}
      <Potato fav="kimchi" 
        something={1} 
        papapa={['hello', 1,2,3,4, true]} 
        objA={{name:'ROBIN', age:20}}
        booltype={true}
      />
      <SweetPotato/>
      <p>바로바로 적용?</p>

    </div>
  );
}
export default App2;
//export 빼먹으면 import로 뭘 가져와야 하는지 모르기 때문에 누락하면 안 됨.

 

값변경

-App2.js : 데이터 던짐

import React from "react";
import {Potato, name, SweetPotato} from "./Potato";
//import {name} from "./Potato"; //해당 모듈에서 제공하는 함수, class, 변수 등을 한번에 import 할 수 있음.

/*
컴포넌트의 부모 태그는 1개만 존재.
return 아래에 <div> 태그 1개만 존재해야 함. 같은 레벨에 다른 태그 존재 불가.

return 뒤에 사용되는 JSX 문법 중 단일 코드로 사용되는 경우에는 괄호를 사용하지 않아도 됨.
코드가 2줄 이상일 때, 괄호를 사용하여 감싸야 함.
*/
function App2() {
    console.log(name);
  // return (
  //     <div>
  //         <h1>App2 파일 생성</h1>
  //         <h2>추가로 한번 만들어 보았음 :)</h2>
  //     </div>
  // );
  return (
    <div>
      <h1>1줄로 죽 표현할 수 있음.</h1>
        {/* Prop를 사용하여 해당 컴포넌트에 데이터 전달. >>Potato.js 이동 
            props를 통해서 하위 컴포넌트로 데이터 전달 시
            -문자열은 ""로 감싸서 전달
            -숫자, 논리형, 배열, object 타입은 {}로 감싸서 전달
        */}
      <Potato fav="kimchi" 
        something={1} 
        papapa={['hello', 1,2,3,4, true]} 
        objA={{name:'ROBIN', age:20}}
        booltype={true}
      />
      <p>바로바로 적용?</p>
      <SweetPotato data="복숭아"/>
      <SweetPotato data="사과"/>
      <SweetPotato data="수박"/>
    </div>
  );
}
export default App2;
//export 빼먹으면 import로 뭘 가져와야 하는지 모르기 때문에 누락하면 안 됨.

└일일이 data=""해주는 거 번거로움. 구조분해 할당

 

-Potato.js

데이터 넘어온 걸 콘솔에 찍음.

function SweetPotato(props){
    console.log(props);
    return <h3>I Love SweetPotato!!</h3>
}
function SweetPotato(props){
    console.log(props);
    return <h3>I Love {props.data}</h3>;
}

 

>> 데이터 4가지 방법으로 사용

//4번 방식 - 매개변수 변경. ES6 버전의 객체 분해 할당을 통해서 매개변수 부분에 {변수명} 사용. jsx 부분에서 해당 변수를 사용하여 출력.
// function SweetPotato({data}) {
function SweetPotato(props) {
  console.log(props);
  //     1번방식 : object 타입의 변수인 props가 가지고 있는 key명을 사용하여 출력
  // return <h3>I Love {props.data}</h3>;

  // 2번 방식 : ES5 버전의 객체 분해 할당 - object 타입의 변수 props의 key명을 사용하여 새로운 변수에 데이터 할당하고 jsx 부분에서 해당 변수 사용
    let data = props.data;
    return <h3>I Love {data}</h3>;

  //3번 : ES6 버전의 객체 분해 할당 - object 타입의 변수 props의 key명을 새로운 변수명으로 사용하고 해당 key의 값을 새 변수의 값으로 할당하여 사용
//   const { data } = props;
//   return <h3>I Love {data}</h3>;
}

 


 

 

2. 실습

/*
문제 1) 컴포넌트 component.js 파일 생성 → 자신의 정보 출력하는 페이지를 화면 출력
-src 폴더 아래 info.js 생성
-출력 정보 : 이름, 성별, 나이, 이메일, 주소
-UI : 화면 구성은 자유

문제 2) 친구 정보 출력하는 컴포넌트 address.js 파일 생성 → 정보 출력하는 페이지를 화면 출력
-src / address.js
-정보 : 이름, 성별, 이메일
-조건 : 친구 2명 이상. props 사용해 하위 컴포넌트로 전달하여 출력
*/

 

(1) info.js

내 정보 출력

import React from 'react';

function Info() {
  let name = 'Woo soyun';
  let gender = 'femail';
  let age = 99;
  let email = 'yun@gmail.com';
  let address = 'Busan';
  return (
    <div>
      <h3>My Infomation</h3>
      <table>
        <thead></thead>
        <tfoot></tfoot>
        <tbody>
          <tr>
            <td>이름</td>
            <td>{name}</td>
          </tr>
          <tr>
            <td>성별</td>
            <td>{gender}</td>
          </tr>
          <tr>
            <td>나이</td>
            <td>{age}</td>
          </tr>
          <tr>
            <td>이메일</td>
            <td>{email}</td>
          </tr>
          <tr>
            <td>주소</td>
            <td>{address}</td>
          </tr>
        </tbody>
      </table>
    </div>
  );
}
//선생님 코드
function Info2() {
  let name = '홍길동';
  let gender = '남성';
  let age = 24;
  let email = 'gildong@gmail.com';
  let address = '부산광역시 전포대로 100길 100';
  return (
    <div>
      <label for="user-name">이름 : </label>
      <h3 className="inlines" id="user-name">
        {name}
      </h3>
      <br />
      <label for="user-age">나이 : </label>
      <h3 className="inlines" id="user-age">
        {age}
      </h3>
      <br />
      <label for="user-gender">성별 : </label>
      <h3 className="inlines" id="user-gender">
        {gender}
      </h3>
      <br />
      <label for="user-email">이메일 : </label>
      <h3 className="inlines" id="user-email">
        {email}
      </h3>
      <br />
      <label for="user-addr">주소 : </label>
      <h3 className="inlines" id="user-addr">
        {address}
      </h3>
      <br />
    </div>
  );
}

export { Info };
export { Info2 };

 

(2) address.js

친구 정보 출력

import React from 'react';

//jsx문법에서는 html 태그를 사용 시 반드시 시작태그와 끝태그가 존재
//ex) <img> : <img></img>, <img />
function Address(props) {
  let name = props.name;
  let sex = props.sex;
  let email = props.email;
  //  const {name, sex, email} = props;
  return (
    <div>
      <h3>Friend Profile</h3>
      <p>name : {name}</p>
      <p>sex : {sex}</p>
      <p>email : {email}</p>
    </div>
  );
}

//선생님 코드
//App.js에서 데이터 입력
function Addr(props) {
  const { name, gender, email } = props;

  return (
    <div>
      <hr></hr>
      <div>
        <label for="user-name">이름 : </label>
        <h3 className="inlines" id="user-name">
          {name}
        </h3>
        <br />
        <label for="user-gender">성별 : </label>
        <h3 className="inlines" id="user-gender">
          {gender}
        </h3>
        <br />
        <label for="user-email">이메일 : </label>
        <h3 className="inlines" id="user-email">
          {email}
        </h3>
        <br />
      </div>
    </div>
  );
}

export { Address };
export { Addr };

 

(3) App.js

import './App.css';
import { Info, Info2 } from './info';
import { Address, Addr } from './address';
import './App.css';

function App() {
  return (
    <div>
      <h1>Profile</h1>
      <Info />
      //선생님 코드 - 내 정보
      //<Info2 />
      
      //<Address data1={{ name: 'Hong-gildong', sex: 'male', email: 'hong@gmail.com' }}
      //<Address data2={{ name: 'Duli', sex: 'male', email: 'duli@gmail.com' }}
      <Address name="Hongildong" sex="male" email="hong@gmail.com" />
      <Address name="Duli" sex="male" email="duli@gmail.com" />
      
      //선생님 코드 - 친구
      //<Addr name="아이유" gender="여성" email="ui@gmail.com" />
      //<Addr name="유재석" gender="남성" email="you@gmail.com" />
    </div>
  );
}

export default App;
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함