분류 전체보기
제네릭 | 한 입 크기로 잘라먹는 타입스크립트
제네릭이란? 종합 병원은 영어로 제네릭 호스피탈이라고 말한다. 그래서 제네릭 함수라함은 모든 타입에 두루두루 사용할 수 있는 범용적인 함수를 의미한다. 함수 계의 종합 병원이랄까...이 개념이 제네릭을 이해하는데 제일 도움이 되는 것 같다. 제네릭을 사용한 경우, 해당 함수를 호출할 때마다 타입이 결정된다. 기본 예시 function func(value: T): T { return value; } let num = func(10); // number 타입 매개변수 타입이 다른 경우 function swap(a: T, b: U) { return [b, a]; } const [a, b] = swap("1", 2); 데이터 배열을 받아오는 경우 function returnFirstValue(data: T[])..
TypeError: Cannot read properties of undefined (reading 'length') 의 원인과 해결 방안
TypeError: Cannot read properties of undefined (reading 'length') 에러는 typescript를 사용한다면 무조건 봤을 에러메세지이다. 원인이 무엇일까? 여러가지 이유가 있을 수 있지만 거의 대부분은 string이나 array의 길이 속성을 참조하기 때문에 발생하는 것이다. 예를 들어, string 인수를 사용하는 함수가 하나 있다고 해보자. 그 함수를 호출했을 때 해당 string 인수 값이 없다면 이 에러를 보게 될 것이다. 위 화면을 보면, zustand에서 magazineStore를 만들어 놓고 sorting이라는 값을 담아서 사용하고 있다. 하지만 RegionResult 컴포넌트를 사용하는 순간에는 magazineStore에서 sorting을 u..
AbortController in UseEffect | UseEffect 내부에서 비동기함수 실행 할 때
요즘 웹 개발에서 api를 패치하는 비동기 작동을 다루는 것은 흔한 일이고 나도 프로젝트에 당연하게 사용하고 있다. 그런데, 이 행위는 생각보다 오래 걸리고 예기치 못한 이슈를 발생시키면서 불필요한 메모리를 잡아먹기도 한다. 이때 필요한 것이 바로 자바스크립트의 기능 중 하나인 AbortController이다. 특히 React의 useEffect 훅과 사용할 때 굉장히 유용하다. AbortController란? abort는 '중단하다'라는 뜻으로, 이전 요청을 취소하는 취소하는 역할을 한다. AbortController을 fetch할 때 사용할 때의 장점 1. 효율적인 리소스 관리 한 api가 완료되는데 오래 걸릴때, 그 요청을 취소함으로써 불필요한 메모리 소비를 막을 수 있다. 2. 빠른 유저 경험 만..
React-query를 이용한 무한 스크롤 구현 with react-intersection-observer
드디어 기획자님이 꼭 원하시던 무한 스크롤 구현을 끝냈다. 후기를 먼저 말하자면, 역시 강의를 보는 것과 직접 하는 것은 큰 차이가 있다. 제로초님의 next.14 강의중 react-query를 이용한 무한스크롤 구현을 봤을 때는 굉장히 쉽고 간단하게 느껴졌다. 그래서 직접 무한스크롤을 구현하려다 애를 먹고 있던 중 라이브러리를 사용하게 되었다. 하지만 강의 프로젝트의 세팅과 내 프로젝트의 세팅은 몇가지 차이가 있었다. 1. 강의는 app router를 사용하지만, 나는 pages router를 사용한다. 2. 강의의 무한 스크롤용 데이터는 쿼리로 cursor=number를 받아 몇 개씩 받아올지 넘기지만, 내 백엔드 api의 url은 쿼리로 base=number&limit=number 즉, base~l..
요즘 Redux 대신 React-Query(tanstack-query)가 대세인 이유
요즘 프로젝트에 무한스크롤을 구현하던 중이다. 이 프로젝트는 블로그 형식에 현재 상태관리로는 zustand를 사용하고 있으며 실제 출시(?)를 염두에 두고 있다. 그래서 나중에 트래픽이 많아질 것을 염려해 무한스크롤에 라이브러리를 쓰지않고 직접 구현하려고 시도했다. 하지만 실패했고, react-query를 궁금하던 찰라에 react-query의 InfiniteQuery를 무한스크롤에 많이 사용하기에 한번 조사해보았다. 도데체 왜 요즘에 react-query라는 말이 자주, 그리고 당연하게 들릴까? 1. redux는 컴포넌트간에 데이터를 공유하는 것이다. - 캐싱이 안됨 2. react-query는 서버 데이터를 가져오는 것이다. 1) 캐싱을 잘 해준다. -> 트래픽관리 -> 비용 감소 - 캐싱을 해놓고 ..
서로소 유니온 타입 | 한 입 크기로 잘라먹는 타입스크립트
서로소 유니온 타입 - 아래 코드에서, tag 프로퍼티는 리터럴 타입이기 때문에 중복될 수 없다 -> 구별용으로 굿 (지금은 엎어졌지만 예전에 높은 연차를 가지신 개발자분들과 프로젝트를 했을 때, 이 타입의 코드를 많이 본 기억이 있다. 그만큼 유용하게 쓸 수 있는 타입 방식이 아닐까싶다.) type Admin = { tag: "ADMIN"; name: string; kickCount: number; }; type Member = { tag: "MEMBER"; name: string; point: number; }; type Guest = { tag: "GUEST"; name: string; visitCount: number; }; type User = Admin | Member | Guest; // 방..
타입단언 (value as typeName) | 한 입 크기로 잘라먹는 타입스크립트
타입단언 (value as typeName) - 타입이 확실한 경우에만 사용한다. - 타입스크립트의 눈을 속이는 느낌이랄까.. type Person = { name: string; age: number; }; let person = {} as Person; person.name = ""; person.age = 23; const 단언 let num4 = 10 as const; // 10 Number Literal 타입으로 단언됨 let cat = { name: "야옹이", color: "yellow", } as const; // 모든 프로퍼티가 readonly를 갖도록 단언됨 Non Null 단언 - 이 값이 undefined이거나 null이 아닐것으로 단언하는 것 type Post = { title: ..
리액트 개발 도구 필수 셋팅 추천 | react-dev-tools
나는 리액트, 넥스트를 사용해서 개발하는 프론트엔드 개발자이다. 그래서 리액트 팀에서 리액트 애플리케이션의 원할한 개발을 위해 만든 개발 도구인 react-dev-tools 설치가 필수이다. 그 안에 많은 활용할 수 있는 다양한 기능들이 있지만 필수로 사용해야 하는 몇 가지만 적어본다. (안사용하면 바부..) 우선, react-dev-tools을 내 크롬에 확장한다. [설치 링크] https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ko (미리보기가 안뜨넹..) 두번째, 개발자 도구를 연다. (F12 다들아시져?) 세번째, Profiler를 찾는다. 네번째, 오른쪽에서 검정색 톱니..
소마 15기 지원 1차 코딩테스트 결과
3솔일 것이라고 예상했습니다. 그런데 아니였나봅니다.. ㅜㅜ 오전 11시 정각에 날라온 불합격 문자를 받고 씁쓸하지만 다음을 기약하면서.. 취준하라는 계시인가봐요 ㅠ.,ㅠ 붙으신 분들 파이팅하세요🏋️♂️
Typescript를 사용해본 프론트엔드 개발자가 다시 Typescript 강의를 듣는 이유
제일 공들인 최근 프로젝트를 시작할 때 타입스크립트를 사용하기로 했었다. 요즘은 타입스크립트가 필수라고하기도하고 타입스크립트를 적용한 프로젝트를 해보고 싶기도 했다. 그래서 문법만 빠르게 달달 외워서 프로젝트에 도입했다. 초반에는 타입스크립트 ebook을 구매해서 살펴보는 등 적극적으로 관심을 가졌지만 너무 어려운 책을 선택한 탓인지 어느샌가 그냥 내 ebook 책장에 담겨만 있었다. 더 변명을 하자면, 생각보다 개발하는데 더 기간이 걸려서 mvp 완성시키는데 급급했고, 그 결과 타입스크립트의 기능들을 제대로 활용하지도 못했고 오히려 타입스크립트가 지적해주는 여러가지 오류들을 해결하느라 any를 남발하거나 배포 테스트를 할 때에는 너무 타입스크립트관련 오류가 많이 나서 배포시 타입스크립트 적용 옵션을 끄..
티스토리 hELLO 스킨 + overstackflow-dark highlight 스킨 적용기 | 라이트 모드일 때 바뀌는 폰트 컬러 수정
[hELLO스킨에서 글쓰기나 관리자페이지로 가려면 "Q"를 누르면 쉽게 갈 수 있다.] 구글링 할 때마다 자주 보이는 hELLO 티스토리 스킨이 탐나 나도 적용시켜 보았다. 스킨이 바꼈기 때문에 코드블럭 highlight를 다시 커스텀 해주어야했다. 이번에는 overstackflow-dark가 예뻐보여서 구글링해서 따라 적용했다. 그런데 문제가 생겼다. 아래를 보고 overstackflow-dark를 고른건데 구글링을 통해 적용한 내 블로그에는... 아래처럼 보라색으로 뜨는 것이다. 확인해보니 다크 모드를 누르면 내가 원했던 위의 코드 highlight가 나왔다. 라이트 모드에서 색상이 바뀌는 것을 확인하고 귀찮지만 개발자도구를 열었다. 여기서 프론트엔드 개발자의 면모가... 발휘되나,,,? 위의 보라색..
타입스크립트의 기본 중, 잘 몰랐던 부분 정리 | 한 입 크기로 잘라먹는 타입스크립트
1. 다차원 배열의 타입 정의 let doubleArr: number[][] = [ [1, 2, 3], [1, 2], ]; 2. 튜플 - 배열의 길이와 타입을 바꿀 수 없다. - 결국 배열이다. let tup: [number, number] = [1, 2]; // 튜플 사용예시 const users: [string, number][] = [ ["이정환", 1], ["이아무개", 2], ["김아무개", 3], ["박아무개", 4], [5, "조아무개"], // 오류 발생 ]; 3. 옵셔널 프로퍼티(?)와 readonly 프로퍼티 let user: { id?: number; readonly name: string; // name은 값 수정 불가 } = { id: 1, name: "이정환", }; user.n..
타입스크립트의 컴파일 과정 | 간단 예시
타입스크립트란? - 자바스크립트를 더 안전하게 사용할 수 있도록 "타입 관련 기능들을 추가한" 언어 타입스크립트는 어떻게 실행될까? 컴파일 과정 여기서 컴파일이란 프로그래밍 언어(소스코드)를 기게어 혹은 기계어와 유사한 low level까지 해석하는 과정을 말한다. => TS -> AST -> Type Checking -> JS -> AST -> Byte Code 용어 정의 AST - 프로그래밍 언어로 작성된 소스 코드의 추상 구문 구조의 트리인데, 보면 엄청 긴 코드이다. 봐도 잘 모른다... Byte Code -가상머신이 이해할 수 있는 중간 레벨로 컴파일 한 코드 (JavaScript에서 가상머신은 브라우저와 node에서 사용되는 V8) 이 정도는 알고 타입스크립트를 써야할 것 같다.
타입스크립트 컴파일러 옵션 설명
현재 next + typescript 프로젝트를 벌써 몇 달째 진행하면서 타입스크립트에 대해 조금만 더 제대로 알고 싶다는 생각에 좀 아쉬워서 -한 입 크기로 잘라먹는 타입스크립트- 강의 (인프런)을 수강중이다. 타입스크립트 컴파일러 옵션 설명 타입스크립트를 설치하면 자동으로 설정이 되다보니 따로 볼 생각을 못했었다. 하지만 당연하다고 여겼던 것들이 다 tsconfig파일에서 컴파일러 옵션으로 지정되어있었기 덕분이였다. 아래 코드에 따른 설명으로, 어떤 옵션으로 인해서 타입스크립트에서 자바스크립트로 자연스럽게 컴파일되는지 알 수 있다. /tsconfig.json { // 컴파일할 때 사용하는 것들 "compilerOptions": { // ESNext: 최신 문법, (에전 문법을 사용해야만 돌아가는 환경..
router.query.id is string | string[] | undefined. type error 해결
router.query.id is string | string[] | undefined. 에러를 해결하려면 간단하다. 나는 router.query.id 을 string으로 사용하고 싶었기 때문에 아래처럼 문자열로 만들어버렸다. const magazineId = router.query.id?.toString();