컴포넌트 기반 구조 (Component-Based)

컴포넌트 : 독립적인 기능을 수행하는 작은 기능 단위 모듈

• 리액트에서는 모든 페이지가 컴포넌트로 구성

• 하나의 컴포넌트는 또 다른 여러개의 컴포넌트 조합으로 구성될 수 있음.

• 레고 블록을 조립하는 것처럼 컴포넌트를 조합해서 사용

 

함수와 리액트 컴포넌트

• 리액트 컴포넌트는 개념적으로 자바스크립트의 함수와 비슷

• 다만 리액트 컴포넌트는 속성(Props)을 입력 받아 이를 이용해 리액트 엘리먼트를 생성 하여 리턴해 준다는 것이 차이점

 

리액트 컴포넌트

리액트 컴포넌트는 객체지향 프로그래밍(OOP)의 클래스와 인스턴스 개념과 유사

  • 클래스 → 붕어빵 틀 (설계도)
  • 인스턴스(객체) → 실제 만들어진 붕어빵

*리액트에서 컴포넌트는 "붕어빵 틀" 같은 역할을 하고, 이를 사용해 만든 **화면 요소들이 "붕어빵"

 

Props

Props(Properties)는 리액트 컴포넌트의 속성을 뜻함
즉, 컴포넌트에 전달할 **데이터(값)**를 의미

컴포넌트에 전달되는 데이터를 담은 자바스크립트 객체
즉, 하나의 컴포넌트에 다른 props(속재료)를 넣어 다양한 결과를 만들 수 있음

 

*붕어빵 비유

  • 붕어빵 틀(컴포넌트)은 같지만,
    속 재료(Props)에 따라 팥붕, 크림붕, 치즈붕처럼 다양한 붕어빵(엘리먼트)이 나올 수 있음

Props의 특징

읽기 전용(Read-Only)

  • Props는 컴포넌트가 받기만 하고, 직접 수정할 수 없음
  • 붕어빵을 찍는 도중에 속재료를 바꿀 수 없는 것과 같음.

Props 값을 변경하려면?

  • 새로운 Props를 전달해야 함
  • 같은 Props가 들어오면 항상 같은 결과(엘리먼트)가 나와야 함.

 

Props 전달 방식 정리

JSX 문법을 사용하면 키-값 형태로 Props를 전달할 수 있고,
내부적으로는 자바스크립트 객체 형태로 변환

또한, Props의 값으로 컴포넌트도 전달 가능
(즉, 컴포넌트 안에 다른 컴포넌트를 넣을 수도 있음.)

 

 

1. JSX 기반 Props 전달 예시

function App() {
  return (
    <Profile
      name="소품" // name이라는 props에 "소품" 전달
      introduction="안녕하세요, 소품입니다." // introduction props 전달
      viewCount={1500} // 숫자 값도 전달 가능 (문자열 X, 중괄호 사용!)
    />
  );
}

위 코드는 내부적으로 아래처럼 변환됨!

const props = {
  name: "소품",
  introduction: "안녕하세요, 소품입니다.",
  viewCount: 1500
};

 

2. Props 값으로 컴포넌트 전달하기

function App() {
  return (
    <Layout
      width={2560} // width 속성 (숫자 값)
      height={1440} // height 속성 (숫자 값)
      header={
        <Header title="소품의 블로그입니다" /> // header props에 Header 컴포넌트 전달
      }
      footer={<Footer />} // footer props에 Footer 컴포넌트 전달
    />
  );
}

컴포넌트 안에 또 다른 컴포넌트를 props로 넘길 수도 있음

 

 


3. JSX 미사용 - React.createElement() 함수 기반

 

React.createElement() 기본 문법

React.createElement(
  type,         // 요소 타입 (예: 'div', 'span', 컴포넌트 등)
  props,        // 속성 객체 (예: { className: "my-class", id: "my-id" })
  ...children   // 자식 요소 (예: 문자열, 다른 React 요소 등)
);
const profileElement = React.createElement(Profile, {
  name: "소품",
  introduction: "안녕하세요, 소품입니다.",
  viewCount: 1500
});

React.createElement()를 사용하면 JSX 없이도 컴포넌트를 만들 수 있음
하지만 코드가 복잡해지기 때문에 JSX를 주로 사용

 

 

실습(댓글 컴포넌트)
Comment.jsx

import React from "react"; // 리액트 라이브러리 불러오기
import imgUserIcon from "../assets/user_icon.png"; // 사용자 아이콘 이미지 불러오기

