notes

착하게 살자2023. 7. 12.

  • 중독 회복 12단계 프로그램 중 9단계를 지나면 이후 단계가 매우 수월해진다고.
  • 9단계: (중독으로 인한 것이든 아니든) 자신이 저지른 잘못에 대해 당사자들에게 (해가 되지 않는다는 조건하에) 사과/배상 하기.
  • 왜냐면 그 과정을 통해서 의지력등 인지 자원이 대폭 늘어나기 때문.
  • 반대 방향에서 보자면, 해결되지 않은 부채감/죄책감 등이 실제로 나의 뇌 리소스를 잡아먹는다는 것.
  • 그리고 '아 이거 해야 되는데(못하고 있네)'도 같은 영향을 미친다고(스스로에게 느끼는 부채감).
  • 이 경우 정말로 그것들을 '해버리던지' 아니면 해야 된다는 생각을 버리던지 둘 중 하나를 해서 '할당된 메모리를 해제' 해야 한다고.
  • 그러니까 누군가에게 잘못한 후 사과를 안하고 있는 동안의 '내가 해야 될 것을 안하고 있다는 느낌', 사과를 했을 때 '후련해지는' 느낌이 단지 느낌만은 아닌 것.
  • 도덕적/윤리적으로 사는 것은 보통 '칭찬할 만한 덕목' 같은 것으로 인식되지만 실제로 뇌 기능에 직접적인 영향을 미치는 요소라는 점 역시 대단히 인상적.

Ref

25% Rule2023. 7. 7.

25% Rule?

목표를 세울 때 최종 목표의 25%를 1차 목표로 잡는 것이 좋다고 한다.

How

그러니까 푸쉬업을 하루에 100개(물론 나는 이런 허황된 목표는 세우지 않지만) 하겠다! 가 목표라면,

  1. 당연히 그건 한 번에 될리가 없음.
  2. 그렇다고 하루에 1개는 좀 음... 한 것이 사실임.
  3. 그럼 어떻게 한담?
  4. 25%인 25개를 일단 1차 목표로 잡아보자.
  5. 25개도 힘들면 그것의 25%인 6-7개 정도로 해보자.
  6. 짠! 목표를 이뤘습니다!
  7. 다음 목표로 원래의 25개 혹은 x2 인 12-13개를 잡아보자.
  8. (계속)

Ref.

Case Insensitive Sort2023. 7. 7.

arr.sort((x, y) => x.toLowerCase().localeCompare(y.toLowerCase()))
//                                ^^^^^^^^^^^^^^^ 🤯
arr.sort((x, y) => x.toLowerCase().localeCompare(y.toLowerCase()))
//                                ^^^^^^^^^^^^^^^ 🤯

Fixed Mindset vs. Growth Mindset2023. 7. 3.

Fixed(/Performance) Mindset?

  • 성공/실패가 '자질'에 의해 결정된다는 믿음.
  • '나의 성공은 나의 지능 때문'
  • 내가 실패한다면? 성공할 확률은 사실상 없음.
  • "Talent"
  • 당연히 시도가 적어지고 -> 성공률도 낮아짐

Growth(/Learning) Mindset?

  • 성공/실패가 아니라 이걸로 내가 뭔가를 배우고 성장했는가가 더 중요하다는 믿음.
  • '나의 성공은 경험/노력('노오력'과는 다른)/학습으로 인한 결과'
  • 내가 실패한다면? 경험/학습이 부족했던 것.
  • "Effort"
  • 시도가 많을 수 밖에 없고 -> 성공률도 높아짐

Fixed -> Growth

  • 생각의 흐름/버릇을 바꾸는 건 강줄기를 바꾸는 것과 비슷하다.
  • "조금씩 조금씩"
  • '내가 지금 Fixed 방식으로 생각하고 있다'를 인지하는 것부터 시작하자.
  • 인지했을 때 스스로에게 '통'할만한 phrases를 찾아서 건네보자.
    • '처음부터 완벽하게 잘하는 사람은 없어'
    • '모든 실패는 나를 성공으로 한발짝 더 가깝게 만들지'
    • '이번엔 잘하진 못했지만 그래도 뭔가 배운 건 있지'
    • 등등
  • 중요한 건 그 phrase가 진짜로 내 마음에 '와닿는가', '실제로 그렇다고 생각하는가' 이다.
    • 마음을 '강제로' 바꿀 순 없기 때문.
    • 자신의 마음을 억지로 바꾸려 하는 건 스스로에 대한 폭력임.
  • 이런 경험이 쌓이면? -> 강줄기가 바뀌게 된다.
  • 여기도 꾸준한 명상이 도움이 될 수 밖에 없다.

CSS container queries2023. 6. 30.

tl;dr

container queries illustrated

