joooii

[99일차] React 공식문서 톺아보기 - 1. UI 표현하기 본문

TIL

[99일차] React 공식문서 톺아보기 - 1. UI 표현하기

joooii 2026. 1. 27. 19:54

 

앞으로 매일 융합 프로젝트 들어가기 전 React와 Next 공식문서를 빠르게 톺아보려고 한다.

프론트엔드 개발자라면 한 번쯤은.. 공식문서를 보는 것이 좋을 것 같아서 react 한글 공식문서를 앞으로 일주일 간 학습해보려고 한다.

 

 

1. 첫 번째 컴포넌트

React 컴포넌트는 마크업으로 뿌릴 수 있는 JavaScript 함수이다.

export default function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3Am.jpg"
      alt="Katherine Johnson"
    />
  )
}

 

컴포넌트 빌드 방법

Step 1) 컴포넌트 내보내기 (`export default`)

Step 2) 함수 정의하기 (` function Component() { } `)

    - 주의사항: 항상 대문자로 시작해야 한다

Step 3) 마크업 추가하기 (`return ( <div> ... </div> )` )

 

컴포넌트 중첩 및 구성

컴포넌트는 다른 컴포넌트를 렌더링할 수 있지만, 컴포넌트를 중첩해서는 안 된다.

export default function Gallery() {
  // 🔴 절대 컴포넌트 안에 다른 컴포넌트를 정의하면 안 됩니다!
  function Profile() {
    // ...
  }
  // ...
}

2. 컴포넌트 import 및 export 하기

React에서는 `./Gallery.js` 또는 `./Gallery` 둘 다 사용 가능

- 전자 (`./Gallery.js`) 의 경우가 native ES Modules 사용 방법에 더 가깝다.

import Gallery from './Gallery';

 

Default와 Named Exports 차이

export

- Default expor : 한 파일에서만 존재 가능 

- Named export : 한 파일 내 여러 개 존재 가능

https://ko.react.dev/learn/importing-and-exporting-components

import

- Default import : 원한다면 import 단어 후에 다른 이름으로 컴포넌트를 가져올 수 있음

ex) `import Button from './button.js';`

- Named import : 양쪽 파일에서 사용하고자 하는 값의 이름이 같아야 함

ex) `import { Button } from './button.js';`

default와 named 비교

 

보편적으로 사용하는 방식

- 한 파일에서 하나의 컴포넌트만 export 할 때 : default export

- 한 파일에서 여러 컴포넌트를 export 할 때 : named export


3. JSX로 마크업 작성하기

JSX는 JavaScript를 확장한 문법으로, JavaScript 파일을 HTML과 비슷하게 마크업을 작성할 수 있도록 한다.

 

JSX 규칙

1. 하나의 root element로 반환하기

한 컴포넌트에서 여러 element를 반환하려면, 하나의 부모 태그로 감싸야한다.

ex) `<div> ... </div>` , `<> ... </>`

 

이때 빈 태그 (`<> </>`)는 Fragment라고 한다.

Fragment는 브라우저상의 HTML 트리 구조에서 흔적을 남기지 않고 그룹화한다

 

❓) 왜 여러 JSX 태그를 하나로 감싸줘야 하나요?

❗️) JSX는 일반 JS 객체로 변환되기 때문에, 하나의 배열로 감싸지 않은 하나의 함수에서는 2개의 객체를 반환할 수 없기 때문이다.

 

2. 모든 태그는 닫아주기

3. 대부분 Camel Case로 작성!


4. 중괄호가 있는 JSX 안에서 자바스크립트 사용하기

이중 중괄호

- 객체를 전달하기 위해서는 `person = {{ name: "String", inventions: 5 }}` 와 같이 다른 중괄호 쌍으로 객체를 감싸야한다.

- 인라인 CSS 스타일에서도 사용할 수 있다. (`style = {{ backgroundColor: 'black' }}`)

 

객체 참조

const person = {
  name: 'Gregorio Y. Zara',
  theme: {
    backgroundColor: 'black',
    color: 'pink'
  }
};

export default function TodoList() {
  return (
    <div style={person.theme}>
      <h1>{person.name}'s Todos</h1>
      <img
        className="avatar"
        src="https://i.imgur.com/7vQD0fPs.jpg"
        alt="Gregorio Y. Zara"
      />
      <ul>
        <li>Improve the videophone</li>
        <li>Prepare aeronautics lectures</li>
        <li>Work on the alcohol-fuelled engine</li>
      </ul>
    </div>
  );
}

5. 컴포넌트에 props 전달하기

부모컴포넌트는 props를 자식컴포넌트에 전달해 줌으로써 컴포넌트 간 props를 이용해 서로 통신한다.

 

prop의 기본값 지정하기

값이 지정되지 않았을 때, 기본값이 주어지길 원한다면 변수 바로 뒤에 `=` 과 함께 기본값을 넣어 구조 분해 할당을 해줄 수 있다

function Avatar({ person, size = 100 }) {
  // ...
}

 

이 기본값은 size prop이 없거나, undefined로 전달될 때 사용한다.

그러나 `size={null}` 또는 `size={0}` 으로 전달된다면, 기본값은 사용되지 않는다.

 

Spread 문법으로 props 전달하기

때때로 전달되는 props는 반복적일 수 있기 때문에 spread 문법을 사용하여 간결하게 사용할 수 있다.

function Profile(props) {
  return (
    <div className="card">
      <Avatar {...props} />
    </div>
  );
}

 