// 🟢 함수 컴포넌트(Function Component)
// Comment 컴포넌트는 name(작성자), comment(댓글 내용)을 props로 받아 화면에 표시함
function Comment(props) {
    // 🟢 스타일 객체 정의
    const styles = {
        wrapper: { // 전체 컨테이너 스타일 (댓글 박스)
            margin: 8,
            padding: 8,
            display: "flex", // 가로 정렬
            flexDirection: "row", // 요소들을 가로로 배치
            border: "1px solid grey", // 회색 테두리
            borderRadius: 16, // 테두리를 둥글게
        },
        imageContainer: {}, // 프로필 이미지 컨테이너 (추후 스타일 추가 가능)
        image: { // 프로필 이미지 스타일
            width: 50, // 가로 크기
            height: 50, // 세로 크기
            borderRadius: 25, // 원형 모양
        },
        contentContainer: { // 텍스트 컨테이너 스타일
            marginLeft: 10, // 왼쪽 여백 추가
            display: "flex",
            flexDirection: "column", // 세로 정렬
            justifyContent: "center", // 중앙 정렬
        },
        nameText: { // 이름 스타일
            color: "black",
            fontSize: 16,
            fontWeight: "bold",
        },
        commentText: { // 댓글 내용 스타일
            color: "black",
            fontSize: 16,
        },
    };

    // 🟢 컴포넌트 렌더링 (Rendering)
     return (
        <div style={styles.wrapper}>
            <div style={styles.imageContainer}>
                <img src={imgUserIcon} alt="user icon" style={styles.image} />
            </div>
            <div style={styles.contentContainer}>
                <span style={styles.nameText}>{props.name}</span>
                <span style={styles.commentText}>{props.comment}</span>
            </div>
        </div>
    );
}

export default Comment;

 

CommentList.jsx(여러개의 댓글 보여주는 리스트)

import React from "react"; // 리액트 라이브러리 불러오기
import Comment from "./Comment"; // Comment 컴포넌트 불러오기

// 🟢 함수 컴포넌트(Function Component)
// 여러 개의 Comment 컴포넌트를 조합(컴포넌트 합성)하여 CommentList를 생성
function CommentList(props) {
    return (
        <div> {/* 전체 댓글 리스트 컨테이너 */}
            {/* 🟢 컴포넌트 합성 (Composition) */}
            {/* 여러 개의 Comment 컴포넌트를 조합하여 리스트를 만듦 */}
            <Comment name="홍길동" comment="안녕하세요. 댓글 남깁니다~" /> {/* 첫 번째 댓글 */}
            <Comment name="유재석" comment="리액트 재미있어요~!" /> {/* 두 번째 댓글 */}
            <Comment name="강민경" comment="저도 리액트 배워보고 싶어요!!" /> {/* 세 번째 댓글 */}
        </div>
    );
}

// 🟢 CommentList 컴포넌트 내보내기 (다른 파일에서 사용 가능)
export default CommentList;

 

 

index.js

// React 라이브러리를 불러옴 (React 컴포넌트를 만들기 위해 필요)
import React from 'react';

// ReactDOM을 불러옴 (React 요소를 실제 DOM에 렌더링하는 역할)
import ReactDOM from 'react-dom/client';

// CommentList 컴포넌트를 불러옴 (댓글 목록을 표시하는 컴포넌트)
import CommentList from './components/CommentList';

// HTML 문서에서 id가 'root'인 요소를 찾아 React의 렌더링 루트(root)로 지정
const root = ReactDOM.createRoot(document.getElementById('root'));

// React 컴포넌트를 화면에 렌더링하는 함수
root.render(
  <React.StrictMode> {/* StrictMode는 잠재적인 문제를 감지하고 경고를 표시하는 개발 모드 */}
    <CommentList /> {/* CommentList 컴포넌트를 화면에 렌더링 */}
  </React.StrictMode>
);

*root.render()란?

root.render()는 React 컴포넌트를 실제 화면에 그리는 역할

 

 

실습2(컴포넌트기반스터디룸현황UI 제작)

• 총5개의스터디룸현황표시

• 이미지, 이름, 상태 텍스트 출력

 

 

Room.jsx(방 정보 컴포넌트)

// React 라이브러리를 불러옴 (React 컴포넌트를 만들기 위해 필요)
import React from "react";

// 방 아이콘 이미지 파일을 불러옴
import imgUserIcon from "../assets/room_icon.png";

// Room(방) 정보를 나타내는 컴포넌트
function Room(props) {
    // 스타일을 정의하는 객체
    const styles = {
        wrapper: {
            margin: 20, // 외부 여백
            padding: 8, // 내부 여백
            width: 300, // 가로 크기
            height: 400, // 세로 크기
            display: "flex", // flexbox 사용
            flexDirection: "column", // 세로 방향 정렬
            alignItems: "center", // 가로 중앙 정렬
            justifyContent: "center", // 세로 중앙 정렬
            border: "1px solid grey", // 테두리 추가
            borderRadius: 16, // 모서리를 둥글게
        },
        imageContainer: {
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
        },
        image: {
            width: 100, // 이미지 크기 (가로)
            height: 100, // 이미지 크기 (세로)
            borderRadius: 50, // 둥근 이미지 처리
        },
        contentContainer: {
            marginTop: 15,
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            justifyContent: "center",
        },
        nameText: {
            marginTop: 30,
            color: "black", // 글자색 검정
            fontSize: 20, // 글자 크기
            fontWeight: "1000", // 글자 두께
            textAlign: "center", // 글자 중앙 정렬
        },
        commentText: {
            marginTop: 30,
            color: "black",
            fontSize: 16,
            fontWeight: "bold",
            textAlign: "center",
        },
    };

    return (
        <div style={styles.wrapper}> {/* 방 정보를 감싸는 컨테이너 */}
            <div style={styles.imageContainer}> {/* 이미지 컨테이너 */}
                <img src={imgUserIcon} alt="room icon" style={styles.image} />
            </div>
            <div style={styles.contentContainer}> {/* 텍스트 정보 컨테이너 */}
                <span style={styles.nameText}>{props.name}</span> {/* 방 이름 */}
                <span style={styles.commentText}>{props.comment}</span> {/* 사용 가능 여부 */}
            </div>
        </div>
    );
}

