25 Aug 2025
|
typescript
TypeScript에서 {}는 조금 애매한 타입인데,
null과 undefined를 제외한 모든 값을 뜻한다.
let a: {} = 123; // ✅ number 가능
let b: {} = 'hello'; // ✅ string 가능
let c: {} = { x: 1 }; // ✅ object 가능
let d: {} = []; // ✅ array 가능
let e: {} = null; // ❌ 오류
let f: {} = undefined; // ❌ 오류
BFE.dev문제에서 NonNullable<T>를 직접 구현하는 풀이가 있었는데,
정답은 아래와같았다.
type MyNonNullable<T> = T & {};
유니언 타입에서 & {}를 교차시키면,
null과 undefined만 걸러지고 나머지는 그대로 유지된다.
type Ex = string | null | undefined;
type Result = Ex & {};
// = (string & {}) | (null & {}) | (undefined & {})
// = string | never | never
// = string
즉 T가 유니언일 때, 각각을 {}와 교차시켜 계산하여 null/undefined를 걸러낸다.
(유니언은 반복문의 효과를 가져옴)
22 Aug 2025
|
wil
이번 주는 회사에 출근하지 않고 재택으로 일했다. 개발팀장님이 출근할 때는 맞춰야 하지만, 크롤링 작업은 집에서 집중하는 것이 더 효율적이라고 판단했다.
크롤링 자동화를 위해 Electron, BrightData, Playwright로 개발을 시도했으나 실패했다. 시간 압박 속에서 조급하게 접근한 것이 원인이었던 것 같다. 다행히 동료의 코드로 수동 크롤링을 이어갈 수 있었다. 실패 과정에서 얻은 것도 있었다. 페이지 로딩 문제는 크롬 디버그 모드와 user-agent 설정으로 해결할 수 있다는 점을 알게 되었다. 다만 셀렉터 변동성이 많아 완전 자동화까지는 아직 어렵다고 느꼈다.
학습 측면에서는 패턴으로 익히고 설계로 완성하는 리액트를 읽기 시작했다. TDD의 레드-그린-리팩터 주기를 배우고, ACL(오류 방지 계층) 개념도 접했다. 회사에서 사용하던 services 구조가 바로 ACL의 일종임을 깨달았다. 데이터 변환을 한 곳에서만 처리해 뷰를 단순하게 유지한다는 점이 인상적이었다.
또, CS50 강의를 듣기 시작했다. 전구의 on/off를 1과 0으로 표현하는 이진수 개념을 배우고, 각 자리수가 2의 거듭제곱을 나타낸다는 것도 이해했다. 강의는 아직 초반이지만 강사의 열정 덕분에 흥미롭게 보고 있다.
추가로 BFE.dev에서 타입스크립트 문제를 하나씩 다시 풀고 있다.
한 주를 몰아 적다 보니 글이 길어지고 일기처럼 흘러간다. 하지만 지금은 배운 것을 기록하는 습관을 만드는 것이 더 중요하다고 생각한다. 언젠가는 짧고 단정한 기록으로 다듬어낼 수 있을 거라 믿는다.
22 Aug 2025
|
wil
하루는 금방 지나가고, 매일 무언가를 배우지만 금세 흘러가 버린다.
예전에 TIL을 썼을 땐 그 순간의 기록이 쌓이는 게 즐거웠다. 하지만 시간이 지나면서 어느새 숙제처럼 느껴지고, 결국 깃 잔디만 채우는 일로 변해버렸다. 기록의 의미가 흐려진 순간이었다.
요즘은 재택을 주로 하면서 출퇴근에 쓰던 시간을 아끼고 있다. 하지만 돌이켜보면 그 시간조차 온전히 잠으로만 흘려보내고 있었다. 편안하긴 했지만, 어딘가 아쉽다는 생각이 들었다.
그래서 다시 기록을 시작해 보기로 했다. 다만 이번에는 하루가 아니라 한 주 단위로.
억지로 모든 걸 남기려 하지 않을 거다. 그냥 내키는 대로 적고 싶은 만큼만 적을 거다. 살아보니 그게 나한테는 더 오래가는 방식이었다.
이 Weekly I Learned에서는 이번 주에 새로 알게 된 개념과 배운 내용, 회사에서의 업무 경험, 그리고 그 밖의 배움을 얻은 순간들을 함께 기록해둘 거다.
기록은 언젠가 되돌아보았을 때 내 발자취가 되어줄 거라 믿는다.
21 Aug 2025
|
typescript
BFE.dev 사이트의 타입스크립트 챌린지를 풀면서 새롭게 알게 된 개념들을 정리합니다.
TypeScript 조건부 타입에서 중요한 규칙 중 하나는
조건부 타입이 유니언 타입에 대해 자동으로 분배(distribute) 된다는 점이다.
📌 기본 형태
여기서 T가 유니언 타입 (A | B | C)이라면,
조건부 타입은 각 멤버별로 나눠서 평가된다.
즉:
(A | B | C) extends U ? X : Y
는 다음처럼 분배된다.
(A extends U ? X : Y) |
(B extends U ? X : Y) |
(C extends U ? X : Y)
📌 분배를 막는 방법
분배가 항상 원하는 동작은 아닐것이다.
만약 T 전체가 E에 속하는지를 한 번에 체크하고 싶다면,
[T]처럼 튜플로 감싸주면 분배가 일어나지 않는다.
type NoDistribute<T, E> = [T] extends [E] ? never : T
✅ 정리
-
조건부 타입에서 T가 유니언이면 멤버별로 분배된다. (반복문처럼 각 멤버를 순회하면서 조건을 적용한다)
-
이를 분배 조건부 타입(Distributive Conditional Types) 이라고 한다.
-
분배를 원하지 않을 때는 [T] extends [U]로 튜플 감싸기를 활용한다.
-
Exclude, Extract, NonNullable 등 여러 유틸리티 타입이 이 규칙을 기반으로 한다.
05 Aug 2025
|
memo
매번 설정할 때마다 GPT한테 물어보는 게 귀찮아서, 이번에 아예 정리해두기로 했다.
Cursor(또는 VSCode 기반 에디터)에서 Prettier가 포맷터로 적용되지 않을 때 아래 순서대로 설정하면 된다.
✍️ 설정 방법
-
Ctrl + Shift + P (Cmd + Shift + P on macOS) 누르기
→ Preferences: Open Settings (UI) 입력 후 선택
-
상단 검색창에 default formatter 입력
-
Editor: Default Formatter 항목 선택
→ 기본값이 None이라면, 드롭다운에서
Prettier - Code formatter 또는 esbenp.prettier-vscode 선택
✅ 설정 완료 후
이제부터는 파일을 저장할 때 자동으로 Prettier 규칙에 맞게 포맷팅된다.
줄 정렬, 들여쓰기, 세미콜론 처리 등 깔끔하게 자동 적용된다.
💡 참고
추가로 아래 설정을 해두면 더 편리하다:
// .vscode/settings.json 또는 User Settings
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}