[항해 플러스 프론트엔드 7기] 사전 스터디 1주차 - React

Jaehyun Ahn·2025년 9월 17일
0

항해 플러스

목록 보기
2/7

React 소개

  • A JavaScript library for building user interfaces, 웹 or 앱 어플리케이션의 UI를 담당하는 JavaScript 라이브러리
  • SPA(Single Page Application) 기반 프론트엔드 개발 라이브러리

SPA (Single Page Application)

한 개의 페이지로 이루어진 어플리케이션. MPA (Multi Page Application)과 상반된 개념

SPA vs MPA

SPA

  • 한 개의 페이지로 이루어진 어플리케이션
  • 전체 화면에서 일부분이 바뀌는 식으로 동작
  • 최초 로딩은 느리지만 이후 로딩은 빠름
  • CSR 방식 사용 시, SEO에 불리 (초기엔 빈 HTML이기 때문)

MPA

  • 여러 개의 페이지로 이루어진 어플리케이션
  • 페이지 중 일부만 변하더라도 페이지 전체가 리렌더링
  • 매번 새로운 페이지를 렌더링 하기 때문에 로딩이 느림
  • SEO에 유리 (서버로부터 만들어진 HTML을 받기 때문)

왜 React를 많이 사용할까?

  • facebook(현 meta)에서 개발한 기술 스택, 꾸준한 유지보수
  • 방대한 커뮤니티, 문제 발생 시 관련 자료 찾기가 쉬움
  • React에 익숙해지면 RN에도 도전해볼 수 있음

컴포넌트 맛보기

컴포넌트란? 쉽게 말하면 페이지를 이루는 단위 (Header, Footer, Contents 등)
React에서는 컴포넌트를 조립해서 페이지를 만든다 !

  • SPA는 컴포넌트 단위로 변경사항을 반영하기 때문에 화면 깜빡임 X
  • MPA는 바뀐 내용이 반영된 HTML을 다시 불러오기 때문에 화면 깜빡임 O

React에서 자주 사용되는 필수 ES6 문법

상수와 변수

이전에는 var 키워드로 변수를 선언했다면 ES6부턴 let, const 키워드를 사용해 변수, 상수를 선언한다.

  • var : 재할당 가능, 재선언 가능, 함수 레벨 스코프
  • let : 재할당 가능, 재선언 불가, 블록 레벨 스코프
  • const : 재할당 불가, 재선언 불가, 블록 레벨 스코프