// Room 컴포넌트를 다른 파일에서 사용 가능하도록 내보내기
export default Room;

 

RoomList.jsx(방 목록을 보여주는 컴포넌트)

// React 라이브러리를 불러옴
import React from "react";

// Room 컴포넌트를 불러옴 (각 방 정보를 표시)
import Room from "./Room";

// RoomList 컴포넌트 정의 (여러 개의 Room을 한 번에 렌더링)
function RoomList(props) {
    return (
        <div> {/* 전체 컨테이너 */}
            <div style={{ display: "flex", flexDirection: "row", flexWrap: "wrap" }}> 
                {/* flexbox를 사용하여 가로 방향으로 나열하고, 줄바꿈 가능하도록 설정 */}
                
                <Room name="[1F] Cube A" comment="사용가능" /> 
                {/* Room 컴포넌트를 사용하여 Cube A 정보를 전달 */}
                
                <Room name="[1F] Cube B" comment="사용가능" /> 
                
                <Room name="[1F] Cube C" comment="사용불가능" /> 
                
                <Room name="[1F] Cube D" comment="사용가능" /> 
                
                <Room name="[1F] Cube E" comment="사용가능" /> 
                
            </div>
        </div>
    );
}

// RoomList 컴포넌트를 다른 파일에서 사용 가능하도록 내보내기
export default RoomList;

 

index.js

// React 라이브러리를 불러옴 (React 컴포넌트를 만들기 위해 필요)
import React from 'react';

// ReactDOM을 불러옴 (React 요소를 실제 DOM에 렌더링하는 역할)
import ReactDOM from 'react-dom/client';

// RoomList 컴포넌트를 불러옴 (방 목록을 표시하는 컴포넌트)
import RoomList from './components/RoomList';

// HTML 문서에서 id가 'root'인 요소를 찾아 React의 렌더링 루트(root)로 지정
const root = ReactDOM.createRoot(document.getElementById('root'));

// React 컴포넌트를 화면에 렌더링하는 함수
root.render(
  <React.StrictMode> {/* StrictMode는 잠재적인 문제를 감지하고 경고를 표시하는 개발 모드 */}
    <RoomList /> {/* RoomList 컴포넌트를 화면에 렌더링 */}
  </React.StrictMode>
);

'React' 카테고리의 다른 글

리액트JSX  (0) 2025.03.25
소프트웨어 설계 3주차  (1) 2025.03.18
소프트웨어 설계 2주차  (1) 2025.03.18

JSX

• A syntax extension to Javascript (자바스크립트 확장 문법)

• Javascript + XML / HTML

const element = <h1>Hello, wordl!</h1>;

 

 

역할

• JSX는 내부적으로 XML/HTML 코드를 자바스크립트로 변환함.

• createElement 함수 : JSX 코드를 자바스크립트 코드로 변환하는 역할

// JSX를 사용한 코드
const element = (
<h1 className=""greeting">
Hello, world!
</h1>;
)



// JSX를 사용하지 않은 코드
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello, world!'
)

 

 

 

• React.createElement()의 결과로 자바스크립트 객체(엘리먼트)가 생성됨

React.createElement(
type,
[props],
[...children]
)

 

① type - 엘리먼트의 유형 ,<div> <span>같은 HTML 태그나 다른 리액트 컴포넌트

② props – 엘리먼트의 속성. class, style, src 및 onclick 등의 태그 속성

③ children - 현재 엘리먼트가 포함하는 자식 엘리먼트

 

 

JSX 사용 여부에 따른 코드 비교 

// JSX 사용함
<div>Hello, {name}</div>
// JSX 사용 안함
React.createElement('div', null, `Hello, ${name}`);

 

장점

-코드 간결해짐

-가독성 향상

-보안성 향상: 입력창에 문자나 숫자 같은 소스코드를 입력해, 코드가 실행되도록 만드는 injection Attack해킹 방법을 방어 가능해짐( ex) ID 입력 창에 자바스크립트 코드 )

 

 

ReactDOM은 렌더링하기 전에 임베딩(삽입)된 값을 모두 문자열로 변환

const title = response.pontentiallyMaliciousInput;

//이 코드는 안전
const element = <h1>{title}</h1>;

 

• 위 예시 코드는 JSX 코드에서 중괄호를 사용해서 title 변수를 삽입하며, 이는 보안 위험이 발생할 수 있는 코드의 삽입 가능성이 있음

. • XSS(Cross-site-scripting) 공격을 방어할 수 있음

 

 

 

중괄호를 이용한 변수 참조

