작게 만들고, 깊게 이해합니다.
시간대, 데이터, 복원. 개인 앱을 만들며 알아두면 좋은 개발의 기본.
주제별 기록32
마감이 있는 AI 에이전트 대회, 무엇을 먼저 준비해야 할까: AI TOP 100 예선 후기
10월 31일 카카오 AI TOP 100 예선에서 다섯 시간 안에 AI 에이전트를 만들어 마감 직전에 제출했다. 문제 내용은 빼고, AI 둘과 나눈 역할과 잘 된 것, 마지막 배포 뒤에 온 자료와 크레딧, 실제 채널 시험에서 배운 것, 다음에 바꿀 아홉 가지를 적었다.
검색어 C++를 보냈는데, 서버에는 왜 'C '로 도착할까
검색창에 C++를 넣었는데 서버에서 꺼낸 검색어는 C 뒤에 공백 두 칸이었습니다. 쿼리 문자열의 +는 폼 형식으로 읽는 함수에게만 공백이고, encodeURIComponent·decodeURIComponent 같은 퍼센트 인코딩 함수에게는 그냥 +이기 때문입니다. Node.js v24.21.0과 Python 3.9.6에서 실제로 실행한 결과로, 쓰는 함수와 읽는 함수를 어떻게 짝지어야 +와 공백이 그대로 돌아오는지 확인합니다.
node로 .ts 파일을 바로 돌리면, 타입 검사는 누가 해 줄까
Node.js 24는 node app.ts로 TypeScript 파일을 바로 실행하지만, 타입을 공백으로 지울 뿐 맞는지는 검사하지 않습니다. Node.js v24.21.0에서 타입이 틀린 코드가 1000100을 내고 종료 코드 0으로 끝나는 것, enum과 type 없이 가져온 interface가 SyntaxError를 내는 것, tsconfig.json의 paths 별칭이 적용되지 않는 것을 실제로 실행해 확인하고, 타입 검사를 tsc에 따로 맡기는 설정을 살펴봅니다.
같은 문자열인데 정규식 test()가 한 번은 true, 한 번은 false라면 어디를 볼까
g 플래그가 붙은 정규식 객체는 지난번 검색이 끝난 위치를 lastIndex에 기억합니다. Node.js v24.21.0에서 같은 문자열의 test()가 번갈아 true와 false를 내고 filter()가 행을 빠뜨리는 것을 실행해 보고, 메서드마다 lastIndex를 어떻게 다루는지와 목적별 고치는 방법을 정리합니다.
Cache-Control: no-cache라고 보냈는데 브라우저는 왜 응답을 저장할까
no-cache는 저장을 막지 않고, 서버에 확인 없이 다시 쓰는 일을 막습니다. Chromium 152에서 no-cache, no-store, max-age를 같은 순서로 실행해 서버 로그와 캐시만 읽는 요청으로 차이를 보고, 무엇을 고를지와 fetch의 cache 옵션까지 정리합니다.
SQLite에 FOREIGN KEY를 걸었는데, 없는 고객의 주문이 왜 들어갈까
SQLite의 외래 키 검사는 기본으로 꺼져 있고 연결마다 켜야 합니다. sqlite3 3.54.0, Python 3.12.14, Node.js v24.21.0에서 없는 고객의 주문이 들어가는 경우와 거부되는 경우를 실행해 비교하고, 트랜잭션과 오타 때문에 오류 없이 켜지지 않는 경우, 이미 들어간 행을 찾는 PRAGMA foreign_key_check를 살펴봅니다.
localhost의 포트가 다르면 쿠키도 따로 저장될까
localhost:4371과 localhost:4372에 쿠키 이름이 같은 앱 두 개를 띄우면 한쪽 로그인이 다른 쪽 쿠키를 덮어쓰고, 한쪽에서 로그아웃하면 다른 쪽도 풀립니다. 쿠키는 호스트 이름 단위로 저장되고 포트를 보지 않기 때문입니다. Node.js 서버 두 개를 Chromium 152 기반 브라우저로 열어 남긴 서버 로그로 이를 확인하고, SameSite=Strict와 __Host-로도 나뉘지 않는 이유, 쿠키 이름과 호스트 이름 가운데 무엇으로 나눌지를 정리합니다.
환경변수를 바꾸고 다시 시작했는데, Next.js 화면에는 왜 예전 주소가 나올까
NEXT_PUBLIC_API_BASE를 바꾸고 next start를 다시 했는데 화면은 예전 API 주소를 부릅니다. Next.js 16.4.3에서 A 값으로 빌드하고 B 값으로 시작해 보니, NEXT_PUBLIC_ 변수와 미리 만든 페이지는 빌드 때 값에 머물고 NEXT_PUBLIC_가 없는 서버 변수만 요청 때 값을 읽었습니다. 어떤 값이 빌드 때 굳는지 가려내는 법과 고치는 세 가지 길을 실제 실행 결과로 정리합니다.
파일 이름의 대소문자만 바꾸면 git은 어느 이름을 기억할까
Mac에서 button.js를 Button.js로 바꾸면 git status는 조용하고 커밋할 것도 없다고 합니다. 대소문자를 가리지 않는 APFS에서 git은 core.ignoreCase에 따라 인덱스에 적힌 옛 이름을 계속 쓰기 때문입니다. git 2.54.0에서 실제로 실행한 결과로, 어느 이름이 남아 있는지 확인하고 git mv로 커밋에 넣는 방법을 봅니다. core.ignorecase를 false로 바꾸면 git mv는 멈추고, mv 뒤에 add한 커밋에는 이름이 둘 생깁니다.
복사한 객체를 고쳤는데 원본은 왜 같이 바뀔까
{ ...user }로 만든 복사본의 주소를 고쳤더니 원본 주소까지 바뀌었습니다. 스프레드와 Object.assign은 바깥 객체만 새로 만들고 안쪽 객체와 배열은 원본과 함께 쓰기 때문입니다. Node.js v24.21.0에서 실제로 실행한 결과로, 바꾸는 경로만 새로 만드는 방법과 structuredClone·JSON 왕복이 각각 무엇을 남기고 잃는지 확인합니다.
set -e를 넣었는데 실패한 명령 뒤에도 스크립트는 왜 계속 돌까
set -e는 모든 실패에서 멈추지 않습니다. 파이프라인의 앞쪽 명령, if·&&·||에서 검사로 쓰인 명령과 그 안에서 부른 함수, local v=$(…)처럼 선언과 명령 치환을 한 줄에 쓴 곳에서는 실패 뒤에도 실행이 이어집니다. macOS의 Bash 3.2.57로 실제 실행한 결과와 GNU Bash 매뉴얼로 원인을 확인하고, pipefail·|| return·선언 분리로 고치는 방법을 정리합니다.
Python round(2.5)는 왜 3이 아니라 2일까
Python의 round()는 정확히 가운데인 값을 짝수 쪽으로 보내서 round(2.5)가 2입니다. round(2.675, 2)가 2.67인 것은 또 다른 이유, 2진 float 저장값 때문입니다. Python 3.12.14 실행 결과로 두 원인을 나눠 보고, 금액은 문자열로 만든 Decimal에 ROUND_HALF_UP을 명시하는 방법과 JavaScript Math.round()와의 차이를 정리합니다.
전체 목록31
이 상자에 담긴 글을 제목만 모아 연도별로 놓았습니다.
202629편
- 마감이 있는 AI 에이전트 대회, 무엇을 먼저 준비해야 할까: AI TOP 100 예선 후기AI agents / Contest retrospective
- 검색어 C++를 보냈는데, 서버에는 왜 'C '로 도착할까Web / URL
- node로 .ts 파일을 바로 돌리면, 타입 검사는 누가 해 줄까Node.js / TypeScript
- 같은 문자열인데 정규식 test()가 한 번은 true, 한 번은 false라면 어디를 볼까JavaScript / RegExp
- Cache-Control: no-cache라고 보냈는데 브라우저는 왜 응답을 저장할까Web / HTTP caching
- SQLite에 FOREIGN KEY를 걸었는데, 없는 고객의 주문이 왜 들어갈까SQLite
- localhost의 포트가 다르면 쿠키도 따로 저장될까Web / Cookies
- 환경변수를 바꾸고 다시 시작했는데, Next.js 화면에는 왜 예전 주소가 나올까Web / Next.js
- 파일 이름의 대소문자만 바꾸면 git은 어느 이름을 기억할까Git / CLI
- 복사한 객체를 고쳤는데 원본은 왜 같이 바뀔까Web / JavaScript
- set -e를 넣었는데 실패한 명령 뒤에도 스크립트는 왜 계속 돌까Shell / Bash
- Python round(2.5)는 왜 3이 아니라 2일까Python
- Promise.all이 실패했는데 나머지 요청은 왜 계속 돌까Web / JavaScript
- API에서 받은 주문 번호의 끝자리가 왜 바뀔까Web / JavaScript
- package.json의 ^0.2.3은 왜 0.3.0으로 올라가지 않을까Tools / npm
- Python 함수를 다시 불렀는데 왜 지난번 값이 남아 있을까Python
- forEach 안의 await는 왜 반복문을 멈추지 못할까JavaScript
- 숫자 배열을 sort()했는데 왜 10이 9보다 앞에 올까JavaScript
- gitignore에 적었는데 왜 계속 커밋될까Git
- 보낸 JSON에서 필드가 왜 사라졌을까JavaScript
- fetch는 404를 받았는데 왜 catch로 가지 않을까Web
- Meta Muse, 한국에서 바로 써보기AI Agents
- SQLite 백업, 파일이 생겼다면 이제 복원해 볼 차례SQLite
- 개인 앱의 날짜가 하루 밀릴 때: 저장 시간과 표시 시간 구분하기JavaScript
- 브라우저가 JSON 요청을 막았는데 서버에는 왜 안 보일까Web
- POST로 보냈는데 다음 주소는 왜 GET일까Web
- AI에게 일을 맡겼는데 왜 계속 헛돌까: 하네스·루프·그래프 쉽게 이해하기AI Agents
- 개인 앱의 오류 메시지: 사용자가 다음 행동을 알게 만들기Apps
- 바이브 코딩이 막히는 건 모델이 아니라 지도다AI