전체 글
-
제외 목록에 NULL 하나 넣었더니 SQL 결과가 사라지는 이유Data Analysis 2026. 10. 5. 00:21
NOT IN 조회가 갑자기 0행이 됐다면 제외 목록에 NULL이 들어왔는지 먼저 확인하세요. NOT EXISTS로 바꿀 때는 후보 ID의 NULL도 어떻게 처리할지 정해야 합니다.후보가 1, 2, 3이고 제외할 ID가 2라면 1, 3을 기대합니다. 그런데 제외 목록이 2, NULL이 되면 다음 쿼리는 아무 행도 남기지 않습니다.WITH candidates(id) AS ( VALUES (1), (2), (3)), excluded(id) AS ( VALUES (2), (NULL::integer))SELECT idFROM candidatesWHERE id NOT IN ( SELECT id FROM excluded)ORDER BY id;아래 결과는 PostgreSQL 18 문서의 규칙으로 도출한 예상입니다..
-
UNIQUE를 걸었는데 빈 값이 여러 개 들어가는 이유Data Analysis 2026. 10. 5. 00:21
별칭 컬럼에 UNIQUE를 걸었는데 별칭 없는 회원이 여러 명 저장됩니다. PostgreSQL의 기본 규칙에서는 정상입니다. 같은 문자열의 중복은 막지만 NULL 두 개를 같은 값으로 비교하지 않기 때문입니다. NULL을 여러 개 허용할지 하나로 제한할지 업무 의미부터 정하고 PostgreSQL의 UNIQUE NULL 처리 방식을 명시하세요.선택 입력인 별칭이라면 아직 정하지 않은 사람이 여럿이어도 괜찮습니다. 반대로 “그룹마다 이름 없는 기본 설정은 하나만 둔다”는 규칙이라면 NULL의 중복까지 막아야 합니다. 필수 입력이 목적이라면 NOT NULL이 필요하고요. 이 세 요구를 같은 “빈 값 금지”로 부르면 다른 제약을 고르게 됩니다.아래 SQL은 PostgreSQL 18 문서에 따른 가상 설계 예시입..
-
SQLite에 외래 키를 썼는데 잘못된 참조가 들어가는 이유Data Analysis 2026. 10. 5. 00:21
SQLite 테이블에 REFERENCES가 있는데 없는 부모 ID도 저장된다면, 쓰기에 사용한 연결에서 PRAGMA foreign_keys;를 조회하세요. 외래 키는 선언과 함께 연결별 활성화 상태를 확인해야 합니다.화면에서는 잘 막히는데 CSV 가져오기에서만 잘못된 값이 들어가는 경우도 같은 순서로 좁힐 수 있습니다. 두 기능이 같은 DB 파일을 사용하더라도 서로 다른 연결을 만들 수 있기 때문입니다.책이 없는 분류를 가리키는 예시분류 10이 있고 각 책에는 분류가 반드시 하나 있어야 한다고 가정하겠습니다. 아래 SQL은 빈 테스트 DB용 설명 예시이며 운영 자료에 실행한 결과가 아닙니다.CREATE TABLE categories ( id INTEGER PRIMARY KEY, name TEXT NO..
-
timestamptz에 저장한 시간대 이름은 어디로 갔을까Data Analysis 2026. 10. 5. 00:20
PostgreSQL의 timestamptz에는 입력한 Asia/Seoul 같은 시간대 이름이 남지 않습니다. 저장되는 것은 한 순간입니다. 원래 선택한 지역까지 다시 보여 줘야 한다면 시간대 이름을 별도 열에 보관하세요.서울 오전 9시를 저장했는데 조회 결과가 자정으로 나오는 것도 같은 이유로 설명할 수 있습니다. 조회 세션의 시간대가 UTC라면 서울 오전 9시에 해당하는 UTC 자정을 보여 줍니다. 값이 아홉 시간 이동했다고 판단하기 전에 입력의 자료형과 세션 설정부터 확인해야 합니다.입력, 저장, 표시가 각각 하는 일timestamp with time zone이라는 이름은 시간대 문자열도 값 안에 함께 들어갈 것처럼 보입니다. PostgreSQL 문서는 입력값을 UTC 기준으로 변환하며, 원래 지정했..
-
웹앱을 배포했는데 열린 탭만 옛날 버전인 이유Programming 2026. 10. 5. 00:20
새 창에서는 바뀐 화면이 뜨는데 오전부터 열어 둔 탭은 그대로라면, 배포 파일부터 다시 올리기 전에 Service Worker의 상태를 보세요. Service Worker의 설치·대기·활성화와 현재 페이지의 controller를 구분하고, 사용자 작업을 보존한 뒤 버전을 전환하세요.Service Worker를 쓰는 웹앱에서는 새 파일의 배포, 새 worker의 설치, 열린 페이지의 전환이 서로 다른 시점에 일어납니다. 새 worker가 waiting에 있다는 것은 설치 후 기존 페이지들이 끝나기를 기다리는 상태일 수 있습니다.아래 메모 앱의 v1·v2는 갱신 흐름을 설명하는 가상 버전입니다. 2026년 9월 28일 확인한 공식 개발 문서에 근거하며, 실제 사용자의 탭이나 저장 자료를 변경하지 않았습니다...
-
오프라인 파일 하나가 404인데 왜 설치 전체가 실패할까Programming 2026. 10. 4. 00:49
서비스 워커를 업데이트했는데 새 버전이 설치되지 않습니다. 내려받을 파일 목록에는 HTML, JavaScript, 그리고 없어도 화면을 쓸 수 있는 안내 이미지가 함께 들어 있습니다. 그 이미지 하나가 404라면 cache.addAll()에 넘긴 전체 목록과 install 이벤트의 Promise 연결부터 확인하세요. 필수 화면과 선택 이미지를 같은 실패 조건으로 묶었을 수 있습니다.404가 설치 실패로 이어지는 경로addAll()은 URL 목록의 응답을 받아 캐시에 넣습니다. 정상 응답이 아닌 항목이 있으면 반환한 Promise가 거부됩니다. 404도 여기에 해당합니다. 이 Promise를 install 이벤트의 waitUntil()에 넘겼다면, 실패가 설치 단계까지 전달됩니다. Cache.addAll(..
-
다른 탭에 변경을 알렸는데 새로 연 탭은 모르는 이유Programming 2026. 10. 4. 00:49
설정 화면 A에서 테마를 바꾸자 열려 있던 B도 어두운 화면으로 바뀝니다. 그런데 그다음에 연 C는 예전 테마를 보여 줍니다. BroadcastChannel에 변경 알림을 보낸 것과 현재 설정을 저장한 것은 서로 다른 작업이기 때문입니다.BroadcastChannel은 참여 중인 탭에 메시지를 전달합니다. 나중에 열린 탭이 이전 알림을 다시 받는 이력 저장소는 제공하지 않습니다. 새 탭은 저장된 현재 상태를 먼저 읽고, 열린 탭은 알림을 받으면 그 상태를 다시 읽게 만드세요. 이 글에서는 서버에 설정을 저장하는 가상 앱으로 그 순서를 따라갑니다. 실제 서비스를 실행한 기록은 아닙니다.A와 B가 맞았는데 C만 틀린 까닭다음 코드는 다른 탭에 신호를 보내는 데는 충분합니다.const channel = ne..
-
탭 두 개가 같은 작업을 동시에 할 때: Web Locks의 범위Programming 2026. 10. 4. 00:49
같은 출처의 협력하는 작업은 Web Locks로 조정하되, 서버·다른 기기까지 잠겼다고 가정하지 마세요.메모 앱을 두 탭에서 열면 두 탭 모두 미전송 메모를 발견할 수 있습니다. 각 탭에 isRunning 변수를 두어도 상대 탭의 상태는 알 수 없습니다. 이럴 때 같은 이름의 Web Lock을 요청하면 한쪽이 작업하는 동안 다른 쪽을 기다리게 할 수 있습니다.다만 기다린 탭이 나중에 오래된 목록을 그대로 보내면 중복 전송은 남습니다. 이 글에서는 잠금을 얻는 코드보다 그 안에서 언제 목록을 읽고, 언제 완료로 처리하는지까지 연결해 보겠습니다. 2026년 9월 28일 확인한 명세를 바탕으로 하며, 코드는 실제 서버에 연결하지 않은 설계 예시입니다.탭 A가 먼저 끝나도 탭 B의 목록은 낡아 있습니다미전송 메..