Zeno ZENO
Frontend / React · 조회 2 · 좋아요 0

1. React 시작 전 반드시 알아야 할 JavaScript 핵심 문법 정리

React 코드에서 자주 쓰이는 JS 문법 10가지를 예시와 함께 정리한 글

1. 정의

이 글은 React를 배우기 전에 반드시 알아야 할 JavaScript(이하 JS) 문법을 정리한 글이다.

React는 JS 위에서 동작하는 라이브러리다.
라이브러리란, 자주 쓰는 기능을 미리 만들어 놓은 도구 모음이다.
React 코드를 보면 JS 문법이 그대로 사용된다.
JS 기초가 없으면 React 코드를 읽는 것 자체가 어렵다.

여기서 다루는 문법은 ES6+ 문법이다.
ES6란 2015년에 업데이트된 JS 버전이다.
그 이후 버전을 통틀어 ES6+라고 부른다.
현재 실무에서는 ES6+ 문법이 표준이다.


2. 필요한 이유

React 코드를 보면 아래처럼 생긴 코드가 자주 나온다.

const { name, age } = user;
const newList = [...list, newItem];
const double = (x) => x * 2;

이 코드들은 전부 JS 문법이다.
이걸 모르면 React 튜토리얼 첫 줄부터 막힌다.

React를 배우다가 JS 문법에서 막히면 학습 흐름이 끊긴다.
React 공부 전에 JS 문법을 미리 정리해두면 React 코드를 막힘 없이 읽을 수 있다.

💡 React 공부 = JS 공부가 아니다.
React에서 자주 쓰는 JS 문법만 선별해서 익히면 된다.

3. 핵심 개념

React 코드에서 반복적으로 등장하는 JS 문법 10가지다.

① const / let / var

변수를 선언(만들기)할 때 사용하는 키워드다.

키워드 재선언 재할당 사용 권장
const ✅ 기본으로 사용
let ✅ 값이 바뀔 때만
var ❌ 사용하지 않는다
  • 재선언: 같은 이름으로 변수를 다시 만드는 것
  • 재할당: 변수에 다른 값을 다시 넣는 것

React에서는 거의 모든 변수를 const로 선언한다.
값이 바뀌어야 할 때만 let을 쓴다.
var는 예측하기 어려운 동작 때문에 현재는 사용하지 않는다.


② 화살표 함수 (Arrow Function)

함수를 짧게 쓰는 문법이다.

// 기존 함수 선언 방식
function add(a, b) {
  return a + b;
}

// 화살표 함수
const add = (a, b) => a + b;

React에서는 컴포넌트, 이벤트 핸들러, 콜백 함수 등 거의 모든 곳에 화살표 함수가 쓰인다.
콜백 함수란, 다른 함수의 인자로 전달되는 함수다.


③ 구조 분해 할당 (Destructuring)

객체나 배열에서 원하는 값만 꺼내는 문법이다.

// 객체 구조 분해
const user = { name: '철수', age: 20 };
const { name, age } = user;
// name = '철수', age = 20

// 배열 구조 분해
const [first, second] = [10, 20];
// first = 10, second = 20

React의 useState가 배열 구조 분해를 사용한다.

const [count, setCount] = useState(0);

④ 스프레드 / 나머지 연산자 (...)

... 하나로 두 가지 기능을 한다.

스프레드: 배열이나 객체를 펼친다.

const arr = [1, 2, 3];
const newArr = [...arr, 4]; // [1, 2, 3, 4]

const obj = { a: 1 };
const newObj = { ...obj, b: 2 }; // { a: 1, b: 2 }

나머지(rest): 나머지 값을 모아 배열로 만든다.

const [first, ...rest] = [1, 2, 3, 4];
// first = 1, rest = [2, 3, 4]

React에서 State(상태)를 업데이트할 때 스프레드 연산자를 자주 쓴다.


⑤ 템플릿 리터럴

