본문 바로가기
728x90

전체 글113

Daphne에서 Gunicorn + Uvicorn으로 마이그레이션 후 발생한 WebSocket 무응답 장애 디버깅 배경실시간 대시보드 시스템은 Django Channels를 이용해 WebSocket으로 클라이언트(장비 측 연결)와 웹 대시보드 사용자에게 메시지를 실시간으로 푸시한다. 오랫동안 단일 ASGI 프로세스인 Daphne로 운영해왔는데, 수평 확장을 위해 Gunicorn + Uvicorn 워커 구성(gunicorn -k uvicorn_worker.CustomUvicornWorker -w 4)으로 마이그레이션했다.Gunicorn 자체는 원래 WSGI(동기, "요청 하나 → 응답 하나") 전용 프로세스 매니저라 WebSocket 같은 비동기 프로토콜을 모른다. 그래서 이 구성은 Gunicorn을 워커 프로세스 관리자(마스터)로만 쓰고, 실제 ASGI 요청 처리는 Uvicorn 워커가 담당하는 하이브리드 구조다. .. 2026. 8. 10.
AI 코딩 에이전트 OpenCode 설치 및 사용법 (feat. 오픈소스) 설치환경OS: Windows패키지 설치 관리자: Chocolatey실행환경: 터미널사용할 모델: Opencode Zen 무료모델 및 Ollama 공개 Opensource 모델테스트 해볼 작업: 호스트 경로의 파일 읽고, task에 따른 쓰기 작업 사전작업설치방법1. 패키지 설치 관리자 설치하기일단 먼저 Chocolatey가 없을 경우 아래 방법으로 설치https://chocolatey.org/install Installing ChocolateyChocolatey is software management automation for Windows that wraps installers, executables, zips, and scripts into compiled packages. Chocolatey in.. 2026. 8. 6.
Docker 빌드 시 CRLF(Line Ending) 문제 자동 해결하기 개요Windows 환경에서 작성한 설정 파일이나 쉘 스크립트를 Linux 기반 Docker 이미지에 포함시키다 보면 예상치 못한 오류가 발생하는 경우가 있다.특히 Nginx 설정 파일, Logrotate 설정 파일, Shell Script 등을 Windows에서 수정한 뒤 그대로 이미지에 포함하면 컨테이너 실행 시 오류가 발생하거나 설정 파일을 정상적으로 읽지 못하는 현상이 발생할 수 있다.이번 글에서는 Docker 빌드 과정에서 CRLF(Line Ending)를 자동으로 LF 형식으로 변환하도록 수정한 사례를 정리해본다.증상가장 흔하게 발생하는 증상은 다음과 같다./bin/sh^M: bad interpreter: No such file or directory또는/usr/bin/env: 'bash\r':.. 2026. 7. 27.
[Postgresql] 파티션 테이블에 무중단으로 LIKE 전용 인덱스 생성하기 배경 — 왜 이 방법이 필요한가?*운영 중인 대용량 테이블에 인덱스를 추가하면, 테이블 전체에 ACCESS SHARE LOCK이 걸려 쓰기가 차단됩니다. PostgreSQL은 CONCURRENTLY 옵션으로 이를 우회할 수 있지만, 파티션된 부모 테이블(partitioned table)에는 CONCURRENTLY를 직접 쓸 수 없습니다.CREATE INDEX CONCURRENTLY ON your_parent_table ... → 에러 발생!파티션된 테이블은 CONCURRENTLY를 지원하지 않습니다. (PostgreSQL 공식 제약) 해결책은 자식 파티션 각각에 CONCURRENTLY로 인덱스를 만든 뒤, 부모에 껍데기(invalid) 인덱스를 만들고, 마지막으로 연결하는 것입니다. 참고로 아래와 같은.. 2026. 5. 11.
네트워크에서 Sever 와 Client의 관계 (Initiator & Listener) 정리 서버와 클라이언트를 구분하는 기준네트워크에서 서버(Server) 와 클라이언트(Client) 는연결(Connection)을 누가 먼저 시작(Initiate)했는가에 따라 결정된다. 연결을 시작/요청한 주체는 클라이언트가 되고 반대로 그 연결을 수락/응답하는 대상이 서버가 되는 셈이다. 예를 들어 A와 B가 HTTP 연결을 맺는다고 하자.A가 B에게 연결을 요청했다면 → A는 클라이언트 (Initiator)그 요청을 받는 B는 → 서버 (Listener)이처럼 서버와 클라이언트의 역할은 고정된 것이 아니라, 연결 관계에 따라 유동적으로 바뀐다.즉, A가 항상 클라이언트이고 B가 항상 서버인 것은 아니다.사용자와 브라우저사람(사용자)은 화면을 바라보지만 네트워크 연결을 직접 시작하지 않는다.사용자 관점.. 2025. 9. 26.
나의 Ubuntu가 갑자기 apt-get update를 못한다..? (도커) 우분투 버전이 latest로 설정되어 있어 생으로 빌드를 할 때 마다 버전이 올라가는 구성이었는데 (레거시)어느날 갑자기 패키지들이 설치가 되지 않는 것이었다. 무슨일이지 하고 찾아보다보니 우분투 레파지토리와의 연결이 문제인 것을 알아냈고레파지토리가 장애가 있는지 확인을 먼저 한 뒤DNS를 KT에서 구글 (8.8.8.8) 로 변경해보았다. 하지만 우분투 레파지토리 (https://archive.ubuntu.com/) 는 전혀 문제가 없었고 DNS를 변경했음에도 여전히 문제가 지속되었다.결국 마지막 해결 방법으로 미러서버를 이용한 레파지토리 소스 변경을 시도했고, 이 방법이 해결책이 되었다. 하지만 이 소스를 변경할 때 대부분 Host PC를 기준으로 작성된 글들이 대부분이다 보니, 나와 같이 도커를 사용.. 2025. 9. 8.
AWS에 올려둔 개발용 DB가 알고보니 채굴용으로 쓰이고 있었다고? AWS에 올린 개발용 Postgres DB가 주기적으로 Down되는 현상이 있어 분석했고 결과적으로 DB 컨테이너가 Malware로 부터 감염이 되어 채굴용으로 사용된 것으로 파악이 되었다. 1. DB 컨테이너가 Down 주기적으로 Down 되었던 이유 -> Host OS 혹은 Docker Daemon에서 판단 했을 때 해당 컨테이너의 CPU 점유율 및 메모리 사용량이 상당히 높아 해당 PID를 강제로 kill 했을 것으로 추측된다. 아래는 문제가 되었던 DB 컨테이너의 상태로. CPU 사용률/점유율이 200퍼센트를 넘겼으며 메모리 사용량도 2GiB를 넘기는 수치이다. 아래는 정상적인 DB 컨테이너의 상태로 차이가 극명하다. *signal 9: Killed 라는 로그 메세지가 Out Of Mem.. 2025. 7. 9.
VSCode Remote Explorer 통해 SSH 접근 시 에러 디버깅 Bad permissions. Try removing permissions for user:~~[09:32:45.358] > Bad permissions. Try removing permissions for user: UNKNOWN\\UNKNOWN (~) on file C:/Users/user/.ssh/config.[09:32:45.380] > Bad owner or permissions on C:\\Users\\user/.ssh/config> 프로세스에서 없는 파이프에 쓰려고 했습니다.[09:32:46.645] "install" terminal command done[09:32:46.645] Install terminal quit with output: 프로세스에서 없는 파이프에 쓰려고 했습니다.[09.. 2025. 6. 20.
자주 사용하는 도커 로그 구하는 법 실시간 로그 구하기docker logs -f 컨테이너명 예시:docker logs -f 20b 실시간인데 30분전부터 구하기docker logs -f --since "시간" 컨테이너명 예시:docker logs -f --since "30m" 20b 로그 라인으로 제한docker logs --tail 라인수 컨테이너명 예시:docker logs --tail 2000 20b 정규표현식으로 검색하기 IPdocker logs --tail 라인수 컨테이너명 2>&1 | grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" 예시:docker logs --tail 2000 20b 2>&1 | grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" 숫자docker log.. 2025. 6. 18.
FATAL: remaining connection slots are reserved for roles with the SUPERUSER attribute 에러 디버깅 환경: Django 4.0.5Postgres 16.4 문제:DB 트랜잭션이 요구되는 모든 작업 불가 원인:FATAL: remaining connection slots are reserved for non-replication superuser connections 에러는 PostgreSQL의 최대 연결 수(max_connections)를 초과했을 때 발생하는 에러로 슈퍼유저나 복제(replicaton) 연결을 위한 슬롯을 제외하고, 일반 연결을 모두 소진했을 때 나타나는 경우가 일반적이다. 특히 Django에서 ASGI 서버(Daphne, Uvicorn 등)로 웹소켓 연결을 사용할 때 "FATAL: remaining connection slots are reserved for non-replicatio.. 2025. 6. 17.
윈도우 함수란? 아래와 같은 주문 데이터 셋이 있다고 가정해보자Date Customer Order_ID Amount2025-05-01Alice10152025-05-02Alice10272025-05-03Alice103102025-05-04Bob10442025-05-05Bob1056 우리는 이 데이터 셋에서 5월 1일부터 5월 5일까지 어떤 고객이 어떤 주문 ID를 통해 얼마나 주문했는지 알 수 있다.하지만 이것은 원시 데이터이고 아주 간단하면서도 적은 양이기 때문에 실제로 엄청나게 많은 양의 데이터를 한눈에 보는 것은 어렵다. 해서 조금 더 한눈에 볼 수 있고 의미있는 데이터를 보기 위해서는 각 고객별로 얼마나 주문을 했는지의 집계를 보고 싶을 수 있다. 집계를 내고 보는 방법은 다양하다.오늘은 윈도우 함수라는 것을 사용.. 2025. 5. 20.
그래서 JWT가 뭔데? (Stateless의 장단점과 보완방법) JWT(JSON Web Token)의 이해와 활용JWT는 JSON Web Token로 말 그대로 JSON 객체로 토큰을 주고 받는 토큰 인증 방식이다.이 토큰은 디지털 서명되어 있어 정보의 신뢰성과 무결성을 보장하고 HMAC 알고리즘을 사용한 비밀키나 RSA를 사용한 공개/개인 키 쌍으로 서명될 수 있다고 한다.JWT는 세 부분으로 구성되어 있다.헤더(Header): 토큰 유형(JWT)과 서명 알고리즘페이로드(Payload): 토큰에 포함할 사용자에 대한 정보나 메타데이터, 통칭 클레임서명(Signature): 헤더와 페이로드를 Base64Url로 인코딩한 비밀키이 세 부분은 점(.)으로 구분되어 xxxxx.yyyyy.zzzzz 형태로 표현된다. JWT의 Flow토큰 생성: 클라이언트가 웹에 로그인하면 .. 2025. 4. 8.
728x90