Myalog/Study

[유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 - 사전직무교육 Day 3

myalog 2024. 8. 25. 12:18

 

사전직무교육 Day3

기업 프로젝트 KT조의 팀 미팅시간

 

오늘은 프로젝트 캠프에서의 셋째날이다.

이 날 병원 진료때문에 온라인 수업을 들었고, 기업 프로젝트 팀 미팅시간에는 참여하지 못해 내 이름이 없다..😭

 

오늘은 지난 시간에 이어 컴포넌트 스타일링 라이브러리와 폰트 적용 방법에 대해 배우고,

본격적으로 리액트 컴포넌트 문법과 이벤트, props를 배웠다!!

드디어 제일 기다리고 기다리던 시간.. (두근두근)

 


 

🧚‍♂️ Tailwind CSS

 

  • Tailwind CSS 공식문서에 나온 프레임워크 별 가이드라인대로 설치 진행 후 기본 세팅
  • tailwind-merge
    • 클래스가 중복될 경우 병합하기 위해 사용하는 라이브러리
      • twMerge()
        • 병합의 우선순위는 뒤에 있는 속성
        • 클래스 중복을 제거
      • twJoin()
        • 병합의 우선순위 상관 없이 병합
        • 클래스를 합쳐줌
  • tailwind-forms
    • tailwind의 기본 폼 스타일을 구성
    • tailwind를 index.css 파일에 초기화하게 되면, 모든 스타일이 초기화되므로 기본 폼 스타일링을 해주는 패키지
    • tailwind.config.js 파일에 플러그인을 적용해야함

 

💄 CSS-in-JS

 

  • Styled-Components
    • 가장 대중적인 CSS-in-JS 라이브러리
  • Emotion
    • Styled-Components의 단점을 개선하여 나옴
  • Vanilla Extract
    • 런타임 과정에서 연산 작업을 하지 않도록 빌드 과정에서 연산 작업을 끝냄 (Zero run time)
    • 성능 개선을 위해 등장
    • 안정성은 아직 떨어지기 때문에 별도의 추가 세팅이 필요함
  • Linaria
    • Zero run time

 

React 컴포넌트

 

컴포넌트 트리 구조

  • DOM 트리에는 형제 노드가 존재하지만, 리액트 컴포넌트 트리에는 오직 부모와 자식뿐임
  • 리액트는 깊이 우선 탐색(Depth-First Search, DFS) 알고리즘을 사용하여 컴포넌트를 생성하고 렌더링 함

컴포넌트 렌더링 순서

 

  • 특정 컴포넌트가 업데이트 되면 해당 컴포넌트는 리렌더링 됨
    • 하지만 만약 해당 컴포넌트에 하위 컴포넌트가 존재한다면 같이 리렌더링 됨
    • 반대로, 하위 컴포넌트에 업데이트가 있을 경우엔 상위 컴포넌트에 영향을 주지 않음
    • 그래서 렌더링 최적화를 위해 리렌더링이 불가피한 컴포넌트가 최하위가 될 수 있도록 컴포넌트를 설계하는 것이 중요함!

 

컴포넌트 이벤트

  • 이벤트 타입은 타입추론을 통해 확인이 가능함
  • 폼 이벤트
    • onChange
    • onSubmit
  • 마우스 이벤트
    • onClick
    • onMouseEnter
    • onMouseLeave
  • 키보드 이벤트
    • onKeyDown
    • onKeyPress
    • onKeyUp
  • 포커스 이벤트
    • onFocus
    • onBlur
  • 드래그 이벤트
    • onDragStart
    • onDragOver
    • onDrop
  • 터치 이벤트
    • onTouchStart
    • onTouchMove
    • onTouchEnd
  • 함수 자체를 이벤트로 전달할 경우 이벤트 객체(event)가 자동으로 넘어가서 바로 활용이 가능함
<button onClick={onClickHandler}>버튼 클릭</button>

 

  • 콜백 함수로 함수를 이벤트로 전달할 경우 명시적으로 이벤트 객체(event)를 매개변수로 넘겨줘야 활용 가능
<button onClick={(e)=>onClickHandler(e)}>버튼 클릭</button>

 

컴포넌트 Props

  • 컴포넌트 간에 데이터를 전달하는 방법
  • 부모 컴포넌트에서 자식 컴포넌트에 전달하는 읽기 전용 데이터임
  • props를 활용함으로써 컴포넌트의 재사용성이 높아짐

 

  • 기본 사용법
// Greeting.jsx

const Greeting = (props) => {
	return <h1>Hello, {props.name}</h1>
}

// Greeting.tsx

const Greeting = (props: { name: string }) => {
	return <h1>Hello, {props.name}</h1>
}



//App.jsx

const App = () => {
	return (
		<>
			<Greeting name="Mia" />
			<Greeting name="승미" />
			<Greeting name="뜽" />
		</>
	)
}

 

  • 표현식 사용법
const App = () => {
	return (
		<>
			<Greeting name={"Mia"} />
			<Greeting name={"승미"} />
			<Greeting name={"뜽"} />
		</>
	)
}

 

  • 구조분해할당
// Greeting.tsx

const Greeting = ({ name }: { name: string }) => {
	return <h1>Hello, {name}</h1>
}

 

  • 여러 개의 Props 전달
// UserCard.tsx
// 구조분해할당 + 여러개 props 전달

const UserCard = ({ name, age, gender }: {name: string; age: number; gender: string;}) => {
	return (
		<>
			<p>{name}</p>
			<p>{age}</p>
			<p>{gender}</p>
		</>
	)
}


// App.tsx
// 기본 사용 + 표현식 사용

const App = () => {
	return (
		<>
			<UserCard name="Mia" age={30} gender={"female"}/>
			<UserCard name="Kai" age={20} gender={"male"}/>
			<UserCard name="승미" age={10} gender={"female"}/>
		</>
	)
}

 

  • props로 이벤트나 함수를 전달할 수 있음
// UserCard.tsx

const UserCard = ({ name, age, gender, onClickHandler }: {name: string; age: number; gender: string; onClickHandler: (name: string, age: number, gender: string) => void;}) => {
	return (
		<>
			<p>{name}</p>
			<p>{age}</p>
			<p>{gender}</p>
			<button onClick={()=>onClickHandler(name, age, gender)}>버튼 클릭</button>
		</>
	)
}


// App.tsx

const App = () => {
	const onClickHandler = (name: string, age: number, gender: string) => {
		alert(`${name}, ${age}, ${gender === "male" ? "남자" : "여자"}`)
	}
	
	return (
		<>
			<UserCard name="Mia" age={30} gender={"female"} onClickHandler={onClickHandler}/>
			<UserCard name="Kai" age={20} gender={"male"} onClickHandler={onClickHandler}/>
			<UserCard name="승미" age={10} gender={"female"} onClickHandler={onClickHandler}/>
		</>
	)
}

 

  • 타입스크립트의 경우 모든 props의 타입을 지정해주어야 함
    • interface, type 등으로 모듈화 후 사용
    • 직접 props 매개변수에 타입지정 후 사용

 

📚 오늘의 과제

 

  • 프로필 카드 컴포넌트 만들기
  1. ProfileCard 컴포넌트 생성
  2. 배경 이미지, 유저 이미지, 유저 이름, 인스타 아이디를 props로 전달
  3. [Follow] 버튼을 클릭했을 때 클릭 이벤트가 발생할 수 있도록 이벤트를 props로 전달
// ProfileCard.tsx

interface ProfileCardProps {
  cardImg: string;
  userImg: string;
  userName: string;
  ig: string;
  onClickHandler: () => void;
}

const ProfileCard = ({ ...props }: ProfileCardProps) => {
  return (
    <article className="card">
      <div>
        <img className="card-img" src={props.cardImg} alt="background-pic" />
      </div>
      <div className="profile">
        <img className="prof-img" src={props.userImg} alt="profile-pic" />
        <h3 className="alias">{props.userName}</h3>
        <p className="username">{props.ig}</p>
        <button onClick={props.onClickHandler}>Follow</button>
      </div>
    </article>
  );
};

export default ProfileCard;
// App.tsx

import ProfileCard from './components/ProfileCard';

function App() {
  const imgSrc: string[] = [
    'https://cdn.pixabay.com/photo/2021/01/08/06/32/cafe-5899078_1280.jpg',
    'https://cdn.pixabay.com/photo/2019/10/03/13/20/cat-4523300_1280.jpg',
  ];

  const onClickHandler = () => {
    alert('You have successfully followed!');
  };
  return (
    <ProfileCard
      cardImg={imgSrc[0]}
      userImg={imgSrc[1]}
      userName="Meow"
      ig="@meow"
      onClickHandler={onClickHandler}
    />
  );
}

export default App;

 

가독성을 위해 props 들의 타입을 interface로 정의 후 ProfileCard 컴포넌트를 생성했다.

상위 컴포넌트인 App 컴포넌트에서 cardImg, userImg, userName, ig를 props로 전달했고,

[Follow] 버튼을 클릭했을 때 발생하는 이벤트 핸들러 함수 onClickHandler를 선언하여 props로 전달했다.

 


 

본격적으로 리액트 컴포넌트에 대해 배우면서 앞으로 배우게 될 내용이 중요하기 때문에 수업에 더 집중하고, 빠지지 않아야 흐름을 놓치지 않겠다는 생각을 했다.

이번 과제를 통해 props에 대해 좀 더 고민해보는 시간을 가질 수 있었고, 어떻게 해야 계속 늘어나는 props를 가독성 좋게 리팩토링 할 수 있을지도 고민할 수 있는 시간을 가질 수 있었다.

 

빠지지 말고 내일도 힘내보자!!!! 😎


본 후기는 본 후기는 [유데미x스나이퍼팩토리] 프로젝트 캠프 : React 2기 과정(B-log) 리뷰로 작성 되었습니다.