const name = "hh";
const element = <h1>Hello, {name}</h1>;
ReactDOM.render (
element,
document.getElementById('root’)
);

 

 

중괄호를 이용한 함수 호출

function formatterName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Hyunwoo',
lastName: 'Nam'
}
const element = (
<h1>
Hello, { formatterName(user) }
</h1>
);
ReactDOM.render (
element, document.getElementById('root')
);

 

태그의 속성에 값을 넣는 방법

 

• 큰따옴표 사이에 문자열을 넣는 방식

const element = <div tabIndex="0"></div>;

 

 

• 중괄호 사이에 자바스크립트 코드를 넣는 방식

const element = <img src={user.avatarUrl}></img>;

 

 

자식(children)을 정의하는 방법

• 평소 HTML 코드와 같이 상위 태그가 하위 태그를 둘러싸도록 작성하면 됨.

const element = (
<div>
<h1>안녕하세요.</h1>
<h2>반갑습니다.</h2>
</div>
);

 

 

 

실습

-저번에 만들어둔 파일))

 

-src안에 components폴더 생성

-components폴더 안에 Book.jsx, Library.jsx파일 생성

 

Book.jsx

import React from "react"; //리액트 라이브러리 가져오기, ui를 구축하는데 사용용

function Book(props){//Book 이라는 함수 + 컴포넌트 정의(props는 부모 컴포넌트에서 전달된데이터 포함)
    return(//jsx를 반환하기 시작, jsx는 js와 html결합한 문법법
        <div>
        <h1>{`이 책의 이름은 ${props.name}입니다.`}</h1>
        <h2>{`이 책은 총 ${props.numOfPage}페이지로 이루어져 있습니다.`}</h2>
        </div>
    );
}
export default Book;//이 컴포넌트를 다른 파일에서 사용할 수 있도록 내보냄냄

 

 

 

Library.jsx

import React from "react";//react 라이브러리 가져옴
import Book from "./Book";//Book컴포넌트를 현재 파일로 가져옴

function Library(props) {
    return(
        <div>
            <Book name="처음 만난 파이썬" numOfPage={300} />
            <Book name="처음 만난 AWS" numOfPage = {400} />
            <Book name ="처음 만난 리액트" numOfPage={500} />

        </div>
    );
}

export default Library;

 

 

index.js수정

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import Library from './components/Library' //Library컴포넌트 불러오기기
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Library /> //이 부분도 불러올 컴포넌트인 Library로 변경경
  </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();

 

 

컴포넌트 구조

 

 

 

  • 엘리먼트(Element)란?
    • "요소" 또는 "성분"을 의미하며, 리액트 앱을 구성하는 가장 작은 단위.
    • 기존 웹에서 사용하던 DOM 엘리먼트 개념과 유사.
  • 리액트 엘리먼트의 역할
    • 화면에 보이는 UI를 기술하는 자바스크립트 객체.
    • 실제로 웹 브라우저에서 렌더링될 DOM 엘리먼트를 생성하는 기반이 됨.
  • 엘리먼트와 DOM의 관계
    • 리액트 엘리먼트: 화면에 어떤 UI가 나타날지 정의하는 객체.
    • DOM 엘리먼트: 리액트 엘리먼트의 정보를 바탕으로 실제 브라우저에서 렌더링되는 요소.
  • 왜 ‘엘리먼트’라고 부를까?
    • 리액트 초기에는 이를 **Descriptor(설명자)**라고 불렀음.
    • 하지만 결국 DOM 엘리먼트를 나타내므로, 개념적 통일성을 위해 **엘리먼트(Element)**라는 용어를 사용하게 됨.
l const element = <h1>Hello, world!</h1>;

• 리액트의 createElement( ) 함수에 의해 리액트 엘리먼트가 생성됨

 

 

 

엘리먼트의 형태

• 리액트 엘리먼트는 자바스크립트 객체 형태로 존재

• 컴포넌트 유형, 속성, 자식(children)에 대한 정보를 포함하는 자바스크립트 객체

 

 

리액트 엘리먼트

{
	type: 'button',
    props: {
    	className: 'bg-green',
        children: {
        	type:'b',
            props: {
            	children: 'Hello, element!'
                }
            }
        }
}

 

 

DOM엘리먼트

<button class = 'bg-green'>
	<b>
    	Hello, element!
    <b>
 </button>

 

 

 

createElement( ) 함수

• 함수의 실행 결과로 자바스크립트 객체(엘리먼트)가 생성됨

React.createElement(
type,
[props],
[...children]
)

① type - 엘리먼트의 유형 ,<div> <span>같은 HTML 태그나 다른 리액트 컴포넌트

② props – 엘리먼트의 속성. class, style, src 및 onclick 등의 태그 속성

③ children - 현재 엘리먼트가 포함하는 자식 엘리먼트

 

 

 

• createElement( ) 함수의 동작 과정

• Buttton 컴포넌트를 포함하는 ConfirmDialog 컴포넌트 구성

function Button(props){
	return(
    	<button className = { `bg-${props.color}`}>
        	<b>
            	{props.children}
            </b>
        </button>
     )
 }
 
 
 function ConfirmDialog(props) {
 	return(
    	<div>
        	<p>내용을 확인하셨으면 확인 버튼을 눌러주세요.</p>
            <Button color = 'green'>확인</button>
        </div>
        )
 }

 

 

