목록전체 글 (293)
가수면
Children.only() .only 함수는 주어진 children이 하나의 React 요소만 포함하고 있을 때 해당 요소를 반환한다. 그렇지 않으면 오류를 발생시킴. children을 하나만 받을 경우에 사용하면 안정성을 높일 수 있으며, 다른 개발자들에게 컴포넌트 사용에 대한 명확한 의도를 전달할 수 있다. 예시) interface InputProps extends HTMLAttributes { label?: ReactNode; children: ReactElement; bottomText?: string; } export function Input({ label, children, bottomText, ...props }: InputProps) { const child = Children.only..
Classic, Inline, Balloon 등 공식 문서에서 제공하는 기본 빌더들이 있다. 해당 패키지를 설치한다. 예) npm install --save @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic 필요하다면 import를 이용해 에디터에 한국어 설정을 적용한다. 이후 간단하게 입력한 값을 확인해보는 로직 import React from "react"; import { CKEditor } from "@ckeditor/ckeditor5-react"; import ClassicEditor from "@ckeditor/ckeditor5-build-classic"; import "@ckeditor/ckeditor5-build-classic/bui..
프로젝트에 적용할 에디터를 선별하는 과정에서 네이버 스마트 에디터를 구현한 것을 정리한다. 초기 로딩이 더 길어지는 것을 방지하기 위해 index.html에 스크립트를 추가해 구현하는 방법 대신 useEffect를 통해 특정 컴포넌트가 마운트될 때만 스크립트를 추가하고 언마운트 시 스크립트를 다시 제거하는 방법으로 구현하였다. import React, { useEffect, useRef } from "react";declare global { interface Window { nhn: any; }}const NaverEditor = () => { const TextRef = useRef(null); const oEditors = useRef({}); useEffect(() => { /..
코드 컨벤션**명명 규칙**1. 컴포넌트 - Pascal Case2. 그 외 파일 - Kebab Case (ex. hook-bookmark.ts)3. const variant - Upper Case4. 변수명, 타입 - Camel Case5. 리액트 훅 - React객체를 사용6. 함수는 화살표 함수 사용7. 컴포넌트 타입은 React.FC**import 순서**1. 외부 라이브러리2. 내부 라이브러리3. 컴포넌트4. asset 등 기타**export**1. 컴포넌트, 커스텀훅만 export default**비동기**1. async / await 사용**컴포넌트 내부 선언 순서**1. 리액트 훅2. 라이브러리 훅3. 커스텀 훅4. 변수 및 상수5. 함수6. useEffect (상태값을 의존성으로 갖는 것..
Sanity에서 sanity에서 graphQL을 사용하려면 엄격한 스키마 지정을 해줘야 함. 예를 들어 아래와 같은 스키마가 있다고 한다면, // schemas/blogPost.js import {defineType} from 'sanity' export default defineType({ name: 'blogPost', title: 'Blog post', type: 'document', fields: [ // ... other fields ... { name: 'sponsor', title: 'Sponsor', type: 'object', fields: [ { name: 'name', title: 'Name', type: 'string' }, { name: 'url', title: 'URL', typ..
Next 설치 1. npm install next@latest react@latest react-dom@latest 2. package.json에 추가 { "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" } } 3. Next.js 방식의 경로 디렉토리 생성 후 파일 옮기기 4. app/layout.tsx 생성 export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } 5. Router, index, App 파일 삭제 Tailwind CSS가 적용되지..
메모이제이션 자체가 연산이 들어가기 때문에 불필요한 메모이제이션은 오히려 프로젝트 성능을 악화시킨다는 것은 모두 알고 있을 것이다. 그렇다면 대체 언제, 어느 시점에, 몇 번의 리렌더링이 일어날 때, 시간 복잡도가 얼마일 때 메모이제이션을 써야 되는 걸까하는 궁금증이 있었는데,그 기준을 실험한 흥미로운 글이 있어서 가져왔다. https://github.com/yeonjuan/dev-blog/blob/master/JavaScript/should-you-really-use-usememo.md?utm_source=substack&utm_medium=email 위 글은 복잡한 시간복잡도를 가진 컴포넌트를 메모이제이션 적용한 것과 적용하지 않은 것 각각 10,000번 렌더링, 리렌더링시켜 해당 컴포넌트의 시간복..
카카오 로그인의 테스트 코드를 작성하던 중 테스트 코드 상의 경로가 제대로 이동되지 않는 문제가 발생했다. 하나씩 클리어해 간 과정과 잊어버리지 않도록 주의해야 할 점들을 기록한다. 1. axios 오류 평범하게 msw를 설치해 axios를 사용할 경우 모듈 외부에서 import 문을 사용할 수 없다며 axios import하는 부분에 오류가 발생하게 된다. Jest는 Node.js 환경에서 사용되는 테스트 프레임워크다. 그러나 애플리케이션이 웹 클라이언트용으로 빌드되고, axios가 버전업이 되면서 CommonJS 대신 ES 모듈로 빌드되도록 변경되었기 때문에 CommonJS 형식으로 작성된 Node.js에서 실행되지 않는 문제가 발생한 것이다. 여러 해결 방법이 있었는데, 나는 axios를 CJS 모..
https://mswjs.io/docs/ Introduction What is Mock Service Worker? mswjs.io 실제 요청을 가로채는 API 목킹 라이브러리 npm install msw --save-dev 기본 세팅 handlers 설정 요청할 api들을 모아 놓은 곳. 원하는 결과를 설정해 넣으면 테스트 시 설정한 대로 요청이 간다. // src\mocks\handlers.ts import { rest } from "msw"; export const handlers = [ rest.get("http://localhost:3030/scoops", (req, res, ctx) => { return res( ctx.json([ { name: "Chocolate", imagePath: "/..
https://www.sanity.io/docs/connect-your-content-to-next-js https://www.sanity.io/docs/js-client#multiple-mutations-in-a-transaction JavaScript Our JavaScript API client library www.sanity.io 그냥 진행하는 방식과 라이브러리 설치해 사용하는 방법이 있는데, 이번 글에선 라이브러리를 이용한 방법을 적는다. npm install @sanity/client 기본 설정 각 키는 아래에서 확인 가능함 (토큰은 생성할 때 확인 가능함) https://www.sanity.io/manage https://www.sanity.io/manage www.sanity.io exp..
Warning: An update to Options inside a test was not wrapped in act .... Warning: Can't perform a React state update on an unmounted component. 위 두 가지 오류의 대부분의 경우는 테스트가 끝난 뒤에 컴포넌트가 바뀌기 때문에 발생하는 오류이다. 예를 들어 초기 화면에 0이 잘 렌더링 되는지를 테스트하는 함수를 작성했다고 해보자. 테스트 함수는 잘 작성되었고 성공적으로 통과되어 언마운트까지 한 상황이다. 그러나 만약 해당 컴포넌트 안에 fetch 등의 비동기 로직이 있는 경우 문제가 발생할 수 있다. 테스트가 종료되어 이미 언마운트가 일어났음에도 불구하고 비동기 작업이 반환되어 컴포넌트를 렌더링 ..
waitFor 비동기에 대한 요청이 전부 처리될 때까지 기다리도록 하는 메소드 function waitFor( callback: () => T | Promise, options?: { container?: HTMLElement timeout?: number interval?: number onTimeout?: (error: Error) => Error mutationObserverOptions?: MutationObserverInit }, ): Promise 예시) 2개의 요청 결과를 기다려야 함 test("스쿱 및 토핑 라우트를 핸들링", async () => { server.resetHandlers( rest.get("http://localhost:3030/scoops", (req, res, ctx)..
fireEvent도 좋지만 공식 문서에서는 user-event를 더 추천. npm install @testing-library/user-event@^14 fireEvent vs user-event fireEvent DOM 이벤트를 디스패치 (컴퓨터 이벤트) user-event 모든 상호작용을 시뮬레이션 (사용자 상호 작용 이벤트) 기본 형태 import 시 구조 분해하지 않고, async / await를 사용해야 한다. import userEvent from '@testing-library/user-event' // inlining test('trigger some awesome feature when clicking the button', async () => { const user = userEven..
screen 쿼리 목록 https://testing-library.com/docs/queries/about/#priority About Queries | Testing Library Overview testing-library.com getByRole의 역할 목록 https://www.w3.org/TR/wai-aria/#role_definitions Accessible Rich Internet Applications (WAI-ARIA) 1.2 A section of a page that consists of a composition that forms an independent part of a document, page, or site. An article is not a navigational lan..
@testing-library/jest-dom을 설치하고 @testing-library/react를 버전 업하길 추천 (이건 필수) npm test 리액트 테스팅 라이브러리과 Jest RTL 테스트를 위한 가상 DOM을 제공 가상 DOM이 원하는 대로 작동하는지 확인할 수 있는 도구를 제공 Jest 테스트 러너. RTL로 작성된 테스트 파일을 찾고 실행하여 테스트를 수행 cra에 포함되어 기본으로 제공 setupTests.js 파일을 사용해 각 테스트 전에 jest-dom을 가져옴 (모든 테스트에서 jest-dom 매처를 사용할 수 있음) Watch mode - 마지막 커밋 이후 변경된 파일과 연관된 테스트만 실행 (모든 테스트 실행도 가능) 실패 조건 - 테스트 함수 실행 시 에러 발생할 때, 단언의 ..
타입스크립트로 마이그레이션 npm install typescript --save-dev yarn add typescript --dev tsconfig.json을 생성하고 기본 값을 추가 (tsc --init) 자바스크립트 파일들을 타입스크립트 파일로 변환 tsc로 잘 적용됐는지 확인해가며 작업 ※ 처음부터 타입을 엄격하게 적용하지 않을 것. any 타입으로 선언 후 any 타입을 더 적절한 타입으로 변경해 나갈 것 tsconfig.json target 컴파일된 자바스크립트 코드가 어떤 ECMAScript(웹 브라우저나 다른 실행 환경에서 동작하는 스크립트) 버전과 호환되어야 하는지를 지정. 항상 최신 버전을 지정하면 좋겠지만 호환되지 않는 브라우저도 있을 수 있기에 최소를 목표로 잡는 게 좋다. noIm..
기본 동작 use client를 사용한 클라이언트 컴포넌트라도 초기 페이지 로드 시에는 서버에서 생성된 html파일을 받아온다. 실제로 개발자 도구에서 받아온 페이지의 요소들을 확인해보면 클라이언트 컴포넌트 안에 있는 요소들도 다 포함이 되어있다. 초기 페이지 로딩 성능을 최적화하려는 Next의 최적화 전략이다. 문제는 이러한 SSR + CSR를 혼합한 방식으로 인해 클라이언트 컴포넌트에 몇 가지 제약이 생긴다는 것이다. 1. 초기 렌더링 시 어떤 요소를 보여줄 건지 결정하는 로직들이 사용 불가능하다. 서버 사이드 렌더링된 컨텐츠와 클라이언트 사이드에서 렌더링하려는 컨텐츠가 다르면 안 된다. 예를 들어 쿠키, 리액트 쿼리의 isLoading 등을 이용해 초기 뷰를 분기 처리하려는 경우 수화 과정에서 받아..
npm i swr 전역 설정 'use client'; import { SWRConfig } from 'swr'; type Props = { children: React.ReactNode; }; export default function SWRConfigContext({ children }: Props) { return ( fetch(url).then((res) => res.json()), }} > {children} ); } 해당 컴포넌트를 provider로 사용하면 아래처럼 간단하게 api요청 함수를 사용할 수 있음 const { data, isLoading, error } = useSWR('/api/me'); mutate의 경우 mutate만 해줄 경우 해당 api 데이터로 요청이 가지만, 아래처럼 ..
이걸 내가 다시 만질 날이 올 줄이야... 기본 세팅 npm i mongodb import { MongoClient, ServerApiVersion } from "mongodb"; const uri = process.env.MOGO_DB_URI ?? ""; const client = new MongoClient(uri, { serverApi: { version: ServerApiVersion.v1,// MongoDB 서버 API 버전 strict: true,// 엄격 모드 deprecationErrors: true,// 오래된 버전이면 에러 뱉을 건지 }, }); 데이터 베이스에 접근 export async function GET() { const mongo = await client.connect();..
'개체 리터럴은 알려진 속성만 지정할 수 있으며 '{ name?: string | null | undefined; email?: string | null | undefined; image?: string | null | undefined; }' 형식에 'username'이(가) 없습니다.' 기존 라이브러리 없는 속성을 지정할 경우 이러한 타입 오류가 발생한다. 이 경우 라이브러리에서 선언된 타입에 속성을 추가해주면 된다. 라이브러리에 선언 된 타입 확인하기 DefaultSession에 usename이라는 타입을 추가해주면 된다. 추가하기 // src\types\next-auth.d.ts import NextAuth, { DefaultSession } from 'next-auth'; declare modu..