2P by GN⁺ 3시간전 | ★ favorite | 댓글 1개
  • Immich 개발 과정에서 습득한 저주받은 지식 목록 공유임
  • 다양한 소프트웨어 및 인프라 환경에서 발견한 예상치 못한 문제점을 정리함
  • EXIF 메타데이터, YAML 공백 처리, PostgreSQL 등 도구와 언어별 문제점 언급함
  • 일부 문제는 보안, 플랫폼 호환성, 오픈소스 의존성과 직접적으로 연결됨
  • 개발자라면 주의해야 할 실제 사례와 원인에 초점을 맞춤

개요

Immich 개발 팀이 프로젝트를 진행하며 겪은, 다시는 알고 싶지 않은 저주받은 지식을 공개함. 이는 실제 서비스 개발 및 운영 중 여러 도구, 언어, 플랫폼에서 직접 경험한 예상치 못한 함정과 문제를 나열한 목록임.

저주받은 지식 목록

  • 2025년 6월 4일

    • Zitadel의 Actions는 저주받은 기능임
    • Zitadel이 제공하는 커스텀 스크립팅 기능은 JS 엔진 기반이나, 정규식의 네이밍 캡처 그룹을 지원하지 않아 한계가 드러남
  • 2025년 5월 30일

    • Microsoft Entra는 PKCE를 지원하지만, 이를 OpenID discovery 문서에 명시하지 않아
    • 이로 인해 있는 기능이 클라이언트에서 감지되지 않는 문제 발생함
  • 2025년 5월 5일

    • 이미지를 설명하는 EXIF 메타데이터의 크기 정보는 실제 이미지와 다를 수 있음
    • 이 차이로 인해 크롭, 리사이즈 작업에서 오류 발생함
  • 2025년 4월 1일

    • YAML의 공백 처리는 예측과 다르게 동작하는 경우가 많음
    • 포매팅에 민감하여 의도와 다르게 내용이 해석되는 위험성 있음
  • 2024년 9월 20일

    • Windows의 숨김 파일은 "w" 플래그로 열리지 않음
    • SMB의 "hide dot files" 옵션과 조합하면 파일 탐색 및 처리 혼란이 커짐
  • 2024년 8월 7일

    • Bash 스크립트에서 캐리지 리턴(CRLF) 문제 발생 가능성 있음
    • Git이 체크아웃 시 자동으로 LF를 CRLF로 변환하면 스크립트 실행에 오류 유발함
  • 2024년 8월 7일

    • Cloudflare Workers에서의 fetch는 https를 명시해도 기본으로 http가 적용됨
    • 이로 인해 리다이렉션 루프 등 네트워크 관련 문제 야기함
  • 2024년 7월 21일

    • 모바일의 GPS 공유는 앱에 위치 권한 없을 때 GPS 정보가 이미지에서 조용히 제거됨
    • 위치 기반 서비스 정확성, 프라이버시에 영향 있음
  • 2024년 7월 3일

    • PostgreSQL의 NOTIFY는 트랜잭션 내에서만 동작함
    • socket.io의 postgres-adapter와 같이 사용할 경우 5초 주기로 WAL 기록이 발생해 부하 유발함
  • 2024년 7월 3일

    • npm 스크립트 실행 시 마다 npm 레지스트리에 http 요청을 보냄
    • 따라서 헬스 체크를 스크립트로 하면 비효율적
  • 2024년 6월 28일

    • JavaScript 커뮤니티 내 일부 사용자가 "하위호환성" 명분으로 50여개의 패키지 의존성 강제 추가
    • 이 패키지들은 모두 해당 사용자가 관리함
  • 2024년 6월 25일

    • bcrypt 구현체는 문자열 앞 72바이트만 사용함
    • 그 이후 문자는 무시되므로 긴 비밀번호가 무의미해짐
  • 2024년 1월 31일

    • JavaScript Date 객체는 연도와 날짜는 1부터, 월은 0부터 인덱싱함
    • 혼동하기 쉬운 구조임
  • 2024년 1월 9일

    • Node.js v20.8 이전, --experimental-vm-modules 옵션을 사용하는 CommonJS 프로젝트에서 ES 모듈이 다시 CommonJS 모듈 불러올 때
      • segfault(세그폴트)로 Node.js가 크래시되는 문제 발생함
  • 2023년 12월 28일

    • PostgreSQL의 매개변수 제한은 65,535개임
    • 대량 데이터 집합의 벌크 인서트에서 성능상 한계 초래함
  • 2023년 6월 26일

    • Secure Contexts에서만 사용 가능한 웹 API 있음
    • 대표적으로 클립보드 API 등은 https 또는 localhost 환경에서만 작동함
  • 2023년 2월 23일

    • TypeORM의 remove 구현체는 입력값에 직접 영향을 줌
    • 원본 객체 id 속성까지 삭제해버림

결론

이러한 저주받은 지식은 실제 서비스 개발 및 운영 환경에서 빈번히 마주칠 수 있는 함정임. 개발자라면 각 도구, 프로그래밍 언어, 환경 별로 숨어있는 제약과 이슈를 미리 파악함으로써, 효율적인 문제 해결 및 안정적인 서비스 개발에 도움이 됨.

