-
모던 리액트 Deep Dive - 리액트 개발을 위해 꼭 알아야 할 JSReact 2024. 2. 12. 18:32
1. 자바스크립트의 데이터 타입
1) 원시 타입
- boolean
0, -0, 0n, 0x0n은 부호나 소수점 유무에 상관없이 falsy한 값
NaN은 Number타입
- null
type of null === 'object' // true?
typeof로 null을 확인했을 때 해당 타입이 아닌 object가 반환.
명시적으로 비어 있음을 나타내는 값
- undefined
선언됐지만 할당되지 않은 값.
- number
- string
백틱을 사용해서 표현한 문자열을 템플릿 리터럴이라고 함.
같은 문자열을 반환하지만 줄바꿈이 가능하고, 문자열 내부에 표현식을 쓸 수 있음.
- symbol
심볼은 심볼함수를 이용해서만 만들 수 있음.
- bigint
number가 다룰 수 있는 숫자 크기의 제한을 극복하기 위해 ES2020에서 새롭게 나온 것.
* 질문)
bigint와 symbol을 사용하는 코드를 접해본적이 없는데, 많이 사용이 되는가?
2) 객체 타입
7가지 원시 타입 이외의 모든 것. 배열 함수 정규식 클래스 등 포함.
객체타입은 참조럴 전달한다고 해서 참조 타입(reference type)으로도 불림.
function hello() {} typeof hello === 'function' //true const hello1 = function() { } const hello2 = function() { } hello1 === hello2 // false
객체인 함수의 내용이 육안으로는 같아 보여도 참조가 다르기 때문에 false가 반환
3) 값을 저장하는 방식의 차이
객체는 프로퍼티를 삭제 추가 수정할 수 있으므로 원시 값과 다르게 변경 가능한 형태로 저장. 값을 복사할 때도 값이 아닌 참조를 전달.
var hello = { greet: 'hello, world' } var hi = { greet: 'hello, world' } console.log(hello===hi) // false console.log(hello.greet === hi.greet) // true
위처럼 동등비교하면 false, 내부 속성값을 비교하면 true가 나옴.
4) Object.is
Object.is는 두 개의 인수가 동일한지 확인하고 반환하는 메서드.
'=='와 '==='이 만족하지 못하는 몇 가지 특이 케이스를 추가하기 위해 Object.is가 나름의 알고리즘으로 작동.
단, 한 가지 주의해야 할 점
-> Object.is도 객체 비교에는 별 차이가 없음.
*질문 (p.30~34)
책에서 나온 objectIs와 shallowEqual을 통해서, Object.is로 먼저 비교를 수행한 다음에 Object.is에서 수행하지 못하는 비교, 즉 객체 간 얕은 비교를 한 번 더 수행하는 것을 알 수 있다고 나오는데, 이를 어떻게 알 수 있는지 도통 모르겠음.
2. 함수
작업을 수행하거나 값을 계산하는 등의 과정을 표현하고, 이를 하나의 블록으로 감싸서 실행 단위로 만들어 놓은 것.
1) 함수 선언문
function (a,b) { return a + b }
2) 함수 표현식
a. 일급 객체
다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 의미
js에서 함수는 일급 객체
const sum = function (a,b) { return a + b } sum(10,24) // 34
const sum = function add(a,b) { return a + b } sum(10,24) // 34 add(10,24) // add is not defined
실제로 함수 호출 위해서 사용된 것은 sum. 그리고 add는 실제 함수 내부에서만 유효한 식별자일 뿐. 함수를 외부에서 호출하는 데에는 사용할 수 없는 식별자다.
-> 함수 표현식에서 함수에 이름을 주는 것은 함수 호출에 도움이 안되고, 코드를 읽는데 방해가 될 수 있다.
** 함수 표현식과 선언 식의 차이
가장 큰 차이는 '호이스팅'
hello(); // hello function hello() { console.log('hello') } hello(); // hello
맨 앞에서 호출한 hello()는 어떠한 에러도 없이 작동을 수행.
함수의 호이스팅은 함수에 대한 선언을 실행 전에 미리 메모리에 등록하는 작업을 의미
반면 함수 표현식은 함수를 변수에 할당. 변수도 마찬가지로 호이스팅이 발생하나,
함수의 호이스팅과는 다르게 호이스팅 되는 시점에서 var r같은 경우에는 undefined로 초기화 된다는 차이가 있다.
hello(); // hello is not a function var hello = function () { console.log('hello') } hello(); // hello
함수와 다르게 변수는 런타임 이전에 undefined로 초기화되고, 할당문이 실행되는 시점, 즉 런타임 시점에 함수가 할당되어 작동한다는 것을 알 수 있다.
**뭐가 더 좋은가?함수를 자유롭게 선언하고 자유롭게 호출하고 싶다 -> 함수 선언문
그러나 실제 함수를 어디서 어떻게 선언했는지 해당 스코프를 끝까지 확인하지 않으면 개발자가 찾기 어려운데, 이는 관리해야 할 스코프가 길어질 경우 더 나쁘게 작용.
=> 둘 중에 더 우위에 있는 것은 없음. 본인이나 프로젝트의 상황에 맞는 작성법을 일관되게 사용하면 충분.
3) Function 생성자
const add = new Function('a', 'b', 'return a + b') add(10, 24)
함수 클로저가 생성되지 않음. 여러모로 권장되지 않는 지원 방식
4) 화살표 함수
const add = (a,b) => { return a + b }
화살표 함수에는 constructor와 arguments사용 불가.
**arguments란?
자바스크립트 함수 내에서 사용되는 특별한 객체.
함수를 정의할 때 명시적으로 매게변수를 정의하지 않고도 함수 내에서 전달된 인수들을 처리해야 할 때 유용함.
**화살표 함수와 일반 함수의 차이
this 바인딩
(this에 대한 자세한 내용은 예전에 필자가 작성한 글 2번 함수호출 참조)
링크 : https://popeyes9304.tistory.com/28
[JS] this에 대해 알아보자!
평소에 저는 혼자 공부할 때 우테코 문제를 풀어보면서 공부를 진행했었는데요, class를 자주 사용하는 형식이다 보니 아무래도 this를 자주 쓰게 되더라구용. 문득 이런 생각이 들었습니다. ‘내
popeyes9304.tistory.com
5) 즉시 실행 함수
(function (a,b) { return a + b })(10,24); //34
즉시 실행 함수는 한 번 선언하고 호출된 이후에 재호출 불가.
독립적인 함수 스코프 운용한다는 장점 있음.
재사용되지 않는 함수이고 한 번만 사용된다면 충분히 사용 검토해보자.
6) 고차함수
함수를 인수로 받거나 결과로 새로운 함수를 반환시킬 수 있는 역할을 하는 함수를 고차 함수라고 한다.
const doubledArray = [1,2,3].map((item) => item *2) doubledArray // [2,4,6]
//함수를 반환하는 고차 함수의 예 const add = function (a) { //a가 존재하는 클로저를 생성 return function(b) { //b를 인수로 받아 두 합을 반환하는 또 다른 함수를 생성 return a + b } } add(1)(3) //4
고차 함수형 컴포넌트를 만들면 컴포넌트 내부에서 공통으로 관리되는 로직을 분리해 관리할 수 있어 효율적으로 리팩토링 할 수 있다.
** 질문
실제 고차함수 사용 예시
*** 함수를 만들 때 주의해야 할 사항
1) 함수의 부수 효과 최대한 억제하라
함수의 부수효과 (side effect)란 함수 내의 작동으로 인해 함수가 아닌 함수 외부에 영향을 끼치는 것.
부수효과가 없는 함수를 순수 함수라 하고, 부수 효과가 존재하는 함수를 비순수 함수라고 함.
function PureComponent(props) { const {a, b} = props return <div>{a + b}</div> }
이 컴포넌트는 순수한 함수형 컴포넌트로 분리할 수 있다. 외부에 어떤 영향도 미치지 않고 있고 언제 어디서든 동일한 인수를 받아서 동일한 결과를 반환하기 때문이다.
**항상 순수 함수로만 작성해야 할까?
그렇지 않다.
웹 애플리케이션을 만드는 과정에서 사이드 이펙트는 피할 수 없는 요소이다. 그러나 이러한 부수 효과를 최대한 억제할 수 있는 방향으로 함수를 설계해야 한다. 리액트의 관점에서 본다면 부수 효과를 처리하는 훅인 useEffect의 작동을 최소화 하는 것이 그 일환이라 볼 수 있다.
useEffect의 사용을 최소한으로 줄임으로써 함수의 역할을 좁히고, 버그를 줄이며, 컴포넌트의 안전성을 높일 수 있다.
2) 가능한 한 함수를 작게 만들어라
**아래 예시코드는 단일 책임 원칙에 부합하는가?
예전 솝트 2주차 JS과제 중 일부를 가지고 왔다.
최대한 단일 책임 원칙에 부합하게 짜려고 노력했으나,
아직 스스로 이 원칙에 부합하는지 아닌지 판단하는 능력이 다소 떨어지는 것 같다.
import { eventController } from "../EventController.js"; import { storage } from "../Storage.js"; import { qs } from "../util/domHelper.js"; import View from "./View.js"; export default class MyAccountView extends View { constructor() { super(qs(".all_my_amount")); this.plusAmount = qs(".amount_detail_plus", this.element); this.minusAmount = qs(".amount_detail_minus", this.element); this.totalMyAccount(storage.HISTORY_LIST); this.detailPlusAndMinus(storage.HISTORY_LIST); //이벤트 발행(firstRender함수의 on메서드에서 이벤트 수신) eventController.subscribe("updatedList", (updatedList) => { this.totalMyAccount(updatedList); this.detailPlusAndMinus(updatedList); }); } calculateAccount(items) { let totalIncome = 0; let totalSpend = 0; items.forEach((item) => { if (item.SPEND_OR_INCOME === "income") { totalIncome += item.PRICE; } else if (item.SPEND_OR_INCOME === "spend") { totalSpend += item.PRICE; } }); return { totalIncome, totalSpend }; } totalMyAccount(items) { const { totalIncome, totalSpend } = this.calculateAccount(items); const myAmount = qs(".my_amount"); const p = document.createElement("p"); p.className = "my_amount_sub"; myAmount.innerHTML = ` <p class="my_amount_title">나의 자산</p> <p class="my_amount_sub">${(totalIncome - totalSpend).toLocaleString()}</p> `; } detailPlusAndMinus(items) { const { totalIncome, totalSpend } = this.calculateAccount(items); const plusAccount = qs(".amount_detail_container"); plusAccount.innerHTML = ` <div class="amount_detail_plus_container"> <p class="amount_detail_plus">+</p> <p class="amount_detail_plus">${totalIncome.toLocaleString()}</p> </div> <div class="amount_detail_minus_container"> <p class="amount_detail_minus">-</p> <p class="amount_detail_minus">${totalSpend.toLocaleString()}</p> </div> `; } }
'React' 카테고리의 다른 글
[React] useRef는 왜 써야하는가? (0) 2024.02.25 모던 리액트 Deep dive - 클래스, 클로져 (3) 2024.02.18 Funnel에서의 상태관리 고민 (0) 2024.01.30 왕초보가 작성한 토스 퍼널의 아주 기초적인 사용법 (0) 2024.01.19 리액트에서 .env 사용하기 (카카오 로그인) (0) 2023.11.06