Frontend/Today I Learned 28

[JS] 프로토타입 Prototype

※ 본 내용은 코어 자바스크립트 (정재남)의 내용을 정리한 글입니다. 앞서 정리한 프로토타입 기반 객체 지향 언어인 JS에 대해 이어서 이야기해보자. 01 프로토타입 개념프로토타입(prototype)은 단어 그 자체처럼 원형, 원조로 생각하면 된다. 상속된다는 느낌보다 대를 잇는 느낌으로 보면 된다. 01-1 Constructor, Instance, Prototype프로토타입을 이해할 때 중요한 개념은 생성자(constructor) 함수, 프로토타입(prototype), 인스턴스(instance)와 `__proto__`이다. '코어 자바스크립트'에서는 아래 삼각형으로 그 관계를 설명하고 있다.  JS의 함수는 본래 prototype 속성을 가지고 있고, new 키워드를 통해 생성된 인스턴스는 `__pro..

[JS] 객체 지향 언어 : 프로토타입 vs. 클래스

인공지능에 대한 관심이 커지면서 파이썬 사용이 늘어났다. 그러면서 많이 들었던 말 중 하나로 '파이썬은 객체 지향 언어'가 있다. 파이썬 외에도 Java, C++ 등도 객체 지향 언어이고, 웹 개발에 많이 쓰이는 JavaScript도 객체 지향 언어이다. 그런데 파이썬, Java, C++과 JS은 완전히 같은 객체 지향 언어는 아니다. 먼저 JS는 프로토타입 기반이고 파이썬, Java, C++은 클래스 기반 객체 지향 언어(Object-Oriented Programming, OOP)이다. 01 객체 지향 프로그래밍 (OOP) vs. 절차 지향 프로그래밍 (Procedural Programming)객체 지향 프로그래밍은 프로그램이 해결해야할 문제를 작은 부분들로 나누고, 각 부분을 데이터(속성)와 그 데이..

[JS] 클로저(closure)

※ 본 내용은 코어 자바스크립트 (정재남)의 내용을 정리한 글입니다. 01 클로저 Closure 클로저는 여러 함수형 프로그래밍 언어에서 등장하는 보편적인 특성이라고 한다. 그 때문인지 여러 책에서 클로저를 다양하게 정의/설명하고 있다. 참고하고 있는 '코어 자바스크립트' 교재에서 다른 클로저의 정의/설명을 소개해주었는데, 한 번 클로저 내용을 다 읽은 후 다시 살펴보니 모두 이해가 되는 글들이었다. 교재에서는 MDN에서 내린 클로저의 정의를 소개했다. A closure is the combination of a function and the lexical environment within which that function was declared. 직접 MDN closures 문서를 확인해보니, 수정되..

[JS] this

※ 본 내용은 코어 자바스크립트 (정재남)의 내용을 정리한 글입니다. JS를 공부하다보면 많이들 혼란스러워하는 개념 중 하나로 `this`가 있다. this는 상황에 따라 가리키는 대상이 달라져 매우 혼란스럽기 때문이다. 이에 대해서 정리해보려고 한다. 01 상황에 따라 달라지는 this실행 컨텍스트가 생성될 때 VariableEnvironment와 LexicalEnvironment가 생성되며 하나의 일을 더 한다. 그것이 바로 thisBinding이다. this가 가리키는 대상을 결정해준다. this는 함수를 호출할 때 결정된다. 함수를 어떤 방식으로 호출하냐에 따라 값이 달라진다. 01-1 전역 공간에서의 this전역 공간에서 this는 전역 객체를 가리킨다. 즉 브라우저에서 실행하면 window, ..

[Next.js] Zustand 사용하기

Zustand 공식 문서를 확인하면 Next.js와 같이 사용하는 방법에 대해 별도로 안내하고 있다. 이를 확인하면 React의 Context API와 함께 사용하라고 하는데, 그 이유가 무엇일까? 이에 대해 정리한 후, 실제 사용방법에 대해 정리하려고 한다. 1. Next.js의 SSR과 zustand storeNext.js는 서버와 클라이언트 측에서 모두 실행되므로, 전역 변수의 동작이 zustand의 가정과 다르다. 즉 zustand는 하나의 store에서 모든 상태를 관리하지만, Next.js는 서버와 클라이언트 상태가 분리될 수 있다는 것이다. 그래서 Next.js 서버의 상태를 클라이언트와 공유하기 위해서 별도의 과정이 필요하다. 이때 아래 상황들을 고려해야 한다. 1. Per-request ..

[React] TanStack Query로 custom hook 만들기

한 페이지에 여러 데이터를 불러오게 되면 `useQuery'를 불러오는 데이터 개수만큼 사용해야 한다. 하지만 여러 데이터를 불러올수록 비슷한 코드가 여러 번 작성되고, 가독성도 떨어지는 단점이 생긴다. 이를 방지하기 위해 tanStack Query를 이용해 custom hook을 만들 수 있다. 사용자와 사용자가 등록한 아이 정보가 있다고 가정하겠다. 1. Custom Hook 만들기Custom hook을 만드는 과정은 굉장히 쉽다. 우리가 컴포넌트 내부에서 쓰던 것처럼 사용하면 된다. 예를 들어 supabase 서버에서 로그인 정보를 가져오는 코드를 살펴보자.// Schedule.tsx"use client";import { useChildrenQuery, useUserQuery } from "@/ap..