문자열 안에 변수를 넣는 문법이다. 백틱(`)을 사용한다.

const name = '철수';

// 기존 방식
const msg = '안녕, ' + name + '!';

// 템플릿 리터럴
const msg = `안녕, ${name}!`;

JSX(React의 HTML 문법) 안에서 동적인 문자열을 만들 때 사용한다.


⑥ 배열 메서드: map / filter / reduce / find

배열을 다루는 함수들이다. React에서 리스트를 렌더링할 때 필수로 사용한다.

  • map: 배열의 각 요소를 변환해 새 배열을 만든다.
  • filter: 조건에 맞는 요소만 남긴 새 배열을 만든다.
  • reduce: 배열을 하나의 값으로 합친다.
  • find: 조건에 맞는 첫 번째 요소 하나를 반환한다.
const numbers = [1, 2, 3, 4, 5];

// map: 각 숫자를 2배로
numbers.map(n => n * 2); // [2, 4, 6, 8, 10]

// filter: 짝수만
numbers.filter(n => n % 2 === 0); // [2, 4]

// reduce: 전체 합산
numbers.reduce((acc, n) => acc + n, 0); // 15

// find: 3보다 큰 첫 번째 숫자
numbers.find(n => n > 3); // 4

⑦ 단축 평가 / 옵셔널 체이닝 / Nullish 병합

조건 처리를 짧게 쓸 수 있는 문법이다.

&& (단축 평가): 앞이 참이면 뒤를 실행한다.

isLoggedIn && <UserMenu />
// isLoggedIn이 true일 때만 UserMenu를 렌더링

|| (OR 연산자): 앞이 falsy(거짓 같은 값)면 뒤를 사용한다.

const name = user.name || '익명';

?. (옵셔널 체이닝): 값이 없을 때 에러 대신 undefined를 반환한다.

const city = user?.address?.city;
// user나 address가 없어도 에러가 나지 않는다

?? (Nullish 병합): 값이 null 또는 undefined일 때만 뒤를 사용한다.

const name = user.name ?? '익명';
// user.name이 null/undefined일 때만 '익명' 사용
// 0이나 ''(빈 문자열)은 그대로 사용 (||와 차이점)

⑧ import / export (ESModule)

파일 간에 코드를 주고받는 문법이다.

// utils.js — 내보내기
export const add = (a, b) => a + b;
export default function greet() { return '안녕'; }

// App.js — 가져오기
import greet, { add } from './utils';
  • export default: 파일당 하나만 내보낼 수 있다. 가져올 때 이름을 자유롭게 정할 수 있다.
  • named export: 여러 개를 내보낼 수 있다. 가져올 때 반드시 같은 이름을 써야 한다.

React 컴포넌트 파일은 거의 항상 export default를 사용한다.


⑨ 프로미스와 async/await

비동기 처리를 위한 문법이다.

비동기란, 작업이 끝나기를 기다리지 않고 다음 코드를 먼저 실행하는 방식이다.
API 호출, 파일 읽기, 타이머 등이 비동기 작업이다.

// async/await 방식 (현재 표준)
async function fetchUser() {
  const response = await fetch('https://api.example.com/user');
  const data = await response.json();
  return data;
}
  • async: 이 함수 안에서 await를 쓸 수 있다고 선언하는 키워드
  • await: 비동기 작업이 끝날 때까지 기다린다
  • fetch: 서버에 데이터를 요청하는 내장 함수

⑩ 얕은 복사 vs 깊은 복사

React에서 State를 업데이트할 때 반드시 알아야 하는 개념이다.

얕은 복사: 1단계만 복사한다. 중첩된 객체는 원본을 참조한다.
깊은 복사: 모든 단계를 복사한다. 원본과 완전히 분리된다.

// 얕은 복사 (스프레드 연산자)
const copy = { ...original };

// 깊은 복사 (간단한 방법)
const deepCopy = JSON.parse(JSON.stringify(original));

React에서 중첩 객체 State를 업데이트할 때 얕은 복사만 하면 버그가 생긴다.
이 부분은 State 파트에서 자세히 다룬다.


4. 주변 기초 개념

CommonJS vs ESModule

JS에서 파일을 나누는 방식은 두 가지가 있다.

방식 문법 사용 환경
CommonJS require / module.exports Node.js (서버)
ESModule import / export 브라우저, React (현재 표준)

React에서는 ESModule 방식만 사용한다.

스코프 (Scope)

변수가 유효한 범위다.
constlet블록 스코프다. { } 안에서만 유효하다.
var함수 스코프다. 함수 전체에서 유효해서 예측이 어렵다.

if (true) {
  const x = 10; // 블록 안에서만 유효
  var y = 20;   // 블록 밖에서도 유효 (의도치 않은 동작 가능)
}
console.log(y); // 20 (에러 없음)
console.log(x); // ReferenceError (에러 발생)

클로저 (Closure)

함수가 자신이 만들어진 시점의 변수를 기억하는 특성이다.
React의 Hook 내부에서 클로저가 자주 등장한다. 지금은 "함수는 바깥 변수를 기억한다"는 정도만 알고 넘어가면 된다.


5. 실제 흐름

React 컴포넌트 하나가 동작하는 흐름에서 위 문법들이 어떻게 쓰이는지 확인해보자.

  1. import로 필요한 것을 가져온다.
  2. const로 컴포넌트 함수를 선언한다. (화살표 함수 또는 일반 함수)
  3. 구조 분해 할당으로 Props를 꺼낸다.
  4. 배열 메서드로 데이터를 가공한다.
  5. async/await로 API 데이터를 가져온다.
  6. 스프레드 연산자로 State를 업데이트한다.
  7. export default로 컴포넌트를 내보낸다.

이 흐름 안에 이 글에서 다룬 JS 문법이 모두 들어 있다.


6. 예시

간단한 React 컴포넌트 코드에서 어떤 JS 문법이 쓰이는지 확인해보자.

import { useState } from 'react';          // ① import

const UserCard = ({ name, age }) => {      // ② const, 화살표 함수, ③ 구조 분해
  const [isOpen, setIsOpen] = useState(false); // ③ 배열 구조 분해

  const tags = ['react', 'js', 'web'];
  const tagList = tags.map(tag => `#${tag}`);  // ⑥ map, ⑤ 템플릿 리터럴

  return (
    <div>
      <p>{name} ({age}세)</p>
      {isOpen && <p>태그: {tagList.join(', ')}</p>}  {/* ⑦ && */}
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen ? '접기' : '펼치기'}
      </button>
    </div>
  );
};