createElement( ) 함수의 동작 과정 – ConfirmDialog 컴포넌트

• 현 단계에서 Button 컴포넌트는 아직 HTML 태그가 아니기 때문에 DOM 렌더링이 안됨.

 

{
	type: 'div'
    props:{
    	children: [
        {
        	type: 'p',
            props: {
            	children: '내용을 확인하였으면 확인버튼을 눌러주세요.'
                }
             },
             {
             	type: Button,
                props: {
                	color: 'green',
                    children: '확인'
                    }
                }
           }
       ]
   }
}

 

 

 

• createElement( ) 함수의 동작 과정 – ConfirmDialog 컴포넌트 • 최종적으로 DOM에 렌더링되는 엘리먼트의 구성

{
	type: 'div'
    props:{
    	children: [
        {
        	type: 'p',
            props: {
            	children: '내용을 확인하였으면 확인버튼을 눌러주세요.'
                }
             },
             {
             	type: Button,
                props: {
               		className: 'bg-green',
                    children: {
                    	type: 'b',
                        props: {
                        	children:'확인'
                         }
                    }
                }
           }
       ]
   }
}

 

 

 

• Root DOM node

• root라는 id를 가진 div 태그에 모든 리액트 엘리먼트들이 렌더링되며, 리액트 DOM에 의해 관리됨.

• 리액트만으로 만들어진 앱은 단 하나의 Root DOM Node를 가짐

 

Root DOM node 엘리먼트 렌더링

const element = <h1>안녕, 리액트!<h1>;
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);

 

• createRoot로 설정된 Root DOM Node에 render 함수를 사용하여 화면을 렌더링 함.

• 엘리먼트가 렌더링되는 과정은 Virtual DOM에서 실제 DOM으로 이동하는 과정

• 렌더링된 엘리먼트 업데이트

• 엘리먼트는 한번 생성되면 바꿀 수 없기 때문에 다시 생성해야 함

• 즉 기존 엘리먼트를 변경하는 것이 아니라 새로운 엘리먼트를 생성해서 바꿔치기 방식으로 새로운 화면으로 업데이트 할 수 있음.

 

 

 

 

 

실습: 시계 만들기

 

-1초마다 실행: setinterval()함수 사용

-시간 정보 추출

: new Date().toLocaleTimeString() 내장함수 사용

 

 

components폴더 안에 Clock.jsx파일 생성후 작성

import React from "react" //react라이브러리 가져옴

function Clock(props) {//Clock이라는 이름의 함수형 컴포넌트 정의
    return (
        <div>
            <h1>
                현재시간: {new Date().toLocaleDateString() }

            </h1>
        </div>
    )
}

export default Clock;//이 컴포넌트를 다른 파일에서 사용할 수 있도록 내보냄

 

 

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Clock from './components/Clock'

//DOM의 'root'요소를 선택하여 react가 렌더링 할 루트 생성
const root = ReactDOM.createRoot(document.getElementById('root'));
//1초 간격으로 Clock 컴포넌트 렌더링
setInterval(() => {
  root.render(
    <React.StrictMode>
      <Clock />
      </React.StrictMode>
  );
}, 1000);//1초 후에 컴포넌트 갱신


// 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();

 

 

 

 

'React' 카테고리의 다른 글

컴포넌트와 Props  (0) 2025.04.02
소프트웨어 설계 3주차  (1) 2025.03.18
소프트웨어 설계 2주차  (1) 2025.03.18

리액트란

-사용자 인터페이스를 만들기 위한 JavaScript라이브러리

- SPA를 쉽고 빠르게 만들수 있도록 해주는 도구

 

장점

  •  빠른 업데이트와 렌더링 속도
  •  재사용성이 높은 컴포넌트 기반 구조 
  • 메타의 든든한 지원 
  • 활발한 지식 공유와 커뮤니티 
  • 리액트 네이티브를 통한 모바일 앱 개발 가능

 

단점

  • 방대한 학습량
  • 높은 상태 관리 복잡도

 

프레임워크와 라이브러리

-프로그램 흐름에 대한 제어권한차이

-프레임워크는 전체적인 흐름을 갖고 있으며, 애플리케이션의 코드는 프레임워크에 의해 사용됨

-라이브러리는 흐름에 대한 제어를 하지 않고 개발자가 필요한 부분만 가져다 사용  

 

SPA(Single Page Application)

-단일 페이지로 구성된 웹 애플리케이션

*하나의 html 틀을 만들어 놓고 , 사용자가 요청할 그 페이지에 해당하는 콘텐츠를 가져와 동적으로 페이지의 내용을 채워서 보여주는 방식

 

 

 

여러개의 버튼 생성하기

// MyButton 컴포넌트 정의
function MyButton(props) {
    // 클릭 상태를 관리하는 상태 변수와 setter 함수 정의
    const [isClicked, setIsClicked] = React.useState(false);

    // 버튼을 생성하여 반환
    return React.createElement(
        'button', // 'button' HTML 요소 생성
        { onClick: () => setIsClicked(true) }, // 버튼 클릭 시 상태를 true로 변경하는 이벤트 핸들러
        isClicked ? 'Clicked!' : 'Clicked here!' // 클릭 상태에 따라 버튼 텍스트 변경
    );
}