How to

  1. container query로 "볼" element에 container-type으로 "containment context"를 지정한다.
  2. container-type은 아래와 같은 옵션들이 있다.
    • size: 'containment context로 지정된 element의 "inline", "block" layout 정보를 다 쓰겠다.'
    • inline-size: '"inline" layout 정보만 쓰겠다.'
    • normal: 'layout 정보는 안쓰겠다.'
  3. container-name으로 naming도 할 수 있다. (grid-area랑 비슷한 머시기라고 생각하자.)
  4. 위 둘을 줄여서 container: {name} / {type} 로 쓸 수 있다.
  5. @container {name} ({condition}) { ... }로 스타일을 정의한다.
  6. container queries용 unit도 따로 있다.
    • cqw: containment context element width의 1%
    • cqh: height의 1%
    • cqi: inline size의 1%
    • cqb: block size의 1%
    • cqmin: cqi와 cqb 중 작은 값
    • cqmax: 큰 값

"width랑 inline size랑 같은 거 아니에요?"

writing mode가 vertical일 경우를 생각해보시면...

Refs

비고

Callback Ref2023. 6. 26.

callback refs?

ref는 보통 useRef hook과 함께 쓰지만 ref 에 함수를 넘길 수도 있는데, 요런 패턴을 callback refs 라고 하고, 대부분 DOM node를 액세스 하는 경우에 쓰인다.

How?

놀랍게도 ref엔 함수를 넘길 수 있는데, 요 경우 아래와 같이 node를 arg로 받게 된다.

const ref = (node) => {
  // access the dom node
}
const ref = (node) => {
  // access the dom node
}

사실 useRef가 넘기는 ref 도 걍 아래와 같다.

<div
  ref={(node) => {
    ref.current = node;
  }}
/>
<div
  ref={(node) => {
    ref.current = node;
  }}
/>

But why?

기존의 ref 는 보통 effect 내부에서 마운트가 된 이후에 액세스하게 된다. 근데 해당 dom node에 조건부 렌더가 걸려있다면 동작하지 않는 케이스가 생길 수 있고, node가 다이나믹하게 변경될 수 있는 케이스에 대응이 어렵다거나 등등.

When?

아래와 같은 걸 할 수 있다.

const ref = (node) => {
  node?.focus()
}

// ...

return <input ref={ref} type="text" />
const ref = (node) => {
  node?.focus()
}

// ...

return <input ref={ref} type="text" />

useCallback

근데 위와 같이 하면 매 렌더시마다 포커스가 될 것이므로, 거의 대부분의 경우 useCallback이랑 쓰게 될 것이다.

const ref = useCallback(() => {
  node?.focus()
}, [])
const ref = useCallback(() => {
  node?.focus()
}, [])

Further Readings

next.js에서 route가 변경되었을 경우 이전 route를 죽지 않게 하려면2023. 6. 25.

til이 딱히 til이 아닌 것 같고 github을 cms로 쓰는 것도 좀 번거로운 감이 있어서 걍 .mdx 파일을 작성하는 걸로 하고 route 이름도 notes로 바꾸었는데, 바꾸고 보니 이전 링크를 preserve 해야 되겠다 싶어서 알아보았다. 브로큰 링크를 만들지 않아보겠다! 가 얼마 전에 목표가 되었기 때문에.

하려는 것

  1. (아마도 없을 것 같긴 하지만) 이전 링크를 어딘가 저장해 둔 누군가가 있을 수도 있다.
  2. 그 저장된 링크는 /til/:id 일 것
  3. 바뀐 링크는 /notes/:id 이지만,
  4. 2.의 링크로도 액세스가 가능해야 함

그러니까 redirects 설정을 하면 되는 것인데,

next.config.js

아래와 같이 하면 된다.

/** @type {import('next').NextConfig} */
const nextConfig = {
	// ...
	async redirects() {
		return [
			// ...
			{
				source: "/til/:path*",
				destination: "/notes/:path*",
				permanent: false,
			},
		]
	},
}
/** @type {import('next').NextConfig} */
const nextConfig = {
	// ...
	async redirects() {
		return [
			// ...
			{
				source: "/til/:path*",
				destination: "/notes/:path*",
				permanent: false,
			},
		]
	},
}

대략 "/til/*" 하면 되지 않을까 했는데 역시 아니었고 "foo/:path*" 라구 해야 함. permanent: false인 것에도 유의.

Ref

app router에서 `fetch`를 쓰지 않을 경우 cache 동작2023. 6. 24.

tl;dr

되긴 됨

Detail

fetch를 쓰지 않을 경우 Default Caching Behavior를 따르거나 Segment Cache Configuration를 따르게 됨.

Default Caching Behavior

If the segment is static (default), the output of the request will be cached and revalidated (if configured) alongside the rest of the segment. If the segment is dynamic, the output of the request will not be cached and will be re-fetched on every request when the segment is rendered.

Segment Cache Config

As a temporary solution, until the caching behavior of third-party queries can be configured, you can use segment configuration to customize the cache behavior of the entire segment.

like:

// app/page.tsx

import prisma from './lib/prisma'
 
export const revalidate = 3600 // revalidate every hour
 
async function getPosts() {
  const posts = await prisma.post.findMany()
  return posts
}
 
export default async function Page() {
  const posts = await getPosts()
  // ...
}
// app/page.tsx

import prisma from './lib/prisma'
 
export const revalidate = 3600 // revalidate every hour
 
async function getPosts() {
  const posts = await prisma.post.findMany()
  return posts
}
 
export default async function Page() {
  const posts = await getPosts()
  // ...
}

Ref

Data Fetching without fetch()

Tags