함수 레벨 스코프, 블록 레벨 스코프

  • 함수 레벨 스코프 : 함수 내부에서 선언된 변수는 함수 내에서만 유효하며 함수외부에서는 참조할 수 없다.
  • 블록 레벨 스코프 : 함수를 포함한 모든 코드 블록(함수, if문, for문, while문, try/catch문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다.

Object 선언, 단축 속성, 객체 복사

객체는 key-value 쌍으로 가짐


// 객체 선언 방법
const a = {
	name: 'abc',
  	age: 1
}

const name = 'Jaehyun'
const b = {
	name, // 객체 키와 동일한 이름을 가진 변수를 적용할 때, 단축 속성을 사용할 수 있음
  	age: 1
}

얕은 복사, 깊은 복사

객체나 배열을 복사할 때 참조까지 복사하느냐의 차이

얕은 복사

  • 객체/배열의 1차원 값은 복사
  • 객체/배열 참조는 주소만 복사 -> 원본과 복사본이 같은 참조를 공유

변수에 객체, 배열, 함수와 같은 참조 타입 데이터를 담을 때, 변수에는 데이터가 담기는 것이 아닌, 데이터의 메모리 주소(참조값)가 저장됨


const user = {
  name: "재현",
  address: { city: "Seoul" }
};

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

copy.name = "길동";
copy.address.city = "Busan";

console.log(user.name);        // "재현" (독립적)
console.log(user.address.city); // "Busan" (같이 바뀜!)

// name은 기본값이라 독립적이지만, address는 객체가 참조값을 공유 => 원본도 같이 변경됨

깊은 복사

  • 중첩된 객체/배열까지 모두 새로운 메모리에 복사
  • 원본과 복사본이 독립적

const user = {
  name: "재현",
  address: { city: "Seoul" }
};

// 깊은 복사 (JSON 방법)
const deepCopy = JSON.parse(JSON.stringify(user));

deepCopy.name = "길동";
deepCopy.address.city = "Busan";

console.log(user.name);        // "재현"
console.log(user.address.city); // "Seoul" (안 바뀜!)


// 두 객체는 독립적이므로 서로 영향을 주지 않음

템플릿 리터럴

백틱 (``)을 사용하여 문자열을 선언하는 방식.

  • 일반 문자열 사이에 데이터를 삽입할 수 있음
  • 멀티 라인 작성 가능

배열/객체 구조 분해 할당


// 객체 구조 분해 할당

const person = {
	name: 'Jaehyun',
	age: 1
}


const {name: userName, age} = person
console.log(`${userName}님, ${age}살이시네요!`); // Jaehyun님, 1살이시네요!


function hello({name, age}) {
	console.log(`${name}님, ${age}살이시네요!`);
}
hello(person); // Jaehyun님, 1살이시네요!


// 배열 구조 분해 할당

const testArr = [1, 2, 3, 4, 5];
const [val1, val2, val3, val4, val5] = testArr;

console.log(val1); // 1

let [name] = ["Tom", 10, "Seoul"];
let [, age] = ["Tom", 10, "Seoul"]; // Tom은 무시됨
let [name, age, region] = ["Tom", 10, "Seoul"];
let [name, age, region, height] = ["Tom", 10, "Seoul"]; // height는 undefined
let [name, age, region, height = 150] = ["Tom", 10, "Seoul"];

전개 연산자 (Spread Operator)

스프레드 연산자(...)는 배열, 객체, 이터러블의 요소를 펼치는 연산자. 배열, 객체, 함수 호출 등의 상황에서 자주 쓰임


const arr1 = [1, 2, 3];
const arr2 = [4, 5];

const merged = [...arr1, ...arr2]; 
console.log(merged); // [1, 2, 3, 4, 5]

// 복사
const obj1 = { name: "Jaehyun", age: 1 };
const obj2 = { region: "Seoul", age: 3 };

const merged = { ...obj1, ...obj2 };
console.log(merged); // { name: "Jaehyun", age: 3, region: "Seoul" }
// 나중에 오는 속성이 앞에 있는 속성을 덮어씀

function sum(...args) {
  return args.reduce((acc, cur) => acc + cur);
}

console.log(sum(10, 20, 30)); // 60
console.log(sum(1, 2, 3, 4, 5)); // 15

// 스프레드 연산자 사용으로 가변 인자를 전달할 수 있음

화살표 함수

  • 함수 선언 시 function 키워드 대신 => 사용
  • 파라미터가 1개면 () 생략 가능
  • return 생략 가능
  • 생성자 함수로 사용 불가 (new 키워드 사용 불가)
  • this 바인딩 차이
    • 일반 함수 : 호출 방식에 따라 this가 동적으로 결정됨
    • 화살표 함수 : this가 정의된 시점의 상위 스코프로 고정됨

// 일반 함수 표현식
const add = function(a, b) {
  return a + b;
};

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

// 생성자 함수로 사용 불가 예시
const Person = (name) => {
  this.name = name;
};

const p = new Person("abc"); // ❌ TypeError

React Component

컴포넌트란

  • React 어플리케이션에서 UI를 구성하는 독립적인 단위 (재사용 가능한 HTML + 로직 조각)
  • 재사용 가능하고, 독립성을 가지며, UI 표현 중심(props, state를 활용해 UI 출력)

컴포넌트 종류

함수형 컴포넌트

  • React 16.8 이후 등장한 hooks 사용 가능, 라이프 사이클(생명주기) 메서드를 hooks를 통해 사용
  • 클래스형 컴포넌트에 비해 간결한 구조를 가지고 있어 많이 사용

클래스형 컴포넌트

  • hooks가 등장하기 이전에 주로 사용하던 방식, 라이프 사이클 메서드 (mount, update, unmount) 사용 가능

컴포넌트 합성 (부모 - 자식 컴포넌트)

  • 컴포넌트는 다른 컴포넌트를 포함할 수 있음

JSX

JSX(JS + XML) :JS를 확장한 문법으로 JS 파일 내부에서 HTML 문법을 사용있는 문법

  • 조건문은 삼항 연산자로 사용 (return 문 안에서 if 못쓰니깐)
  • 반복문은 map() 메서드 사용
  • 1개의 엘리먼트만 반환 (return 문 안에 최상위 태그는 1개만 존재)

Props

부모 컴포넌트가 자식 컴포넌트로 넘겨준 데이터를 props라고 함 (컴포넌트 간 state 공유 방법)

  • props는 읽기 전용 데이터
  • props를 받은 컴포넌트는 props를 직접 수정할 수 없다. (핸들러 함수를 같이 props로 넘겨주어 상위 컴포넌트에서 관리되고 있는 props 데이터를 변경하도록)

props drilling

최상위 컴포넌트에서 최하위 컴포넌트로 props를 넘겨주어야 할 때 중간에 의미 없이 props를 받아 그대로 넘기는 현상이 많아지는 것을 말함

  • props drilling가 심해질 수록 데이터 흐름 파악이 힘들고 컴포넌트 간 결합도가 높아짐 => 유지보수 헬
  • props drilling를 방지하기 위해 react의 context API, 전역 상태 라이브러리를 사용할 수 있음

children

컴포넌트 태그 사이에 들어가는 내용을 의미,

  • 부모가 자식을 감쌀 때 전달 됨
  • ReactNode 타입
  • Layout 컴포넌트를 만들 때 자주 사용

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

// 사용 예시
<Card>
  <h1>제목</h1>
  <p>내용</p>
</Card>

구조 분해 할당으로 props 추출하기


const Card = (props) => {
  return <div>{props.name}</div>;
}

// 사용 예시
<Card name='Ahn' />

구조 분해 할당을 적용해보면


const Card = ({name}) => {
  return <div>{name}</div>;
}

// 사용 예시
<Card name='Ahn' />

로 사용 가능

defaultProps

컴포넌트에 props가 전달되지 않았을 때 사용할 기본값을 지정하는 개념


const Card = ({name}) => {
  return <div>{name}</div>;
}

Card.defaultProps = {
	name: 'Ahn'
}
  • 클래스/함수형 모두 사용 가능
  • TS와 호환성 문제가 있을 수 있고 최근에는 점점 안 쓰이는 추세

const Card = ({ name = 'Ahn' }) => {
  return <div>{name}</div>;
}
  • 함수형 컴포넌트에서만 사용 가능
  • TS와 자연스럽게 호환
  • 가장 일반적이고 간단한 방법
profile
미래 프론트 어쩌고

0개의 댓글