// ButtonGroup 컴포넌트 정의
function ButtonGroup() {
    return React.createElement(
        'div', // 'div' HTML 요소 생성
        null, // div의 속성은 없음
        React.createElement(MyButton), // 첫 번째 MyButton 컴포넌트 생성
        React.createElement(MyButton), // 두 번째 MyButton 컴포넌트 생성
        React.createElement(MyButton)  // 세 번째 MyButton 컴포넌트 생성
    );
}

// DOM의 '#root' 요소를 선택
const domContainer = document.querySelector('#root');

// ButtonGroup 컴포넌트를 렌더링
ReactDOM.render(React.createElement(ButtonGroup), domContainer); // ButtonGroup을 선택한 DOM 요소에 렌더링

 

 

CRA(create-react-app)기반 리액트 프로젝트 생성

 npx create-react-app my-app
cd my-app
npm start

*내장 웹서버를 통해 리액트 프로젝트의 웹 페이지에 접속 가능

'React' 카테고리의 다른 글

컴포넌트와 Props  (0) 2025.04.02
리액트JSX  (0) 2025.03.25
소프트웨어 설계 2주차  (1) 2025.03.18

var를 이용한 변수 선언의 문제점

-# 변수를 덮어 쓸 수 있음

-# 다시 선언(재선언)할 수 있음

 

let을 이용한 변수 선언

-재선언 불가능, 변수 덮어 쓸 수는 있음

let val2 = "let 변수";
 console.log(val2);
 // let은 덮어 쓰기 가능
val2 = "let 변수 덮어 쓰기“;
 console.log(val2);
 // let은 재선언 불가능/ 에러 발생
let val2 = "let 변수 재선언";
 console.log(val2);

 

const를 이용한 변수 선언

-재선언, 덮어쓰기 모두 불가능

const val3 = "const 변수";
 console.log(val3);
 // const 변수는 덮어 쓰기 불가능 / 에러 발생
val3 = "const 변수 덮어 쓰기";
 // const 변수는 재선언 불가능 / 에러 발생
const val3 = "const 변수 재선언";

 

 

 

* 예외적으로 오브젝트 타입(객체, 배열, 함수, 기타)의 데이터는 const로 정의해도 도중에 데이터 수정 가능

* 프리미티브 타입 ( boolean, number, bigint, string, undefined, null,symbol)은 데이터 수정 불가

 

 

객체속성값변경및추가

 // 객체정의
const obj1 = {
  name: "홍길동",
  age: 24,
 };
 console.log(obj1);
 // 속성값변경
obj1.name = "이순신";
 console.log(obj1);
 // 속성값추가
obj1.addr = "Seoul";
 console.log(obj1);

 

 

배열값변경및추가

// 배열정의
const arr1 = ["dog", "cat"];
 console.log(arr1);
 // 첫번쨰값변경
arr1[0] = "bird";
 console.log(arr1);
 // 값추가
arr1.push("monkey");
 console.log(arr1);

*push()함수: 배열 끝에 요소 추가

 

*리액트 개발에서는 const가장 많이 사용

*동적으로 바뀌는 값은 state 으로 관리

*state로 관리하지 않으면서 처리 도중 수정이 필요한 변수만 let으로 선언

 

 

템플릿 문자열

+연산자 사용

const name = "홍길동";
 const age = 24;
 // 기존의 문자열과 변수 결합 방법
const message = "내 이름은 " + name + "입니다. 나이는 " + age + "세 입니다.";
 console.log(message);

 

` 역따옴표 사용

  • `(역 따옴표 또는 백쿼트backquote)로 문자열 감싼다
  • 문자열 내부에 ${}로 감싼 안쪽은 자바스크립트로 입력 가능
  • 변수 외에도 함수 호출 같은 자바스크립트 코드 넣을 수 있음
const name = "홍길동";
 const age = 24;
 // 템플릿 문자열 이용 방법
const message = `내 이름은 ${name}입니다. 나이는 ${age}세 입니다.`;
 console.log(message);

 

 

화살표 함수 () => {}

기존 함수 작성 예

 // 기존함수작성법#1
 function func1(value) {
  return value;
 }
 console.log(func1("func1입니다"));
 // 기존함수작성법#2
 const func2 = function (value) {
  return value;
 }
 console.log(func2("func2입니다"));

 

 

화살표 함수 예) 

const func3 = (value) => {
 return value;
 }
 console.log(func3("func3입니다"));

 

 

*주의점

 

인수가1개인경우에는소괄호( ) 생략이 가능함

const func3 = value => {
 return value;
 }
 console.log(func3("func3입니다"));

 

인수가2개이상인경우소괄호를생략할수없음.

const func3 = value1, value2 => {//에러 발생//(value1, value2)괄호 필요
 return value1 + value2;
 }
 console.log(func3("func3입니다"));

 

 

return생략표기법

•처리를한행으로반환하는경우중괄호와return을생략할수있음.

