개발 팁
프로젝트와 상관없이 다시 쓸 수 있는 요령을 문제·원인·해법·코드 예시로 짧게 적습니다.
- Django async(웹소켓) 서버 성능 점검 목록 →DB 연결 수명, thread_sensitive, 전달 경로에서 저장 떼기, 채널 용량, 코어 수만큼 프로세스. 부하 때 지연이 튀면 이 다섯 곳부터 본다.
- CRDT(Yjs) 문서는 평평한 키로, 큰 숫자 열은 바이너리 하나로 둔다 →동시에 생길 수 있는 구조는 합쳐지는 단위로 나누고, 통째로 쓰고 잘 안 바뀌는 데이터는 압축해 한 값으로 둔다.
- 헬스체크는 싸게, 뜨는 동안만 촘촘히, 접근 로그에서는 뺀다 →검사 한 번의 비용을 간격으로 나눈 값이 상시 CPU다. 가벼운 도구로 검사하고, start_interval로 뜨는 동안만 촘촘히 보고, 헬스 요청은 접근 로그에서 거른다.
- 같은 상태를 보는 연결은 한 프로세스로 모으고, 휘발성 이벤트는 묶어 보낸다 →스티키 라우팅으로 같은 문서의 연결을 한 프로세스에 모으고, 프로세스 안에서는 메모리로 나눠 주고, 커서처럼 마지막 값만 중요한 이벤트는 모아 보낸다.
- 시험 환경에서는 일부러 느리게 만든 것을 끈다 →비밀번호 해셔는 MD5, Postgres는 tmpfs와 fsync=off, Redis는 저장 끔, 배경 작업 주기는 짧게, YAML은 C 로더. 운영 설정에는 두지 않는다.
- 시험 DB는 마이그레이션해 둔 템플릿에서 복제한다 →워커마다 migrate를 돌리지 않는다. 마이그레이션 해시로 이름 지은 템플릿 DB를 한 번 만들고 CREATE DATABASE … TEMPLATE으로 복제하면 7~9초가 1초 미만이 된다.
- Next.js 공개 값은 빌드에 굽지 말고 실행 환경에서 넘긴다 →NEXT_PUBLIC_*은 번들에 문자열로 박혀 환경마다 이미지를 다시 굽게 만든다. 실행 env를 루트 레이아웃이 window로 넘기면 같은 이미지를 어디서나 쓴다. 빌드는 Turbopack으로.
- SSE 동시 접속 한도는 CPU보다 파일 서술자 한도에서 먼저 막힌다 →스트림 하나가 소켓 하나와 Redis 구독 하나, 서술자 2개를 쓴다. 컨테이너 기본 soft 한도 1024면 약 500명에서 Too many open files가 난다.
- 문서가 닫힐 때 malloc_trim으로 빈 메모리를 OS에 돌려준다 →glibc는 free한 메모리를 바로 OS에 돌려주지 않는다. 큰 객체(문서·방)가 닫힐 때 간격을 두고 malloc_trim(0)을 부르면 RSS 355MB가 229MB로 줄었다.
- 지연에 민감한 프로세스는 CPU 몫 제한 대신 코어를 못박는다 →--cpus 몫 제한은 할당량이 차면 프로세스를 0.1초씩 통째로 멈춘다. 틱 루프 같은 프로세스는 --cpuset-cpus로 코어를 고정하고 taskset으로 자리를 나눈다.
- 시험 하나마다 시간 예산을 두고, 러너가 강제한다 →순수 로직 0.5초, 백엔드 1초, E2E 3초. 넘으면 통과한 시험도 실패로 바꾸고, 예산을 늘리는 대신 로직과 준비를 고친다.
- Django ASGI에서 DB 연결은 풀로 쓰고, 오래 열린 요청은 바로 돌려준다 →ASGI에서는 CONN_MAX_AGE를 올려도 연결이 재사용되지 않는다. psycopg 풀을 켜고, SSE·롱폴링은 DB를 쓴 직후 연결을 풀에 돌려준다.