export default UserCard;                    // ⑧ export default

7. 코드 설명

  • import { useState } from 'react' — react 라이브러리에서 useState 함수를 가져온다.
  • const UserCard = ({ name, age }) => — UserCard라는 컴포넌트를 화살표 함수로 선언한다. Props를 구조 분해 할당으로 바로 꺼낸다.
  • const [isOpen, setIsOpen] = useState(false) — 배열 구조 분해 할당으로 State 값과 업데이트 함수를 꺼낸다.
  • tags.map(tag => `#${tag}`) — 배열의 각 값을 #태그 형태 문자열로 변환한다. 화살표 함수와 템플릿 리터럴을 함께 사용한다.
  • isOpen && <p>...</p> — isOpen이 true일 때만 태그 목록을 렌더링한다.
  • () => setIsOpen(!isOpen) — 버튼 클릭 시 isOpen 값을 반전시키는 화살표 함수다.
  • export default UserCard — 이 컴포넌트를 다른 파일에서 가져다 쓸 수 있게 내보낸다.

8. 주의점

① const인데 객체/배열 내부 값은 바꿀 수 있다

const user = { name: '철수' };
user.name = '영희'; // 가능! (재할당이 아니라 내부 수정)
user = {};          // 에러! (재할당 불가)

const는 변수가 가리키는 주소가 바뀌는 걸 막는다. 내부 값 수정은 막지 않는다.

② 화살표 함수에 중괄호 있으면 return 필요

// 한 줄: return 생략 가능
const double = x => x * 2;

// 중괄호 있으면: return 필수
const double = x => {
  return x * 2;
};

③ 0 && ... 는 0을 렌더링한다

// 잘못된 예
{list.length && <List />}
// list.length가 0이면 0이 화면에 출력됨

// 올바른 예
{list.length > 0 && <List />}

④ || vs ??

연산자 기본값 사용 조건
|| falsy 값일 때 (0, '', false, null, undefined)
?? null 또는 undefined일 때만
const count = 0;
console.log(count || 10);  // 10 (0은 falsy이므로)
console.log(count ?? 10);  // 0 (null/undefined가 아니므로)

⑤ map은 반드시 새 배열을 반환한다

원본 배열을 변경하지 않는다. forEach와 혼동하지 말 것.
forEach는 반환값이 없다. 반환값이 필요하면 반드시 map을 쓴다.


9. 요약

  • 변수 선언은 const를 기본으로 쓴다. 값이 바뀌면 let.
  • 함수는 화살표 함수로 짧게 쓴다.
  • 구조 분해 할당으로 객체/배열에서 값을 꺼낸다.
  • 스프레드 연산자(...)로 배열/객체를 복사하거나 합친다.
  • 배열 메서드 map, filter, find는 React 리스트 렌더링에 필수다.
  • &&로 조건부 렌더링, ?.으로 안전하게 접근, ??로 기본값 처리한다.
  • 파일 간 코드 공유는 import / export로 한다.
  • 비동기 처리는 async/await로 한다.
  • State 업데이트 시 불변성(원본 보존)을 지켜야 한다.

10. 핵심 용어 정리

  • const = 재선언·재할당 불가 변수 선언 키워드
  • let = 재할당 가능한 변수 선언 키워드
  • 화살표 함수 = =>를 사용하는 짧은 함수 표현식
  • 구조 분해 할당 = 객체나 배열에서 필요한 값만 꺼내는 문법
  • 스프레드 연산자 = ...으로 배열/객체를 펼치는 문법
  • 템플릿 리터럴 = 백틱과 ${}을 이용해 변수를 문자열에 삽입하는 문법
  • map = 배열의 각 요소를 변환해 새 배열을 반환하는 메서드
  • filter = 조건에 맞는 요소만 남긴 새 배열을 반환하는 메서드
  • 옵셔널 체이닝(?.) = 값이 없을 때 에러 대신 undefined를 반환하는 문법
  • Nullish 병합(??) = null/undefined일 때만 기본값을 쓰는 연산자
  • ESModule = import/export를 사용하는 JS 표준 모듈 시스템
  • async/await = 비동기 코드를 동기처럼 읽기 쉽게 쓰는 문법
  • 얕은 복사 = 1단계만 복사하는 방식, 중첩 객체는 원본 참조
  • 깊은 복사 = 모든 단계를 복사하는 방식, 원본과 완전히 분리
  • 비동기 = 작업 완료를 기다리지 않고 다음 코드를 실행하는 방식
  • 스코프 = 변수가 유효한 범위
  • 클로저 = 함수가 자신이 만들어진 시점의 변수를 기억하는 특성

AD

'React' 카테고리의 다른 글

전체보기