// 처리를한행으로반환하므로{} 및return문생략
const func4 = (num1, num2) => num1 + num2;
 console.log(func4(10, 20)); // 30

 

• 반환값이여러행일경우에는( )로감싼뒤단일행과같이모아서반환할수있음

const func5 = (val1, val2) => (
 {
 name: val1,  
age: val2,
 }
 )
 console.log(func5("홍길동", 24)); //{name: '홍길동', age: 24}

 

잘못된return 생략표기법.

•중괄호로감싼뒤return을생략할수있지만값이반환되지않는문제가발생함.

// { }로감쌌지만return 구문을이용하지않음.
 const func4 = (num1, num2) => {
  num1 + num2
 };
 console.log(func4(10, 20)); // undefined

 

 

분할대입{ } [ ]

//분할 대입을이용하지않고문자열을출력
const myProfile = {
 name: '홍길동',
 age: 24,
 }
 const message = `내 이름은 ${myProfile.name}입니다. 나이는
${myProfile.age}세 입니다.`;
 console.log(message);
 
 // 분할 대입 이용
const { name, age } = myProfile;
 const message = `내 이름은 ${name}입니다. 나이는 ${age}세 입니다.`;
 console.log(message);

 

•객체분할대입 

//일부만추출하거나순서를바꾸어추출
const myProfile = {
  name: '홍길동',
  age: 24,
 }
 // 일부만추출
const { age } = myProfile;
 // 순서를바꾸어추출
const { age, name } = myProfile;

// 추출한속성에새로운별명을지정하여사용
const myProfile = {
  name: '홍길동',
  age: 24,
 }
 // 콜론(:)기호를이용해다른변수명(별명)을지정.
 const 
{ name: newName, age: newAge } 
= 
myProfile;
 const message = `내이름은${newName}입니다. 
나이는${newAge}세입니다.`;
 console.log(message);

 

 

•배열 분할 대입

•객체와 마찬가지로 배열에서도 분할대입을 이용할 수 있음.

•배열에 분할대입을 할때는 변수선언부에[ ]를 사용하여 배열에 저장된순서에 임의의 변수명을 설정하여 추출할 수 있음.

 

// 배열인덱스를지정해서대입
const myProfile = ["홍길동", 24];
 // 배열인덱스를지정해서대입
const message = `내이름은${myProfile[0]}입니다. 나이는${myProfile[1]}세입니다.`;
 console.log(message);
 
 // 배열에분할대입
 const myProfile = ["홍길동", 24];
 // 배열분할대입
const [ name, age ] = myProfile;
 const message = `내이름은${name}입니다. 나이는${age}세입니다.`;
 console.log(message);

 

디폴트값=

디폴트값은함수의인수나객체를분할대입할경우,

값이존재하지 않을때초기값을설정해주는기능.

 

인수의 디폴트값

//메시지출력함수의인자값을전달하는경우와아닌경우의출력결과
constsayHello = (name) =>console.log(`${name}님, 안녕하세요!`);
 // 인수가정상적으로전달된경우
sayHello('홍길동');
 // 인수가전달되지않은경우//인자값이전달되지않은경우값이존재하지않기때문에undefined로출력
sayHello(); 


// 인수의디폴트값으로출력된경우
constsayHello = (name="게스트") =>console.log(`${name}님, 안녕하세요!`);
 // 인수가전달되지않은경우//인수값이전달되지않은경우디폴트값“게스트”를출력함
sayHello();

 

 

•객체분할 대입의 디폴트값

•인수와 마찬가지로 변수명뒤에=로값을 설정하면 속성이 존재하지 않은 경우에 설정할 초기값을 지정할 수 있음.

//존재하지 않는 속성을 출력
 const myProfile = {  
  age: 24,
 }
 const { name } = myProfile;
 const message = `${name}님, 안녕하세요!`;
 console.log(message); 
 
 
 
 //분할대입시의디폴트값을설정
 const myProfile = {  
  age: 24,
 }
 const { name=“게스트” } = myProfile;
 const message = `${name}님, 안녕하세요!`;
 console.log(message);

 

스프레드구문...

. . . 과 같이 점 세 개를 연결해 배열에 내부요소를순차적으로전개할수 있는표기법

 

• 1) 요소 전개

 • 스프레드구문

const arr1 = [1, 2];
 console.log(arr1); //[1,2]
 console.log(...arr1);//1 2

 

• 일반적인함수와스프레드구문

const arr1 = [1, 2];
 const summaryFunc = (num1, num2) => console.log(num1 + num2);
 // 일반적으로 배열값을 전달하는 경우
summaryFunc( arr1[0], arr1[1] ); 
// 스프레드 구문을 이용하는 방법
summaryFunc( ...arr1 );

 

 

• 2) 요소모으기

constarr2 = [1, 2, 3, 4, 5];
 const[num1, num2, ...arr3] = arr2;
 console.log(num1); // 1
 console.log(num2); // 2
 console.log(arr3); // [3, 4, 5]

 

 

• 3) 요소복사와결합

// 두개의배열결합
const arr4 = [10, 20];
 const arr5 = [30, 40];
 // 스프레드구문을이용해복사