그러나 spread 문법을 모든 컴포넌트에 사용한다면 문제가 있기에 제한적으로 사용해야 한다 !

 

자식을 JSX로 전달하기

JSX 태그 내에 콘텐츠를 중첩하면, 부모 컴포넌트는 해당 콘텐츠를 children 이라는 prop으로 받게 된다. 

그렇기에 children prop을 가지고 있는 컴포넌트는 부모 컴포넌트가 임의로 JSX를 채울 수 있는 "구멍"이 있는 것으로 생각하게 된다.

import Avatar from './Avatar.js';

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

export default function Profile() {
  return (
    <Card>
      <Avatar
        size={100}
        person={{
          name: 'Katsuko Saruhashi',
          imageId: 'YfeOqp2'
        }}
      />
    </Card>
  );
}

 

⚠️ props는 변경할 수 없고, 상호작용이 필요한 경우 state 설정해야 한다!


6. 조건부 렌더링

 

조건부로 JSX 반환하기

`if else`와 같은 조건문을 통해 조건에 따라 렌더링을 분기처리하는 것이 가능하다.

  if (isPacked) {
    return <li className="item">{name} ✅</li>;
  }
  return <li className="item">{name}</li>;

 

조건부로 null을 사용하여 아무것도 반환하지 않기

  if (isPacked) {
    return null;
  }

 

삼항 조건 연산자

`if else` 대신 `삼항 조건 연산자`를 사용하여 JSX 반환이 가능하다. 자주 사용되는 연산자이다.

아래 코드는 isPacked가 true면 `name + '체크'`를 렌더링 하고, 그렇지 않으면(false) `name`을 렌더링 한다.

return (
  <li className="item">
    {isPacked ? name + ' ✅' : name}
  </li>
);

 

논리 연산자

AND (`&&`)

- 조건이 참일 때, 렌더링

- 조건이 거짓일 때, 렌더링 X

 

변수에 조건부로 JSX를 할당하기

let으로 정의된 변수는 재할당이 가능하므로 표시할 기본값을 우선 대입 후, if 문을 사용하여 조건이 true인 경우 JSX 표현식을 let 변수에 재할당한다.

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✅";
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

7. 리스트 렌더링

`filter()`와 `map()`을 사용하여 데이터 배열을 필터링하고, 컴포넌트 배열로 변환할 수 있다.

 

map()

배열을 순회하며 차례로 렌더링

const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

export default function List() {
  const listItems = people.map(person =>
    <li>{person}</li>
  );
  return <ul>{listItems}</ul>;
}

 

filter()

배열에서 해당하는 값만 반환

const chemists = people.filter(person =>
  person.profession === 'chemist'
);

 

Key를 사용하여 리스트 항목을 순서대로 유지하기

각 배열 항목에 고유하게 식별 가능한 문자열 or 숫자를 key로 지정해야 한다. 

Key는 배열 항목이 정렬 등으로 인해 이동 / 삽입 / 삭제되는 경우 각 컴포너트가 어떤 배열 항목에 해당하는지 React에 알려주어서 일치시킬 수 있도록 하기 때문에 key를 지정하는 것은 중요하다.

 

보통 DB에서는 고유한 DB의 key/ID를 사용하고, Local 데이터는 `crypto.randomUUID()` 또는 `uuid` 같은 패키지를 사용한다.

 

key 규칙

- 형제 간 고유해야 함 (같은 key를 다른 배열의 JSX 노드에 동일한 key로 사용은 가능)

- 변경 X


8. 컴포넌트를 순수하게 유지하기

 

순수성

React는 작성되는 모든 컴포넌트가 순수 함수일 것이라 가정하는데, 이는 작성되는 React 컴포넌트에 같은 입력이 주어진다면 반드시 같은 JSX를 반환한다는 의미이다.

function double(number) {
  return 2 * number;
}

 

사이트 이펙트 (Side Effect)

React 컴포넌트가 화면에 렌더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과를 의미한다.

사이드 이펙트는 보통 이벤트 핸들러에 포함된다. 


9. 트리로서의 UI

 

UI 트리 (Virtual DOM Tree)

- React는 UI트리로 모델링한다.

 

렌더 트리 (Real DOM Tree)

- 부모 - 자식 컴포넌트 간의 관계

- 브라우저가 화면에 표시할 콘텐츠를 그리기 위해 사용하는 트리 구조

- 브라우저에서 DOM을 렌더링 할 때 생성

- 컴포넌트만 캡슐화한다

- Root Node = App의 Root 컴포넌트

 

모듈 의존성 트리 (Module Dependency Tree)

- 각 노드의 모듈을 import 해서 형성하는 트리

- Root Node = Root Module (entry point file)

- 일반적으로 루트 컴포넌트를 포함하는 모듈이다

- 번들러 (React 앱을 빌드할 때 모든 JS를 번들로 묶는 빌드 단계의 도구)는 의존성 트리를 사용하여 포함해야 할 모듈을 결정한다

- 앱의 규모가 커지면, 번들 크기와 비용 증가 문제를 디버깅하는 데 도움이 된다

 

 


📚 참고자료

 

빠르게 시작하기 – React

The library for web and native user interfaces

ko.react.dev

 

'TIL' 카테고리의 다른 글

[119일차] 프론트엔드 FSD 아키텍처  (0) 2026.02.28
[107일차] HLS  (0) 2026.02.10
[95일차] STT와 TTS  (0) 2026.01.20
[90일차] Jira 슬기롭게 사용하기  (0) 2026.01.13
[85일차] 애자일과 JIRA  (0) 2026.01.06