본문 바로가기

22 - 1학기/팀 스터디

[웹 FE 스터디] JSX, Rendering Elements, Components, Props

TAB 2022 2학기 학회활동 [팀 스터디]

 TIL 포스팅입니다.

작성자 : 38기_서다원


ref : 인프런 강의 [소플의 처음 만난 리액트(React)]


JSX란?

A syntax extension to JavaScript 자바스크립트의 확장 문법

리액트로 프로젝트 개발할때 사용됨. 공식적인 자바스크립트 문법은 아님.

 

어떻게 확장한걸까?

JavaScript + XML / HTML

 

JSX 의 예시 코드

JSX는 하나의 파일에 자바스크립트와 HTML을 동시에 작성하여 편리함.

자바스크립트에서 HTML 을 작성하듯이 하기때문에 가독성이 높다.

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

 

 

JSX 를 쓰는 이유?

생산성과 가독성이 높아짐

 

JSX의 장점

1. 간결한 코드

JSX는 createElement를 생략할 수 있다.

 

2.가독성 향상

유지보수 측면에서도 좋고, 버그를 잡기 쉬움

 

3. Injection Attacks 해킹을 방어하기 좋다.

입력창에 소스코드를 입력해서 해당 코드를 실행되게하는 해킹방법인데, 이를 방어하기에 좋음.

 

JSX 쓰는 법

중간에 자바스크립트 쓰려면 저런식으로 중괄호 사용 가능

 

태그의 속성에 값을 넣고 싶다면?

아래처럼 큰 따옴표 사이에 문자열을 넣거나

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

중괄호 사이에 자바스크립트 코드를 넣기.

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

자식을 정의하려면

아래처럼 태그를 안에 작성해주면 된다. 여기서는 h1태그와 h2 태그가 자식이다.

 

아래는 JSX 코드의 예시이다.

Book.jsx

import React from "react";

function Book(props) {
    return (
        <div>
            <h1>{`이 책의 이름은 ${props.name}입니다.`}</h1>
            <h2>{`이 책은 총 ${props.numOfPage}페이지로 이뤄져 있습니다.`}</h2>
        </div>
    );
}

export default Book;

Library.jsx

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

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

export default Library;

실행결과는 다음과 같다.


Rendering Elements 에 대해서 알아보자

 

Elements란?

리액트 앱을 구성하는 가장 작은 블록들

 

리액트 element는 화면에서 보이는 것들을 기술함.

 

Elements의 생김새?

리액트 elements는 자바스크립트 객체 형태로 존재함.

불변성을 가지고 있음.

 

아래는 버튼을 나타내기 위한 element임.

 

Elements의 특징?

불변성(immutable)

한번 생성되면 변하지 않음.

elements 생성후에는 childeren이나 attributes를 바꿀 수 없음.

완성된 element 를 이렇게 비유할 수도 있겠다.

 

새로운 element 를 원한다면 component에서 새로운 element를 생성해서

기존의 element와 바꾸는 식이다.

 

실습 : 시계만들기

clock.jsx

import React from "react";

function Clock(props) {
    return (
        <div>
            <h1>안녕, 리액트!</h1>
            <h2>현재 시간: {new Date().toLocaleTimeString()}</h2>
        </div>
    );
}

export default Clock;

index.js 에서 렌더링 하는 과정이 필요하다.

위는 결과 화면이다.

 


Components와 Props에 대해서 알아보자

 

리액트는 Component-Based 이다.

모든 게 컴포넌트로 구성되어 있고, 레고 블록을 조립하듯이 컴포넌트를 모아서 개발한다.

 

개념은 함수와 비슷하다고 볼 수 있다.(엄연히 말하면 다르지만)

정확히는 props를 받아서 react element 를 뱉는다고 생각할 수 있다.

 

props란?

컴포넌트에 전달할 다양한 정보를 담고 있는 자바스크립트 객체

 

props의 특징?

Read-Only 

이 말은 즉슨 값을 변경할 수 없다는 것.(다 구워진 붕어빵 안의 속재료를 바꿀 수 없는 것과 같음)

 

JavaScript 함수의 속성

입력값을 변경하지 않으며 같은 입력값에 대해서는 같은 출력값을 출력한다.

이런 함수를 pure 함수라고 하는데

 

리액트 컴포넌트는 마치 이런 pure 함수와 같다.

리액트 컴포넌트는 props를 직접 바꿀 수 없고, 같은 props에 대해서는 같은 결과를 보여준다.

 

Component 만들기

크게 함수 컴포넌트와 클래스 컴포넌트로 나뉘는데

요즘은 함수 컴포넌트 많이 씀(hook 을 이용함)

하지만 기본기를 다지려면 클래스 컴포넌트를 쓰는 법도 알아야함.

 

Function Component

함수 컴포넌트의 예시

 

Class Component

클래스 컴포넌트의 예시

React Component를 상속받아서 Welcome 이라는 클래스를 만들었다.

 

Component의 이름

항상 대문자로 시작해야함.

아니면 dom tag로 인식함(에러가 나거나 원하는 대로 출력이 안될 것임).

 

Component 렌더링

컴포넌트에서 만든 element를 렌더링 하면 됨.

일단 Welcome 이라는 함수 컴포넌트가 있음.

그리고 element를 파라미터로 해서 ReactDOM.render 함수를 호출함.

 

이러면 실제 DOM으로 업데이트 되고 브라우저를 통해 볼 수 있게 됨.

 

Component 합성

여러개의 컴포넌트로 컴포넌트를 만들기

복잡한 화면을 만들때 유용하다.

 

예를 들어 위의 경우를 보면 App 컴포넌트에 Welcome 컴포넌트가 3개가 쓰인 걸 볼 수 있다.

이런걸 컴포넌트 합성이라고 한다.

그림으로 나타내면 이런식이다.

 

Component 추출

반대로 일부를 추출해서 새로운 컴포넌트를 만들 수도 있다.

이런 방법은 재사용성이 높아진다. 개발속도도 향상된다.

 

실습 : 댓글 컴포넌트 만들기

Comment.jsx

import React from "react";

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: 8,
        display: "flex",
        flexDirection: "column",
        justifyContent: "center",
    },
    nameText: {
        color: "black",
        fontSize: 16,
        fontWeight: "bold",
    },
    commentText: {
        color: "black",
        fontSize: 16,
    },
};

function Comment(props) {
    return (
        <div style={styles.wrapper}>
            <div style={styles.imageContainer}>
                <img
                    src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png"
                    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";

const comments = [
    {
        name: "이인제",
        comment: "안녕하세요, 소플입니다.",
    },
    {
        name: "유재석",
        comment: "리액트 재미있어요~!",
    },
    {
        name: "강민경",
        comment: "저도 리액트 배워보고 싶어요!!",
    },
];

function CommentList(props) {
    return (
        <div>
            {comments.map((comment) => {
                return (
                    <Comment name={comment.name} comment={comment.comment} />
                );
            })}
        </div>
    );
}

export default CommentList;