- HTML 태그에 고유한 id 어트리뷰트를 추가하기
- 이렇게 하면 document.getElementById로 HTML 엘리먼트를 찾아
- createRoot 사용법 문서 읽어보기
- 점진적으로 "상위 구조로 확장"
- React의 장점을 최대한 활용하기 위해 React 프레임워크로 마이그레이션하는 것을 권장
- React Native 역시 기존 네이티브 앱에 점진적으로 통합가능
- 안드로이드(Java 또는 Kotlin)나 iOS(Objective-C 또는 Swift) 앱을 개발하고 있다면, 가이드를 참고하여 React Native 화면을 추가해보기
- VS Code는 현재 가장 많이 사용되는 에디터 중 하나
- Linting
- 실시간으로 문제 찾아 줌으로써 빠른 문제해결 가능
- ESLint는 많이 사용되고 JavaScript를 위한 오픈소스 린터
- eslint-plugin-react-hooks 규칙을 활성화했느지 확인하세요. 이 규칙은 필수적
- Formatting
- 탭 vs 공백
- Prettier를 사용하면 코드 형식을 깔끔하게 정리
- Prettier 실행하면 모든 탭은 공백으로 전환, 들여쓰기, 따옴표 형식과 같은 요소들 전부 설정에 부합되도록 수정
- JavaScript 코드 베이스에 타입 정의를 추가하는데 너리 사용되는 방법
- JSX를 지원, @types/react 및 @types/react-dom을 추가하면 완전한 React Web 지원을 받을 수 있음
- 학습내용
- React 컴포넌트가 있는 TypeScript
- Hooks 타이핑 예시
- @types/react의 일반적인 타입
- 추가 학습 위치
- 프로덕션 수준의 React 프레임워크는 TypeScript 사용을 지원
- Next.js
- Remix
- Gatsby
- Expo
- tsconfig.json에 설정해야함
-
- dom은 반드시 lib 포함 (지정되지 않으면 기본적으로 dom이 포함)
-
- jsx를 유효한 옵션 중 하나로 설정
- JSX를 포함하고 있는 모든 파일은 .tsx 파일 확장자를 사용해야함
- 이것은 이 파일이 JSX를 포함하고 있음을 TypeScript에 알려주는 TypeScript 전용 확장자
- 타입 검사를 받으려면 TypeScript playground를 사용
- useCallback 함수 자체를 기억해서 불필요한 재생성을 막기위해 사용
- [DOM 이벤트]
- 이벤트 작업할 때 이벤트 핸들러로 이벤트의 타입을 추론 가능
- GitHub Pages 저장소를 생성
- .com이 아니라 .io
- GitHub에서 직접 저장소를 만들었다면 clone해서 locald에서 작업하고 push
- 정적 호스팅을 하기 위해서 반드시 필요한 저장소
- 다른 이름의 저장소도 페이지로 사용 가능
- 선택한 빌드 도구는 단일 페이지 앱(SPA)만 지원
- 서버 사이드 렌더링 SSG와 유사하지만 매 요청 시 서버에서 정적 페이지 생성
- 정적 사이트 생성(SSG) 빌드 시 한 번에 모든 정적 페이지 생성
- React 서버 컴포넌트(RSC) 서버에서 동작하는 컴포넌트로 DB 접근 가능
- 와 같은 다른 렌더링 패턴을 구현해야함
- 처음에는 이러한 기능이 필요하지 않더라도 나중에 SSR, SSG 또는 RSC에 도움이 될 수 있는 몇가지 방법이 있을 수 있음
- 단일 페이지 앱(SPA)은 단일 HTML 페이지를 로드하고, 사용자가 앱과 상호작용할 때 페이지를 동적으로 업데이트함
- SPA는 시작하기는 쉽지만 초기 로드 시간이 느릴 수 있음
- SPA는 대부분의 빌드 도구에서 기본 아키텍처로 사용됨
-
스트리밍 서버 측 렌더링 완전히 렌더링된 페이지를 클라이언트로 전송
-
정적 사이트 생성
-
React 서버 컴포넌트: 설정 및 유지관리에 대한 전문 지식 필요
- 렌더링 전략은 라우터와 통합되어야 프레임워크로 빌드된 앱이 경로별로 렌더링 전략을 선택가능
- 자주 업데이트되는 콘텐츠를 쉽게 받아볼 수 있도록 제공되는 데이터 형식
- 콘텐츠 피드란? 사용자들이 자주 업데이트되는 콘텐츠를 쉽게 받아볼 수 있도록 제공되는 데이터 형식 또는 스트림을 의미
- 올바른 경로에 적합한 렌더링 전략을 사용하면
-
- 첫 뻔째 바이트까지의 시간간
-
- 첫 뻔째 콘텐츠 페인트트
-
- 가장 큰 콘텐츠 페인트
- 그리고 더 많은 것들
- 지금까지 설명한 것은 새 앱을 처음부터 개발할 때 고려해야 할 기능의 몇 가지 예일 뿐
- 직면하게 될 많은 제약은 해결 어려움
- 스스로 해결하고 싶지 않다면, 기능을 제공하는 프레임워크를 바로 사용 가능
- 점진적으로 적용할 수 있도록 설계되었으며, 필요한 만큼 React를 사용 가능
- 간단한 HTML 페이지에 약간의 상호작용을 추가하거나 복잡한 React 기반의 앱을 시작하고자 하는 경우, 이 섹션을 참고
- 이 장에서는
-
- 새로운 React 프로젝트를 시작하는 방법
-
- 기존 프로젝트에 React를 추가하는 방법
-
- 에디터를 설정하는 방법
-
- React 개발자 도구를 설치하는 방법
- 단순히 React를 사용해 보고 싶다면, 아무것도 설치할 필요 없음
local에서 사용해 보고 싶다면 Node.js만 설치하면 됨
- React로 새로운 앱이나 웹사이트를 구축하려면 프레임워크부터 시작하는 것이 좋습니다.
- 권장 프레임워크는 프로덕션에서 앱을 배포하고 확장하는 데 필요한 모든 기능을 지원합니다.
- 최신 React 기능을 통합하고 React의 아키텍처를 활용
- 서버가 필요하지 않음
- 풀스택 React 앱을 활성화하는 React 프레임워크
- Vercel에서 유지 관리
- Node.js와 서버리스 호스팅 혹은 자체 서버에 배포 가능
- 서버가 필요 없는 정적 내보내기도 지원
- 유료 클라우드 서비스도 지원
- React Router는 React에서 가장 인기있는 라우팅 라이브러리이며, Vite와 함께 사용하면 풀스택 React 프레임워크를 만들 수 있음
- 표준 Web API이며, 다양한 자바스크립트 런타임과 플랫폼을 위한 준비된 배포 템플릿이 있다고 강조함
- React Router은 Shopify에서 유지 관리
- 네이티브 UI를 사용하여 안드로이드, ios, 웹을 위한 범용 앱을 만들 수 있는 React 프레임워크
- 네이티브 부분을 쉽게 사용할 수 있게 해주는 React Native SDK를 제공
- Expo에서 유지 관리
- 앱을 빌드하는 것은 무료, 유료 클라우드 서비스를 제공
- TanStack Start (Beta): TanStack Start는 TanStact Router를 기반으로 하는 풀스택
- RedwoodJS: Redwood는 쉽게 풀스택 웹 애플리케이션을 만들 수 있도록 사전탑재된 패키지와 구성을 가진 풀스택 React 프레임워크
- Vite는 현대 웹 프로젝트에 더 빠르고, 가벼운 개발 환경을 제공하는 것을 목표로 하는 빌드 도구
- Vite는 독창적이며, 기본적으로 합리적인 기본 기능을 제공
- Vite는 빠른 새로고침, JSX, Babel/SWC 및 기타 일반적인 기능을 지원하는 풍부한 플러그인 생태계
- 앱을 필요에 따라 로드할 수 있는 작은 묶음으로 나누는 프로세스
- 앱 로드 속드가 느려질 수 있음
- 예시 애플리케이션 내 데이터들을 생각해 봅시다. 애플리케이션은 다음과 같은 데이터를 가지고 있음
- 제품의 원본 목록
- 사용자가 입력한 검색어
- 체크박스의 값
- 필터링된 제품 목록
- 시간이 지나도 변하지 않나요? state X
- 부모로부터 props를 통해 전달됨? state X
- 컴포넌트 안의 다른 state나 props를 가지고 계산 가능? state X
- 이 외 남는 건 아마 state일 겁니다.
- 위 데이터들을 다시 한번 순서대로 살펴봅시다
- 제품의 원본 목록은 props로 전달되었기 때문에 state가 아님(우리가 하는 예제에서는/ 모든 제품 원본 목록이 그렇지 않음)
- 사용자가 입력한 검색어는 시간이 지남에 따라 변하고, 다른 요소로부터 계산될 수 없기 때문에 state로 볼 수 있음
- 체크박스의 값은 시간에 따라 바뀌고 다른 요소로부터 계산될 수 없기 때문에 state로 볼 수 있음
- 필터링된 제품 목록은 원본 제품 목록을 받아서 검색어와 체크박스의 값에 따라 계산할 수 있으므로, 이는 state가 아님
- 따라서, 검색어와 체크박스의 값만이 state
- state가 어디에 위치 돼야 하는지 결정하려면,
- 대개, 공통 부모에 state를 그냥 두면 됨
- 혹은, 공통 부모 상위의 컴포넌트에 둬도 됨
- state를 소유할 적절한 컴포넌트를 찾지 못했다면, state를 소유하는 컴포넌트를 하나 만들어서 상위 계층에 추가하기
- 두 가지 state인 "사용자의 검색어 입력과 체크박스의 값" 을 발견
- 이 예시에서 두 가지 state 항상 함께 나타나기 때문에 같은 위치에 두는 것이 합리적
- 어떤 컴포넌트가 이 state를 소유하고, 변경할 책임을 지게 할 지 정해야 함
- React는 부모에서 자식으로 데이터를 전달하는 단방향 데이터 흐름을 사용하는 것을 기억하기
- 어떤 컴포넌트가 state를 가져야 하는 지 바로 명확하지 않을 수 있음
- 해당 state를 기반으로 렌더링하는 모든 컴포넌트를 찾기
- 그들의 가장 가까운 공통되는 부모 컴포넌트를 찾기- 계층에서 모두 포괄하는 상위 컴포넌트
- state가 어디에 위치 돼야 하는지 결정하기
- state를 쓰는 컴포넌트를 찾아보자
- ProductTable은 state에 기반한 상품 리스트를 필터링
- SearchBar는 state를 표시
-
공통 컴포넌트 찾아보자
-
FilterableProductTable의 상단에 두개의 state 변수를 추가해서 초기값을 명확하게 보여주기
-
다음으로, filterText와 inStockOnly를 ProductTable와 SearchBar에게 props로 전달하기
- 하단에 있는 컴포넌트에서 FilterableProductTable의 state를 업데이트할 수 있어야 함
- 체크하거나 키보드를 타이핑할 경우 UI의 변화가 없고 입력을 무시하는 것을 확인할 수 있음
-
React를 사용하게 되면 우리가 고려하고 있는 디자인이나 만들 앱들에 대한 생각을 바꿀 수 있습니다.
-
React로 사용자 인터페이스를 빌드할 때, 먼저 이를 컴포넌트라는 조각으로 나눕니다.
-
그리고 각 컴포넌트의 다양한 시각적 상태들을 정의합니다.
-
마지막으로 컴포넌트들을 연결하여 데이터가 그 사이를 흘러가게 합니다.
-
이 자습서에서는 React로 검색할 수 있는 상품 테이블을 만드는 과정을 체계적으로 안내할 예정
- 먼저 모의 시안에 있는 모든 컴포넌트와 하위 컴포넌트 주변에 박스를 그리고, 그들에게 이름을 붙이면서 시작
- 디자이너와 함께 일한다면 그들이 이미 디자인 툴을 통하여 이 컴포넌트들에 이름을 정해 두었을 수도 있습니다. 한번 여쭤보세요!
- 어떤 배경을 가지고 있냐에 따라, 디자인을 컴포넌트로 나누는 방법에 대한 관점이 달라질 수 있음
- Programming: 새로운 함수나 객체를 만드는 방식과 같은 방법으로 해봅시다.
-
- 이 중 단일책임 원칙을 반영하고자 한다면 컴포넌트는 이상적으로는 한 번에 한 가지 일만 해야함
-
- 만양 컴포넌트가 점점 커진다면 작은 하위 컴포넌트로 쪼개져야함
- CSS : 클래스 선택자를 무엇으로 만들지 생각해 봅시다.
- Design: 디자인계층을 어떤 식으로 구성할 지 생각해 봅시다.
- FilterableProductTable(회색): 예시 전체를 포괄
- SearchBar(파란색): 사용자의 입력을 받습니다.
- ProductTable(라벤더색): 데이터 리스트를 보여주고, 사용자의 입력을 기반으로 필터링링
- ProductCategoryRow(초록색): 각 카테고리의 헤더를 보여줌
- ProductRow(노란색): 각각의 제품에 해당하는 행을 보여줌
- ProductTable을 보면 Name과 Price 레이블을 포함한 테이블 헤더 기능만을 가진 컴포넌트는 없음
- 독립된 컴포넌트를 따로 생성할 지 말지는 당신의 선택
- 위 레이블들을 컴포넌트로 만들지 않고 그냥 남겨둠
-
가장 쉬운 접근 방법은 상호작용 기능은 아직 추가하지 않고, 데이터 모델로부터 UI를 렌더링하는 버전을 만드는 것
-
먼저 정적인 버전을 만들고 상호작용 기능을 추가하는 게 더 쉬움
-
정적 버전을 만드는 것은 많은 타이핑 필요하지만, 생각할 것 적음
-
데이터 모델을 렌더링하는 앱의 정적인 버전위해
-
- props 이용
- props 이용
-
정적인 버전을 만드는 데는 state를 쓰지 마세요
-
시간이 지남에 따라 데이터가 바뀌는 것에 사용
-
정적 버전을 만들고 있기 때문에 지금은 필요없음
-
앱을 만들 때 계층 구조에 따라 상층부에 있는 컴포넌트 즉, 1. FilterableProductTable부터 시작하는 하향식(top-down)으로 만드는 방법
-
하층부에 있는 컴포넌트인 5. ProductRow부터 상향식(bottom-up)으로 만들 수도 있음
-
간단한 예시에서는 보통 하향식으로 만드는 게 쉽지만, 프로젝트가 커지면 상향식으로 만들고 테스트를 작성하면서 개발하기 더 쉽습니다.
- state를 구조화하는데 가장 중요한 원칙은 중복배제원칙임
- 가장 최소한의 state를 파악하고 나머지 모든 것들은 필요에 따라 실시간으로 계산하세요
- 예를 들어, 쇼핑 리스트를 만든다고 하면 당신은 배열에 상품 아이템들을 넣을 겁니다
- UI에 상품 아이템의 개수를 노출하고 싶다면, 상품 아이템 개수를 따로 state 값으로 가지는 게 아니라 단순하게 배열의 길이만 쓰면 됨
- 예시 애플리케이션 내 데이터들을 생각해 봅시다. 애플리케이션은 다음과 같은 데이터를 가지고 있음
- 제품의 원본 목록
- 사용자가 입력한 검색어
- 체크박스의 값
- 필터링된 제품 목록
- 시간이 지나도 변하지 않나요? state X
- 부모로부터 props를 통해 전달됨? state X
- 컴포넌트 안의 다른 state나 props를 가지고 계산 가능? state X
- 이 외 남는 건 아마 state일 겁니다.
- 이반 JavaScrit 객체이므로 애플리케이션에서 전달 가능
- 여러 엘리먼트를 렌덜이하려면 React 엘리먼트 배열을 사용 가능
- state에 이동 history 배열이 있기 때문에 이것을 React 엘리먼트 배열로 변환해야함
- 한 배열을 다른 배열로 변환하려면 배열 map 메서드를 사용하면 됨
- history 배열을 화면의 버튼을 나타내는 React 엘리먼트로 변환
- "점프"할 수 있는 버튼 목록을 표시
- Game 컴포넌트에서 history를 map을 이용
- map의 기본 구문은 map(callbackFn)혹은 map(callbackFn, thisArg)
- thisArg은 내부에서 this로 사용할 값을지정하는 화살표함수에서는 생략됨
- squares, move는 화살표 함수의 매개변수임
- historys는 모든 플레이를 저장하는 배열. 이 histroy에 map함수를 적용
- history 각각의 요소 index를 순회하면서 squares 추출함
- 각 요소는 {}안의 실행문을 실행하면서 버튼 생성
- 생성된 버튼은 moves 객체(배열)에 다시 저장됨
- move는 최종 rendering에 사용됨
- 다시 정리하면
- 원본 배열(history): map이 호출된 원본 배열
- 원본 배열의 인덱스 (move): 현재 순환 중인 원본 배열 요소의 인덱스
- 요소 값 (squares): 현재 순회 중인 요소 배열의 값값
- 리스트를 렌더링할 때 React는 렌더링 된 각 리스트 항목에 대한 몇 가지 정보를 저장
- 업데이트를 할 때 React는 무엇이 변경되었는지 확인해야함
- 리스트의 항목은 추가, 제거, 재정렬 또는 업데이트될 수 있음
- task의 개수가 업데이트 되었을 뿐만 아니라 Alexa와 Ben의 순서가 바뀌고 Claudia가 두 사람 사이에 추가되었다고 생각할 것임
- 그러나 React는 컴퓨터 프로그램이므로 모름름
- 리스트이 항목에 Key 프로퍼티를 지정하여 각 리스트의 항목이 다른 항목과 다르다는 것을 구별해주어야함
- 만약 데이터베이스에서 데이터를 불러와서 사용한다면 Alexa, Ben, Claudia의 데이터베이스 ID를 key로 사용할 수 있음
- 각 리스트 항목의 key를 가져와서 이전 리스트의 항목에서 일치하는 key를 탐색
- 이전에 존재하지 않았던 key가 있으면 React는 컴포넌트를 생성
- Key를 가지고 있지 않다면 React는 그 key를 가진 컴포너트를 제거
- 두 Key가 일치한다면 해당 컴포넌트는 이동함
- key는 React에서 특별하게 미리 지정된 프로퍼티입니다.
- 반환되는 엘리먼트에 직접 key를 저장함
- 자동으로 key를 사용해 업데이트할 컴포넌트를 결정
- 부모가 지정한 key가 무엇인지 컴포넌트는 알 수 없음
- 동적인 리스트를 만들 때마다 적절한 key를 할당하는 것을 강력하게 추천
- key가 없는 경우 데이터의 재구성을 고려
- key가 지정되지 않는 경울, React는 경고를 표시, 배열의 인덱스를 기본 key로 사용
- 배열 인덱스를 key로 사용하면 항목의 순서를 바꾸거나 항목을 추가/제거할 때 문제가 발생
- 명시적으로 key={i}를 전달하면 경고는 사라지지만, 배열의 인덱스를 사용할 때와 같은 문제가 발생하므로 대부분은 추천하지 않습니다.
-
handleClick 함수는 JavaScript의 slice() 배열 메서드를 사용하여 squares 배열의 사본인 nextSquares를 생성합니다.
-
그 다음 handleClick 함수는 nextSquares 배열의 첫 번째 Squares(indes [0])에 X를 추가하며 업데이트
-
i를 handleClick에 전달해야 함
-
Square의 onSquareClick prop를 아래와 같이 JSX에서 직접 handleClick(0)으로 설정할 수도 있지만, 이 방법은 작동하지 않음
=> 객체만 전달해라
-
() => handleClick(0)은 화살표 함수로, 함수를 짧게 정의하는 방법입니다.
-
Square가 클릭되면 => "화살표" 뒤의 코드가 실행되어 handleClick(0)을 호출합니다.
-
handleClick(0) 함수를 화살표 함수가 호출하고, 화살표 함수를 Sqaure에 전달
-
나머지 8개의 Sqaure 컴포넌트 수정
-
왼쪽 위 사각형 클릭시 button이 Square로부터 onClick prop으로 받은 함수가 실행됨
-
squares 배열의 첫번째 엘리먼트를 null에서 X로 업데이트
-
Board 컴포넌트의 square state가 업데이트되어 Board와 그 모든 자식이 다시 렌더링됨
-
최종적으로 사용자는 왼쪽 위 사각형을 클릭한 후 비어있는 사각형이 X로 변경된 것을 확인
-
DOM < button > 엘리먼트의 onClick 어트리뷰트(속성)는 빌트인 컴포넌트이기 때문에 React에서 특별한 의미
-
사용자 정의 컴포넌트, 예를 들어 Square의 경우 이름은 사용자가 원하는대로 지을 수 있음
-
Square의 onSquareClick prop나 Board의 handleClick 함수에 어떠한 이름을 붙여도 코드는 동일하게 작동
-
React에서는 주로 이벤트를 나타내는 prop에는 onSomething과 같은 이름을 사용하고, 이벤트를 처리하는 함수를 정의할 때는 handleSomething과 같은 이름을 사용
- 원본 데이터를 직접 변형하지 않음으로써 몇가지 이점을 얻을 수 있음
- 불변성을 이용하면 복잡한 기능을 훨씬 쉽게 구현가능
- 특정 작업을 실행 취소하고 다시 실행하는 기능은 앱의 일반적인 요구사항
- 이전 버전의 데이터를 그래돌 유지하여 나중에 재사용할 수 있음
- 불변성을 사용하는 것의 또 다른 장점이 있음
- 부모 컴포넌트의 state가 변경되면 모든 자식 컴포넌트가 자동으로 다시 렌덜이 됨
- 변경사항이 없는 자식 컴포넌트도 포함
- 사용자에게 보이는 것은 아니지만, 트리의 영향을 받지 않는 부분의 리렌더링을 피하는 것이 좋음
- 데이터의 변경 여부를 저렴한 비용으로 판단 가능
- 비구조화 할당, 구조화 할당이라고도 번역되지만 구조 분해 할당을 많이 사용합니다.
- 배열이나 객체의 구조를 해체하여 내부 값을 개발 변수에 쉽게 할당하는 방법
- 코드의 간결성과 가독성을 높임
- map함수에서도 사용되는 아주 많이 사용하는 방법
- 이제 Board에서 Square로 prop value를 전달해 보겠습니다.
- 정상적으로 출력되는지 확인해 보세요.
- Square 컴포넌트를 클릭하면 X로 채워지게 코드를 수정해 보겠습니다.
- 먼저 Square 내부에 handleClick 함수를 선언
- Square 컴포넌트에서 반환되는 JSX 버튼의 props에 onClick 추가
- 다음으로 사각형 컴포넌트가 클릭 된 것을 기억하고 X로 채우기
- 컴포넌트는 무언가 기억을 위해 useState라는 Hook을 제공
- Sqaure의 현재 값을 state에 저장하고, Square가 클릭하면 값이 변경
- 파일 상단에서 useState를 import합니다.
- Square 컴포넌트에서 value prop을 제거합니다. 대신 useState를 사용
- Square 컴포넌트의 시작 부분에 useState를 호출하고, value라는 이름의 state 변수를 반환
- React 개발자 도구를 사용하면 React 컴포넌트의 props와 state를 확인할 수 있습니다.
- CodeSandBox의 브라우저 구역 하단에서 React 개발자 도구 탭을 찾을 수 있습니다.? 찾을 수가 없음.ㅠㅠ
- 개발자 도구에서 component를 열면 프로젝트 관련 정보를 얻을 수 있음
- State 끌어올리기
- 현재 각 Square 컴포넌트는 게임 state의 일부를 기억합니다.
- 틱택토 게임에서 승자를 확인하려면 Board가 9개의 Square 컴포넌트 각각의 state를 기억하고 있어야 합니다.
- Board가 각각의 Square에서 기술적으로는 가능하지만, 코드가 이해하기 어렵고 버그에 취약하며 리팩토링하기 어렵기 때문에 권장하지 않습니다.
- 가장 좋은 방법은 state를 각 Square가 아닌 부모 컴포넌트인 Board에 저장하는 것입니다.
- Board 컴포넌트는 각 Square에 숫자를 전달했을 때와 같이 prop를 전달하여 각 Square에 표시할 내용을 정할 수 있습니다.
- 여러 자식 컴포넌트에서 데이터를 수집하거 고유하려면 부모 컴포넌트에서 공유 state를 선언해야함
- 부모 컴포넌트는 props를 통해 해당 state를 자식 컴포넌트에 전달 가능
- 자식 컴포넌트가 서로 동기화되고 부모 컴포넌트와도 동기화 가능
- component 분리하기
- Board와 Square 분리
- component 내부에 event handler 함수를 선언하면 event에 응답할 수 있습니다.
- onClick-(handleClick)의 끝에 소괄호()가 없는 것을 주목하세요!
- 함수를 호출하지 않고 전달만 하면 됩니다.
- React는 사용자가 버튼을 클릭할 때 이벤트 핸들러를 호출합니다.
- component가 특정 정보를 "기억"해 두었다가 표시하기를 원하는 경우가 있습니다.
- 예를 들어 버튼이 클릭된 횟수를 세고 싶을 수 있습니다.
- 이렇게 하려면 component에 state를 추가하면 됩니다.
- 먼저, React에서 useState를 import합니다.
- 이 코드를 보면 useState는 react 파일 안에 Named Exports로 선언되어 있는 여러 개의 component 중 하나라는 것을 알 수 있습니다.
- 이제 component 내부에 state 변수를 선언할 수 있습니다.
- App.js에 CountState component를 호출합니다.
- 버튼은 반드시 2개 이상을 만들어야 합니다.
- 출력이 정상으로 되는지 확인하고 버튼을 테스트합니다.
- 화면이 아래쪽으로 너무 길면 CSS를 수정해서 두 구역으로 나눠 주세요.
- use로 시작하는 함수를 Hook라고 합니다.
- useState는 React에서 제공하는 내장 Hook입니다.
- 다른 내장 Hook은 API 참고서에서 찾아볼 수 있습니다.
- 또한 기존의 것들을 조합하여 자신만의 Hook을 작성할 수도 있습니다. 사용자 Hook
- Hook은 다른 함수보다 더 제한적입니다. 예를 들면
- component 또는 다른 Hook의 상단에서만 Hook을 호출할 수 있습니다.
- 조건이나 반복문에서 useState를 사용하고 싶다면 새 컴포넌트를 추출하여 그곳에 넣으세요
- Hook은 React의 렌더링 및 상태 관리 메커니즘과 밀접하게 연결되어 있으며, 아래와 같은 규칙을 따라야 합니다.
- 최상위에서만 호출해야 한다.
if, for, while 등의 블록 내부에서 Hooks를 호출 - React 함수형 component 또는 사용자 Hook 내부에서만 사용 가능
- 사이트에서는 MyButton으로 설명하고 있지만, 우리는 CountState로 작성했던 것을 기억하고 사이트의 설명을 봐야 합니다.
- 하지만 데이터를 공유하고 항상 함께 업데이트하기 위한 component가 필요한 경우가 많습니다.
- 두개의 CountState2 component가 동일한 count를 표시하고 함께 업데이트하려면, state를 개별 버튼에서 모든 버튼이 포함된 가장 가까운 component 안으로 이동해야 합니다.
- 여기서 이야기하느 제일 가까운 component는 App component입니다.
- component는 고유한 로직과 모양을 가진 UI의 일부
- 버튼처럼 작을 수도 있고, 전체 페이지처럼 클 수도 있습니다.
- 마크업을 반환(return)하는 JavaScript 함수
- Nesting은 CSS선택자의 중첩 구조를 생각하면 쉽게 이해할 수 있습니다.
- css 중첩 구조는 2023년부터 자체 지원함. 이전에는 Sass나 Lass 등을 이용할 때 사용함.
- MyApp라는 함수형 component를 만들어 보겠습니다.
- 어떤 디렉토리에 파일을 만들지?
- 파일 이름은 뭐라고 할지?
- 함수는 어떻게 구성할지?
- 우리가 사용할 component는 src/ 아래 만들어야 합니다.
- 이번에는 MyApp을 만들지 않고 기존의 App.js를 이용
- 하나의 파일 안에 여러개 component가 있을 때 사용
- component를 사용하는 쪽에서는 component 정확한 이름 명시해야 합니다.
- 하나의 파일 안에서 하나의 component만 내보내는 경우 사용
- component를 사용하는 쪽에서는 어떤 이름을 사용해도 상관 없습니다.
- 앞에서 작성한 코드의 마크업 문법을 JSX라고 함
- 편의성 위해 사용
- JSX는 HTML보다 더욱 엄격한 문법을 적용
- React에서는 여러 개의 component를 JSX 태그로 반환할 수 있음
- 다만 여러 개의 component를 <div>...</div> 또는 빈 < >...</ > wrapping해 줘야 합니다.
- React에서는 className으로 CSS 클래스를 지정
- className은 HTML의 class 속성과 동일한 방식으로 동작
- CSS 파일을 추가하는 방법을 규정하지 않음-> 정적 페이지를 작성할 때와 동일한 방법을 지원
- 가장 간단한 방법은 HTML에 <link>태그를 추가하는 것
- JSX를 사용하면 자바스크립트에 마크업을 넣을 수 있습니다. -> JS안의 마크업 안에 JS를 넣는다는것이 더 정확
- JSX 코드 내에서 JavaScript로 "탈출"하여 변수나 표현식을 사용하는 것
- 이 방법을 Excape Back이라고 합니다.
- { } 중괄호를 사용해서 변수나 표현식을 사용자에게 표시하도록 하는 것
- 단순히 문자열을 전달하는 경우에는 중괄호 대신 큰 따옴표 사용
- React에서 조건문을 작성하는 데에는 특별한 문법이 필요 없습니다.
- 일반적인 자바스크립트 코드를 작성할 때 사용하는 것과 동일한 방법을 사용
- 문서에서는 CodeSandBox를 사용해서 학습을 진행한다고 합니다.
- 그러나 우리는 이미 CRA로 프로젝트를 생성하는 방법을 알고 있기 때문에 local에 프로젝트를 생성하고 학습을 진행합니다.
- 만일 현재 사용하고 있는 프로젝트를 생성하고 바로 commit을 했다면, switch 명령으로 처음 commit으로 이동한 후 새로운 branch를 만들어 진행하면 됩니다.
- 프로젝트를 새로 생성하거나, 초기 commit으로 switch해서 새 branch를 만듭니다.
- src/에 있는 파일 중 불필요한 파일을 삭제합니다. 반드시 삭제해야 하는 것은 아닙니다.
-
App.js: 메인 컴포넌트
-
index.js: React 앱의 진입점(entry point).ReactDOM.createRoot를 사용하여 App.js를 렌더링함.
-
.gitignore: Git에 추가하지 않을 파일 목록을 정의.
-
pagcke.json: 의존성 파일
-
node_modules/: 초기 node module 및 새로 설치하는 패키지가 저장됩니다. git으로 관리하지 않기 때문에 디렉토리 이름이 흐릿하게 나와 있는 것을 확인할 수 있습니다.(압축하지 말 것)
-
public/: 정적(static) 파일을 저장하는 디렉토리 입니다. build 후 배포할 html, CSS, JavaScript 등이 보관되는 곳입니다. 개발하면서 특별히 수정할 코드는 없습니다.
-
public/index.html: html 파일
-
src/: React 프로젝트의 주요 코드가 위치하는 디렉토리입니다. 개발하면서 대부분의 작업이 이루어지는 곳입니다.
-
src/App.js: 메인 commponent로 필요한 sub component를 모아서 관리합니다. 출력을 위해서 index.js로 전달됩니다.
-
src/App.css: App.jc에 적용되는 스타일을 정의하는 스타일 파일입니다.
-
src/index.js: React 앱의 진입 점으로 최종 렌더링의 되는 곳입니다.ReactDOM.creatRoot 사용하여 App.js를 렌더링합니다. 메인메소드같은거, commponent가 아님.
-
src/index.css: 전역 스타일을 정의하는 스타일 파일입니다.
- package.json은 패키지의 의존성을 관리하는 파일
- 의존성이란, 하나의 소프트웨어가 다른 소프트웨어(라이브러리, 패키지, 모듈 등)에 의존하여 동작하는 관계
- 즉 어떤 프로젝트에 사용된 각종 패키지 등의 버전을 동일하게 유지하기 위한 것입니다.
- 협업을 할 때는 팀원들 각자의 컴퓨터에 같은 패키지들을 설치해서 동일한 개발환경을 구성해야 합니다. 코드는 GitHub 등 Git server를 이용하지만, node 패키지는 각 팀원들이 설치해야 합니다.
- 의존성을 무시하면 다른 버전의 패키지를 설치하는 팀원 때문에 개발 프로젝트의 오류 등이 발생할 수 있습니다.
- 개인의 경우도 GitHub에 있는 코드를 내려 받은 후에 동일한 개발환경을 구성해야 할 때가 있습니다.
- 손쉬운 설치 및 업데이트
- 일관된 개발 환경 유지지
- 중복 설치 방지지
- 프로젝트에 필요한 라이브러리를 쉽게 설치, 업데이트, 유지할 수 있도록 도와주는 시스템입니다.
- React component는 JavaScrip함수입니다.
- Reat에서 사용되는 마크업을 JSX(Javascript Syntax eXten)
- React component는 데이터를 수신하고, 화면에 표시해야 하는 내용을 반환합니다.
- React는 라이브러리이기 때문에 component를 조합할 수 있지만 라우팅 및 데이터 가져오기 방법 등을 규정하지는 않습니다.
- React로 전체 앱을 빌드하려면 Next.js또는 Remix와 같은 full-stack React Framework을 사용하는 것이 좋습니다.
- React도 하나의 아키텍처입니다.
- 따라서 이를 구현하는 Framework를 사용하면, 서버에서 실행되거나 혹은 빌드 중에도 비동기 component에서 데이터를 가져올 수도 있습니다.
- 또한 파일이나 데이터베이스에서 데이터를 읽어와서 대화형 component에 전달할 수도 있습니다.
- full-stack App을 개발하는 것이라면 Framework을 사용하는 것이 생산성이 높습니다.
- 동일한 기술을 사용하여, 웹앱과 네이티브 앱을 모두 구축할 수 있습니다.
- 각 플랫폼의 고유한 강점을 활용하여 모든 플랫폼에 잘 어울리는 인터페이스를 구현할 수 있습니다.
- 빠르게 로드되기
- 서버에서 데이터를 가져오는 동안에도 html을 스트리밍을 시작할 수 있기 때문에, JavaScript 코드가 로드되기 전에 콘텐츠를 점진적으로 채울 수 있습니다.
- 클라이언트 측에서는 표준 웹 API를 사용해서, 렌더링 도중에도 UI를 반응하도록 할 수 있습니다.
- 이런 동작들은 사람들이 원하는 빠른 렌더링을 도와줍니다.
- 사람들은 네이티브 앱이 자신의 플랫폼과 같은 모양과 느낌을 주기를 원합니다.
- React Native와 Expo를 사용하면 Android, IOS 등을 위한 앱을 React로 빌드할 수 있습니다.
- 앱이 네이티브처럼 보이고, 느껴지는 이유는 UI가 네이티브이기 때문입니다.
- 즉 Web View가 아니라 플랫폼에서 제공하는 Android 및 iOS View를 사용하기 때문입니다.
- React를 사용하면 웹 개발자도 네이티브 개발자도 될 수 있습니다.
- 사용자 경험의 희생 없이 다양한 플랫폼에 앱을 출시할 수 있습니다.
- 기업에서는 플랫폼 간의 장벽을 허물고, 전체 기능을 협업을 통해 개발할 수 있는 팀을 구성할 수 있습니다.
Node.js는 라이언 달(Ryan Dahl) 이 2009년에 개발했습니다. 당시 웹 개발은 Apache 서버를 기반으로 한 동기식 처리 방식이 주류였고, 확장성과 성능의 한계가 있었습니다.
라이언 달은 브라우저의 비동기 이벤트 처리 모델을 서버에서도 사용할 수 있도록 만들고 싶었습니다. 특히, 파일 업로드 상태를 실시간으로 확인하지 못하는 기존 서버의 문제를 해결하고자 했습니다.
- Node.js는 V8 JavaScript 엔진(Chrome에서 사용됨)을 기반으로 동작합니다.
- 논블로킹 I/O 모델과 이벤트 기반 아키텍처를 적용해 빠른 서버 처리가 가능하게 했습니다.
- 2009년 JSConf EU에서 처음 공개되었으며, 많은 개발자들이 관심을 가졌습니다.
- 기존의 서버 개발 방식과 달리 단일 스레드 이벤트 루프 방식이 혁신적인 개념으로 주목받았습니다.
- 현재는 오픈소스 프로젝트로, 많은 개발자와 기업들이 기여하고 있습니다.
- 2015년, Node.js 재단(Node.js Foundation)이 설립되었고, 이후 OpenJS 재단과 통합되어 관리되고 있습니다.
- Netflix, PayPal, LinkedIn 등 대기업에서도 Node.js를 활용하며, 웹 서버, API 개발, 마이크로서비스 등 다양한 분야에서 사용되고 있습니다.
- 웹 서버 및 API 개발 – Express.js와 같은 프레임워크를 사용하여 RESTful API, GraphQL 서버 등을 구축하는 데 사용됨.
- 실시간 애플리케이션 – 채팅 앱, 실시간 데이터 스트리밍, WebSocket 기반 서비스(예: 온라인 게임, 주식 거래 시스템) 등에 활용됨.
- 마이크로서비스 및 서버리스 – AWS Lambda, Google Cloud Functions 등과 함께 사용하여 확장성이 뛰어난 분산 시스템을 구축하는 데 사용됨.
- 비동기 이벤트 기반 아키텍처 – 논블로킹 I/O 방식으로 빠른 성능과 높은 확장성 제공
- JavaScript 풀스택 개발 – 프론트엔드와 백엔드를 같은 언어(JavaScript)로 개발 가능, 생산성 증가
- 강력한 npm 생태계 – 수많은 오픈소스 라이브러리와 모듈을 쉽게 활용 가능
- 마이크로서비스 및 서버리스 아키텍처 지원 – 확장성이 뛰어나고 클라우드 환경에 최적화
- 대기업 및 커뮤니티 지원 – Netflix, PayPal, LinkedIn 등 대기업에서 적극 사용하며, 활발한 커뮤니티 존재
- 지속적인 업데이트 및 최적화 – V8 엔진 업그레이드와 성능 개선이 계속 이루어지고 있음.
- Deno와의 경쟁 속 발전 – 창시자인 라이언 달이 만든 Deno의 등장으로, Node.js도 보안과 성능을 개선 중.
- 서버리스 및 클라우드 네이티브 환경 적합 – AWS Lambda, Azure Functions 등에서 널리 사용되며 확장성 강화.
- npm 생태계의 성장 – 패키지 관리 및 모듈 생태계가 더욱 강력해지고 있음.
- 대기업과 커뮤니티 지원 – 오픈소스 커뮤니티와 대기업(Netflix, Microsoft 등)의 지속적인 기여로 성장 가능성 높음.
- 빠른 성능 – Chrome V8 엔진을 기반으로 동작하며, 비동기 및 논블로킹(Non-blocking) 방식으로 요청을 처리하여 빠른 속도를 자랑함.
- JavaScript 풀스택 개발 가능 – 프론트엔드와 백엔드를 모두 JavaScript로 개발할 수 있어, 개발 생산성이 높아지고 코드 재사용이 용이함.
- 활발한 생태계 – npm(Node Package Manager)을 통해 수많은 오픈소스 라이브러리를 활용할 수 있어 개발이 빠르고 효율적임.
- 실시간 애플리케이션 개발에 강함 – WebSocket 및 Socket.io를 활용하여 채팅, 스트리밍, 실시간 알림 등의 기능을 쉽게 구현할 수 있음.
- 마이크로서비스 및 서버리스 아키텍처에 적합 – AWS Lambda, Google Cloud Functions 등의 서버리스 환경에서 사용하기 좋으며, 마이크로서비스 구조와도 잘 맞음.
- 싱글 스레드 특성으로 CPU 집약적인 작업에 부적합 – Node.js는 싱글 스레드 이벤트 루프 기반이므로, CPU를 많이 사용하는 연산(예: 대규모 데이터 처리, 이미지 렌더링 등)에 취약함.
- 콜백 지옥(Callback Hell) 문제 – 비동기 코드가 많아질수록 콜백 함수가 중첩되면서 코드가 복잡해지고 가독성이 떨어지는 문제가 있음. (→ 해결책: async/await, Promise 활용)
- 보안 취약점 – npm 패키지 의존성이 많아 보안 취약점이 발생할 가능성이 크며, 자주 업데이트 및 관리를 해야 함.