Hacker News 의견
  • 이걸 처음 봤을 때부터 정말 마음에 들었음. 예시 커밋(여기)을 살펴본 뒤 더더욱 마음에 들게 됨. 문제를 해결하기 위한 코드와 함께 ‘저주받은 지식’이 기록되는 점이 특히 좋음. 이런 기능은 모든 프로젝트에 필요하다는 생각이 가장 먼저 듦. 로그가 그저 카타르시스가 아니라, 각종 골치 아픈 문제를 긍정적인 학습 경험으로 전환해줌. 외부에 공개하면, 같은 문제를 겪은 사람들과 공감도 할 수 있고, 앞으로 발생을 예방하는 툴이 될 수도 있음

    • 보통 이런 정보들을 커밋 메시지에 직접 적는 편임. 누군가 코드 한 줄을 보고 "왜 이렇게 대충 짰지? 그냥 ___ 하면 되는 거 아냐?"라고 생각할 때 바로 설명이 있어서 유용함
  • ‘PostgreSQL 플레이스홀더 6만5천 개를 한 쿼리에서 바인딩할 수 없다’는 부분을 보고 놀랐음. 애초에 이건 별로 좋은 생각이 아니어서 오히려 PostgreSQL 쪽을 탓하긴 어려움. 깃허브 이슈 코멘트들을 보니, ORM을 리팩터링해서 큰 쿼리를 여러 개의 작은 쿼리로 나누는 식의 합리적인 접근을 했더라고 함. 개인적으로는 한 쿼리에서 3,000~5,000 행 정도씩 쓰는 게 적당한 느낌임. 누군가는 TEMP 테이블에 데이터를 먼저 올리고, 나중에 조인하는 방식[특히 COPY … FROM]이 성능상 더 좋다고 조언했는데, 그건 코드 변화가 너무 크고, 결국 그 전략은 포기함. 전반적으로 좋은 경험담이 모인 유익한 모음집이라 생각함. 경고성 사례로 유용함

    • ‘이런 시도 자체가 저주받은 아이디어’라는데 공감함. 목록을 다 읽어보면, ‘저주 목록’이라는 게 일종의 막힌 점이나 설계 함정이라기보다 실제 개발자가 부딪혀서 체득한 교훈 같은 느낌을 받았음. 물론 정보마다 완성도가 다르고 아직 진행 중인 것들도 있으나, 엔지니어링 로그 내 개인적인 경험담으로 이해하면 더 가치가 있음

    • 파일 시스템의 모든 파일 이름을 NUL 문자 없이 xargs 같은 툴로 한 번에 처리하려는 경우랑 비슷한 느낌임. 특이하거나 깨진 파일명이 있거나, 메모리가 넉넉하지 않다면 곤란함. find -print0와 parallel -0/xargs -0 등의 도구를 사용하는 게 좋음. 그리고 sed, grep 등도 LC_ALL=C 없이 쓰면 다중바이트 문자 시퀀스 오류가 발생하니 조심해야 함

    • 실제로 ORM으로 레코드를 대량 upsert 하다가 6만5천 개 바인딩 오류를 직접 겪어 봤음. 특히 테이블에 SQL 배열 타입 컬럼이 있을 때, 삽입하는 항목마다 바인딩해야 하니까 바인딩 변수 수가 기복을 띄게 됨. 그래서 두 번 실행해도 행/열 수는 같아 보여도 바인딩 필요 변수 수는 달라지는 불안정한 상황이 됨

    • 또 다른 전략으로, 값들을 배열 인자(text[]나 int[] 등)로 전달하는 방법도 있음. PostgreSQL도 이건 잘 처리함. ANY() 연산이 IN()보다 약간 느리긴 하지만, 한 파라미터 안에 여러 ID를 담을 수 있음. 아마 ORM이 그걸 지원하지 않았을 수도 있음

    • 나도 그 부분이 눈에 띄었음. 그렇게 많은 파라미터를 바인딩하는 건 확실히 저주받은 방식임. 대량 처리라면 대부분 COPY를 써야 함. 진짜 저주받은 Postgres 사례 하나 더 추가하자면, prepared statement 이름이 NAMEDATALEN-1 만큼만 조용히 잘림(NAMEDATALEN은 64). 이건 2001년부터 그랬고, 사실 그 전에도 있었음. ORM들이 이런 부분을 반드시 인지해야 함. 사람이 60자 넘는 prepare name을 쓰는 경우는 드물지만, ORM은 예외임

  • ‘패키지 50개 추가 설치’ 항목은 정말 충격적임. 그 패키지 저자는 다운로드 수만 엄청 올렸을 것임. 전 세계적으로 낭비되는 대역폭과 디스크 공간을 생각하면 정말 아까움. 혹시라도 명성을 쌓으려고 그런 게 아닐까 궁금함

    • 이 ‘저주받은 지식’에서 지목된 패키지 메인테이너는 TC39 멤버임. 여러 유명 JavaScript 프로젝트에서 종종 논란이 됐던 인물임. 특정 polyfill 이슈와 관련해서 금전적 동기가 있다는 주장도 있었지만, GitHub Sponsor나 Tidelift의 수익이 크지 않기 때문에, 본인이 정말 호환성을 신념으로 삼고 있지 않나 생각함. 2025년 기준으론 그에 대해 생각이 조금 달라졌음. 중요한 유지보수를 꾸준히 하고 있고, 커뮤니티 내에서 계속해서 틀리는 견해를 내는 역할도 어쩌면 필요하다고 봄

    • 명성 또는 특이한 성향 때문일 수도 있지만, 엄청난 규모의 소프트웨어 공급망 공격을 위한 사전포석이라는 극단적 해석도 있음

    • 그 저자 거의 확실히 ljharb임

  • Windows의 NTFS Alternate Data Streams(ADS)는 기존 파일에 무제한의 파일을 숨길 수 있는 기능임
    macOS는 data fork, xattr, Spotlight(md) 인덱싱까지 기본으로 모든 이동식 볼륨에 수많은 숨김 및 임시 파일을 생성함. 해결법: mdutil -X /Volumes/path/to/vol
    그리고, opt-out 텔레메트리가 너무 많음(go, yarn, meilisearch, homebrew, vcpkg, dotnet, Windows, VS Code, Claude Code, macOS, Docker, Splunk, OpenShift, Firefox, Chrome, flutter 등 온갖 곳에서 사생활 침해 우려가 있음)

    • opt-out 텔레메트리: go의 경우 기본적으로 텔레메트리 데이터가 로컬에만 저장됨. 사용자가 원할 때만 일부 승인된 데이터를 telemetry.go.dev로 업로드할 수 있음. 업로드 활성화는 “go telemetry on”, 전체 비활성화는 “go telemetry off”로 조절 가능함(문서 참고)

    • opt-out 텔레메트리만이 진짜 유용한 텔레메트리임

  • ‘npm 스크립트가 실행될 때마다 npm 레지스트리에 HTTP 요청을 보낸다’는 제보에 대해, 사실인지 궁금함. 만약 그렇다면 패키지 매니저로서는 말도 안 되는 동작임

    • 아마 npm 업데이트가 있는지 확인하는 과정일 수 있음. 구버전 사용 시 업데이트 안내가 뜨기도 함

    • 아마도 업데이트 확인 때문일 것임. 때때로 업데이트 배너가 표시되곤 함

  • 하나 빼먹은 게 있어 보임. EXIF 메타데이터의 날짜/시간 처리와 관련된 라운드는 꽤 오래된 논쟁임
    참고 이슈1, 참고 이슈2, 참고 이슈3

    • 날짜/시간 자체도 저주받기 쉬움. 잘 돌아가더라도 관련 기능에서 언제든 문제가 터질 가능성이 있음. 특히 값이 시간대나 서머타임을 포함하고 있다면 더욱 취약함
  • Hadoop과 Kerberos 관련 ‘Madness beyond the gates’(링크) 문서가 연상됨. 이 글이 덕분에 미쳐버릴 위기에서 여러 번 구원받은 적 있음. 저자인 Steve에게 감사함을 표하고 싶음. 저주받은 지식을 얻어내기까지 얼마나 고생했을지 상상도 안 됨

  • 이런 저주받은 지식을 한곳에 정리한 개념이 너무 좋음. 실제로 프로젝트에 깊이 들어가야만 겪을 수 있는 시행착오라는 것도 공감됨. 앞으로 프로젝트마다 이런 목록을 만들어둘 생각임

  • 이 항목은 저주가 아니라, 모바일 OS에서의 권한 관리와 관련한 보안/프라이버시 이슈임

  • 멋진 아이디어임! 다른 분들도 각자의 저주받은 지식을 공유하고픈 생각이 있나 궁금함
    내 경험상 MacOS 파일명도 저주임:

  1. 기본적으로 MacOS에서 파일명은 대소문자를 구분하지 않음(file.txt와 FILE.txt가 동등)
  2. MacOS에서 파일명을 NFC로 저장하면, 때때로 NFD로 변환될 수 있음
  • 1995년 Windows 95 베타 때 CDDB를 처음 만들었음. CD 음반의 트랙 이름들을 모아 .ini 파일로 배포했는데, 64KB라는 .ini 파일 크기 제한 때문에 프로젝트가 중단된 적 있음

  • 맞음. 시스템이나 데이터 볼륨에 case-sensitive APFS나 HFS+ 볼륨을 만들면 무조건 문제가 생김

  • ‘1번’ 항목은 기본 설정일 뿐임. HFS, APFS 둘 다 대소문자 구분 옵션이 있음. NTFS도 비슷하게 동작함. 이들 파일 시스템은 case-retentive이기 때문에 아래와 같이 쓸 수 있음

 $ echo yup > README.txt
 $ cat ReAdMe.TXT
 yup
 $ ls
 README.txt

진짜 문제는 Steam이 case-sensitive 파일 시스템에서는 인스톨 자체를 거부한다는 점임(Linux 버전도 있음에도 불구하고)