turin's blog

만들고, 터지고, 기록합니다

풀스택, Flutter, 서버 운영, SEO, 배포 삽질을 실제 프로젝트 기준으로 정리합니다. 검색해서 들어온 사람이 바로 쓸 수 있는 체크리스트와 명령을 남기는 게 목표입니다.

1175published
8topics
kopractical notes

자주 다루는 주제

주제별로 빠르게 훑어보기

웹 개발350Next.js283서버 운영165Docker110API80TypeScript58DB50Flutter39

전체 글

운영 중 부딪힌 문제를 검색 의도에 맞춰 정리

웹 개발

cron 작업 시간이 9시간 어긋나는 이유

cron은 서버 시스템 timezone을 그대로 따르기 때문에, UTC로 세팅된 서버에서 한국 시각 기준으로 스케줄링하면 반드시 어긋난다.

·1분 읽기
웹 개발1분 읽기

저장 버튼을 두 번 누르지 못하게 막는 가장 간단한 방법

폼 제출 중에 버튼을 비활성화하는 것만으로 중복 요청을 막을 수 있다. isSubmitting 상태 하나면 충분하다.

계속 읽기 →
Next.js1분 읽기

Next.js에서 한글 slug를 쓸 때 URL 복사가 깨지는 이유

한글 slug는 브라우저 주소창에서는 읽기 편하지만, 복사하면 퍼센트 인코딩된 긴 문자열이 된다. canonical URL도 같은 문제가 생긴다.

계속 읽기 →
Docker1분 읽기

Docker Compose 서비스 이름을 명확하게 짓는 이유

Compose 서비스 이름은 컨테이너 간 호스트명이 된다. 이름이 모호하면 같은 compose 파일 안에서도 연결이 헷갈린다.

계속 읽기 →
DB1분 읽기

Prisma schema를 수정한 뒤 빠뜨리기 쉬운 단계들

schema.prisma를 고치고 나서 validate → migrate → generate 순서를 지키지 않으면 런타임에서 예상 못한 에러가 난다.

계속 읽기 →
CI/CD1분 읽기

GitHub Actions 실패 로그를 읽는 순서

Actions 워크플로가 실패하면 웹 UI보다 gh CLI로 보는 게 빠르다. 어느 step에서 어떤 출력이 나왔는지 한 번에 확인할 수 있다.

계속 읽기 →
웹 개발1분 읽기

블로그 글 목록에 날짜를 넣기로 한 이유

날짜 하나가 글 목록에 주는 정보량은 생각보다 크다. 언제 쓴 글인지 알면 읽을지 말지 판단이 빨라진다.

계속 읽기 →
API1분 읽기

API 응답 필드명을 프론트 기준으로 맞추면 달라지는 것

백엔드 DB 컬럼명을 그대로 내려보내는 대신 프론트가 쓰기 편한 이름으로 설계하면 변환 코드가 사라진다.

계속 읽기 →
TypeScript1분 읽기

TypeScript 타입 에러를 any로 덮지 않는 습관

타입 에러가 나면 any로 조용히 덮고 싶은 충동이 생기지만, 그 자리에 정확한 타입을 넣는 게 결국 더 빠르다.

계속 읽기 →
Git1분 읽기

git stash에 메시지를 붙여야 하는 이유

메시지 없는 stash는 나중에 꺼낼 때 뭔지 알 수 없다. 짧은 메모 하나가 복구 시간을 크게 줄여준다.

계속 읽기 →
서버 운영1분 읽기

개인 서버를 업데이트하기 전에 확인하는 것들

apt upgrade 전에 디스크, 실행 중인 프로세스, 최근 로그를 먼저 훑으면 업데이트 후 문제가 생겼을 때 원인을 훨씬 빠르게 잡을 수 있다.

계속 읽기 →
서버 운영1분 읽기

Nginx 설정을 고치기 전에 백업 파일을 남기는 이유

nginx.conf나 sites-available 파일을 수정하기 전에 백업을 남기면, 실수했을 때 복원까지 30초면 끝난다.

계속 읽기 →
Docker2분 읽기

Docker 로그의 마지막 줄만 보면 놓치는 것들

컨테이너가 재시작 루프에 빠졌을 때 최신 로그만 보면 원인을 찾기 어렵다. 로그를 어떻게 읽어야 하는지 정리했다.

계속 읽기 →
Next.js1분 읽기

React 컴포넌트 이름을 대충 지으면 생기는 일

Button, Card, Modal처럼 범용적인 이름은 나중에 뭘 수정해야 하는지 찾기 어렵게 만든다. 이름 하나가 유지보수 속도를 바꾼다.

계속 읽기 →
Next.js1분 읽기

Next.js App Router에서 페이지별 title을 관리하는 방법

App Router의 Metadata API를 써서 전체 사이트 타이틀 템플릿과 페이지별 타이틀을 깔끔하게 분리한 방법을 정리했다.

계속 읽기 →
웹 개발2분 읽기

작은 프로젝트에서 테스트를 어디까지 짜야 하는가

혼자 만드는 프로젝트에서 테스트 커버리지 100%는 현실적이지 않다. 어디에 먼저 써야 효과가 있는지 기준을 잡은 방법을 정리했다.

계속 읽기 →
Next.js1분 읽기

Markdown 코드 블럭이 깨졌을 때 배운 것

블로그 글의 코드 블럭이 배포 환경에서만 이상하게 렌더링됐다. 원인은 remark 플러그인 순서였다.

계속 읽기 →
웹 개발1분 읽기

관리자 페이지와 공개 페이지를 처음부터 분리한 이유

같은 Next.js 앱 안에 관리자 라우트를 넣었다가 인증 미들웨어가 꼬이는 걸 겪고 나서, 아예 라우트 구조를 나눴다.

계속 읽기 →
Docker1분 읽기

Docker Compose의 env_file과 environment, 뭐가 다른가

두 방식 모두 컨테이너에 환경 변수를 주입하지만 우선순위와 보안 동작이 다르다. 혼용할 때 어떤 값이 이기는지 정리했다.

계속 읽기 →
웹 개발1분 읽기

배포 직후에 내가 꼭 확인하는 것들

빌드 성공이 곧 배포 성공은 아니다. 배포 후 5분 안에 체크하는 내 루틴을 정리했다.

계속 읽기 →
TypeScript2분 읽기

TypeScript 타입을 과하게 만들었을 때 겪은 것들

조건부 타입과 mapped type을 남발했다가 빌드 시간이 늘고 팀원 코드 읽기도 힘들어진 경험을 정리했다.

계속 읽기 →
Next.js1분 읽기

개인 도메인을 바꿀 때 SEO에서 놓치기 쉬운 것들

도메인을 이전하면 기술적인 301 리다이렉트 외에도 검색 엔진 입장에서 꼼꼼히 챙겨야 할 것들이 생각보다 많다.

계속 읽기 →
서버 운영1분 읽기

Nginx access 로그로 요청이 실제로 오는지 확인하는 방법

배포 후 응답이 이상하거나 트래픽이 예상대로 오는지 모를 때 Nginx access 로그를 실시간으로 보면 빠르게 파악할 수 있다.

계속 읽기 →
UX2분 읽기

loading 상태를 대충 구현하면 생기는 UX 문제들

스피너 하나 올려두는 게 전부라고 생각했다가, 버튼 중복 클릭과 레이아웃 시프트로 사용자 불만이 쌓였다.

계속 읽기 →