[CSS] Tailwindcss에 색상 커스터마이징하기

프로젝트를 진행할 때 자주 사용하게 되는 색들이 있다. 그것들을 항상 헥사코드를 찾아서 작성하기에는 너무 힘들다. 따라서 tailwind css에서는 기본으로 주어진 색상처럼 사용할 수 있도록 커스터마이징할 수 있는 기능을 지원한다. 먼저 `tailwind.config.ts` 파일에 들어가보자. 그러면 얼추 아래와 같은 세팅이 작성되어 있다. (나는 create-next-app을 통해 Next.js의 App router를 사용하고 tailwind를 사용한다고 설정했으므로 자동으로 content를 작성해주었다.)import type { Config } from "tailwindcss";const config: Config = { darkMode: ["class"], content: [ "./src..

[Next.js] 버튼 클릭 시 query param 추가하기

쇼핑몰에서 하는 것처럼 검색어나 필터를 입히면 query param이 추가되도록 하고 싶었다. 나중에 query param을 통해 정보를 불러올 것이므로 이 방법을 쓰는 것이 적합할 것 같았다. 그 전에 next의 `usePathname`과 `useSearchParams`에서 필요한 부분만 살펴보고 가려고 한다. `usePathname()`먼저 쿼리 스트링이 입력된 경우 pathname이 어떻게 출력될지 궁금했다.`http://localhost:3000/mypage?myKey=hihi` 이와 같은 경로에서 `usePathname`을 통해서 경로를 가져오면 어떤 값을 줄까? 쿼리 스트링은 모두 제거한 path만 깔끔하게 반환해준다.'use client'import { usePathname } from "n..

[React, TS] Input 이미지 파일 미리보기

프로필 이미지를 수정할 때, 업로드한 이미지가 어떻게 보일지 궁금하다. 따라서 파일을 업로드하면 미리보기를 띄우기로 했다.  그러려면 JS의 `FileReader`가 필요하며, 사용할 메소드는 `readAsDataURL`, `onloadend`와 `result` 이다. `readAsDataURL`은 업로드한 파일은 컨텐츠를 읽어오는 역할을 한다. `onloadend`에는 파일을 읽는 행위가 종료되면 실행할 함수를 입력하면 된다. `onloadend`에 작성 한 함수 내부에 파일 경로 저장하는 내용이 필요한데, 이때 `result`를 통해 `readAsDataURL`의 결과로 URL로 데이터를 불러올 수 있으며, 해당 URL을 imgPath에 저장해 미리보기를 띄워주었다. 이 imgPath를 img 태그의..

[Next.js] Link 태그에 버튼을 넣었을 때 페이지 이동 막기

`` 내부에 많은 것들을 할 수 있지만 그 안에 버튼을 넣어 클릭 이벤트를 넣었을 때는 어떻게 할까? 페이지 이동을 하지 않고 버튼 클릭 이벤트만 실행하고 싶을 때 나는 먼저 `e.stopPropagation()`을 생각했다. ``에 `onClick`을 넣고 하위 ``에도 클릭 이벤트가 있을 때 `e.stopPropagation()`을 사용했기 때문이다. 그런데 이렇게 했더니 이벤트가 너무 중구 난방으로 발생했다. 카드를 ``로 만들고 내부에 아래와 같이 ``을 넣었다. {todo.id.slice(0,4)} {todo.contents} { e.stopPropagation() updateTodo(todo); }} > {todo.isDone ? "취소" : ..