const arr6 = [...arr4];
 // 스프레드구문을이용해결합
const arr7 = [...arr4, ...arr5];
 console.log(arr4);  
console.log(arr6);  
console.log(arr7);  

//두개의객체결합
const arr4 = {val1: 10, val2: 20};
 const arr5 = {val3: 30, val4: 40};
 // 스프레드구문을이용해복사
const arr6 = {...arr4};
 // 스프레드구문을이용해결합
const arr7 = {...arr4, ...arr5};
 console.log(arr4); 
console.log(arr6);   
console.log(arr7);

 

*등호(=) 복사하면 복사본 데이터의 변경시 원본 데이터도 변경되는 예상치 못한 동작 발생

 

스프레드를 사용하여 완전히 새로운 데이터를 생성해 복사해야만 한다

const arr8 = [...arr4]; // 스프레드구문을이용해복사

 

 

 

 

map, filter

*배열 처리에서 기존 for문을 대체하여 효율적으로 코드 작성이 가능한 문법

 

 

map함수

기존 for문
const nameArr = ["홍길동", "이순신", "유관순"];
 for(let index=0; index < nameArr.length; index++) {
 console.log(nameArr[index]);
 }
 
 //map함수
 const nameArr = ["홍길동", "이순신", "유관순"];
 nameArr.map((name) => console.log(name));

 

 

map 함수의 인수를이용해 요소 순서대로추출

const nameArr = ["홍길동", "이순신", "유관순"];
 nameArr.map((name, index) => 
console.log(`${index}번째 ${nameArr[index]} 입니다.`));

 

filter함수

*map함수와 동일하며 return 뒤에 조건식을 추가하여 일치하는 것만 반환

const numArr = [1, 2, 3, 4, 5];
 // 홀수(2로나눈나머지가1)인경우만추출
const newNumArr = numArr.filter((num) => {
  return num % 2 === 1;
 });
 console.log(newNumArr); //[1, 3, 5]

 

 

삼항연산자

*if ~ else ~ 구문을 단축시켜줄 수 있는 연산자

조건? 조건이true일때의처리: 조건이false일때의처리

 

//E ?와 :을 이용한예시 
const val1 = 1 > 0 ? "true입니다" : "false입니다.";
 console.log(val1);  
// true입니다.


// 함수 return 부분에 삼항 연산자 이용
const checkSumOver100 = (num1, num2) => {
 return num1+num2 > 100 ? "초과" : "허용 범위"; 
}
 console.log(checkSumOver100(50, 40));
 console.log(checkSumOver100(50, 70));

 

 

 

DOM(Document Object Model)

DOM은HTML 문서의객체기반표현방식으로프로그램에서접근및사용.

•문서객체: HTML 태그를자바스크립트에서사용할수있는객체로만든것

 

 

 

getElementById( ) 메서드를 사용해 문서 객체 1개 선택하기

<html>
 <head>
 <script> 
// 페이지가 완전히 로드된 후 실행될 함수를 지정합니다.
window.onload = function () { 
    // 'header'라는 ID를 가진 HTML 요소를 선택합니다.
    let header = document.getElementById('header'); 
    
    // 선택한 요소의 글자 색상을 주황색으로 변경합니다.
    header.style.color = 'orange'; 
    
    // 선택한 요소의 배경 색상을 빨간색으로 변경합니다.
    header.style.background = 'red'; 
    
    // 선택한 요소의 내용을 'From JavaScript'로 변경합니다.
    header.innerHTML = 'From JavaScript'; 
}; 
</script>
 </head>
 <body> 
    <!-- ID가 'header'인 h1 요소 -->
    <h1 id="header">Header</h1>
 </body>
 </html>

* querySelector( ) 메서드를 사용해 문서 객체 1개 선택하기

* querySelectorAll( ) 메서드를 사용해 문서 객체 여러개 선택하기

 

<script> 
  // 이벤트를연결합니다. 
  window.onload = function () { 
  
    // 변수를선언합니다. 
    let output = ''; 
    for (let i = 0; i < 10; i++) { 
output += '<h1>Header -' + i + '</h1>'; 
} 
    // 문서객체내부의글자를변경합니다. 
document.body.textContent = output; ➊
    // innerHTML 속성을사용합니다. 
// document.body.innerHTML = output; ➋
  }; 
</script>

// +, - 버튼을 클릭할 때마다숫자를증가/감소시켜주는카운터프로그램

<!DOCTYPE html>
<html>
   
 
<body>
    <button id="increase">+</button>

 <span id="count">0</span>
 <button id="decrease">-</button>
 
 </body>

<script>
 let count = 0;
 document.getElementById("increase").addEventListener("click", () => {
 count++;
 document.getElementById("count").innerText = count;
 });
 document.getElementById("decrease").addEventListener("click", () => {
 count--;
 document.getElementById("count").innerText = count;
 });
 </script>
   
     <img id="image">
    </body>
    </html>

'React' 카테고리의 다른 글

컴포넌트와 Props  (0) 2025.04.02
리액트JSX  (0) 2025.03.25
소프트웨어 설계 3주차  (1) 2025.03.18

+ Recent posts