• 개발
  • 7th October 2026
PHP 8.5 에서 외부 API 호출의 TLS 연결을 요청 간에 재사용하기 — curl 영구 공유 핸들 실측 (93ms→14ms)

결제 승인, 지도 좌표 변환, 메신저 알림처럼 요청이 들어올 때마다 외부 HTTPS API를 한 번씩 부르는 웹앱이 많다. PHP에서는 이 호출이 매번 처음부터 시작된다. DNS를 찾고, TCP 연결을 맺고, TLS 핸드셰이크를 하고, 그다음에야 요청 한 줄을 보낸다. 응답을 받고 PHP 요청이 끝나면 그 연결은 버려지고, 다음 방문자의 요청은 같은 서버에 같은 과정을 또 거친다. PHP 8.5에 들어온 curl_share_init_persistent()는 이 연결을...

Read More
  • 개발
  • 7th October 2026
견적서 인쇄에 CSS @page 여백 상자로 머리글·쪽 번호 넣기 — 크롬 131 이상에서만 되는 범위와 position: fixed 비교

견적서나 주문서, 증명서처럼 종이로 뽑히는 화면을 만들면 결국 같은 요청이 온다. 페이지마다 위에 회사 이름을 넣어 달라, 아래에 "2 / 5" 같은 쪽 번호를 넣어 달라. 웹 페이지는 원래 쪽이라는 개념이 없어서, 이걸 처리하는 방법은 오랫동안 둘 중 하나였다. 머리글을 position: fixed로 띄워서 인쇄할 때 매 쪽에 반복되게 하거나, 아예 서버에서 PDF 라이브러리로 문서를 만들어 내려주거나. 앞쪽은 쪽 번호를 못 넣고, 뒤...

Read More
  • 개발
  • 7th October 2026
키 순서가 다른 JSON 을 MariaDB 에서 같은 값으로 비교하고 중복 막기 — JSON_EQUALS 와 JSON_NORMALIZE 실측

상품 옵션을 JSON 컬럼에 저장하는 테이블이 있다. 한 상품에 같은 옵션 조합이 두 번 들어가면 안 되니, 저장하기 전에 같은 값이 이미 있는지 찾는다. $attrs = json_encode(['size' = 'M', 'color' = 'red']); $stmt = $pdo-prepare('SELECT id FROM product_option WHERE product_id = ? AND attrs = ?'); $stmt-execute([$productId, $attrs]); 한동안은 잘 돈다. 그러다 관리자 화면에서 옵션 순서를 바꿔 저장하는 기능이 ...

Read More
  • 개발
  • 4th October 2026
페이지마다 레이아웃이 좌우로 밀릴 때 html 에 scrollbar-gutter: stable 로 스크롤바 자리 미리 잡기

본문이 짧은 페이지에서 긴 페이지로 넘어가면 가운데 정렬된 레이아웃 전체가 왼쪽으로 몇 픽셀 밀린다. 다시 짧은 페이지로 가면 오른쪽으로 돌아온다. 메뉴를 오갈 때마다 로고와 본문이 좌우로 흔들린다. 모달을 열 때도 같은 일이 생긴다. 배경 스크롤을 막으려고 overflow: hidden을 걸면 스크롤바가 사라지고, 그만큼 페이지가 오른쪽으로 튄다. 원인은 같다. 세로 스크롤바가 화면 폭을 차지했다가 내놓기 때문이다. scrol...

Read More
  • 개발
  • 4th October 2026
#:~:text= 링크로 페이지 속 문장까지 이동·강조하기 — 한글은 조사까지 맞춰야 하고, 강조색은 ::target-text 로 바꾼다

긴 안내 페이지나 약관, 문서 링크를 보내면서 "세 번째 단락 중간쯤 보세요"라고 덧붙인 적이 있을 것이다. 받는 사람은 페이지를 열고 스크롤을 내리면서 그 문장을 찾아야 한다. 단락마다 id가 달려 있으면 #id로 보낼 수 있지만, 남이 만든 페이지에는 그런 게 없는 경우가 대부분이다. 주소 끝에 #:~:text=찾을말을 붙이면 이 문제가 풀린다. 브라우저가 페이지를 연 뒤 그 문장을 찾아 화면 가운데로 스크롤하고 강조 표시까...

Read More
  • 개발
  • 4th October 2026
문자열 상태값을 PHP backed enum 으로 바꾸기 — 오타·잘못된 DB 값·== 비교에서 달라지는 동작 실측

주문 상태를 문자열로 들고 다니는 코드는 흔하다. DB 컬럼에는 pending, paid, shipped, cancelled가 들어 있고, 코드에서는 상수로 묶어 비교한다. final class Status { const PENDING = 'pending'; const PAID = 'paid'; const SHIPPED = 'shipped'; const CANCELLED = 'cancelled'; } function canShip(string $status): bool { return $status === Status::PAID; } 상수를 만들어 두어도 함수가 받는 것은 그냥 string이다. ...

Read More
  • 개발
  • 2nd October 2026
한글 밑줄이 받침과 겹칠 때 text-underline-position: under 로 내리기 (skip-ink: all 비교)

한글에 밑줄을 그으면 줄이 글자 아래쪽에 붙는다. 급, 입, 글처럼 받침이 있는 글자는 받침 바닥에 줄이 겹쳐서, 링크 하나만 걸어도 글자가 뭉개져 보인다. 영문은 괜찮다. g나 y처럼 아래로 내려오는 꼬리 부분은 브라우저가 알아서 줄을 끊고 비켜 간다. 이 "비켜 가기"를 정하는 속성이 text-decoration-skip-ink다. 기본값 auto는 한글을 비켜 가지 않는다. 그런데 2026년 5월 크롬 148에 all 값이 들어오면서 이 값이 Basel...

Read More
  • 개발
  • 23rd September 2026
벡터 검색이란 무엇인가 — MariaDB 11.8 VECTOR 타입과 Laravel 13 whereVectorSimilarTo 실측

사내 문서 검색창에 "연차 어떻게 내요?" 라고 치면 아무것도 안 나온다. 문서 제목은 "휴가 결재 절차" 다. LIKE '%연차%' 로는 "휴가" 를 못 잡고, 전문검색(FULLTEXT)을 붙여도 단어가 다르면 마찬가지다. 사람은 두 문장이 같은 얘기라는 걸 바로 아는데 DB 는 글자가 다르니 남이다. 이 간격을 메우는 것이 벡터 검색이다. 그동안은 별도 벡터 DB 를 세우거나 PostgreSQL 에 pgvector 를 붙여야 했는데, MariaDB 11.7 부터 VE...

Read More
  • 개발
  • 22nd September 2026
스크롤바 숨기던 세 줄을 scrollbar-width 한 줄로 — 단, 표준 속성을 쓰는 순간 ::-webkit-scrollbar 는 전부 꺼진다

가로로 흐르는 탭 줄이나 칩 목록에서 스크롤바를 숨기고 싶을 때, 채팅창 옆의 두꺼운 회색 스크롤바를 얇고 옅은 것으로 바꾸고 싶을 때, 지금까지는 이렇게 썼다. .tabs::-webkit-scrollbar { display: none; } /* Chrome·Safari */ .tabs { -ms-overflow-style: none; } /* 옛 Edge·IE */ .tabs { scrollbar-width: none; } /* Firefox */ 세 줄이 전부 같은 일을 한다. ::-webkit-scrollbar 는 표준이 아니라 WebKit 이 2009...

Read More
  • 개발
  • 21st September 2026
Bootstrap 의 .was-validated 스크립트를 지우기 — :has() 와 :user-invalid 로 감싼 박스·라벨·오류 문구까지 CSS 로

폼 검증 표시는 대개 이런 구조로 되어 있다. 입력칸이 틀리면 입력칸 테두리만 빨개지는 게 아니라, 그걸 감싼 박스에 배경이 깔리고, 라벨 색이 바뀌고, 아래에 숨어 있던 오류 문구가 나타난다. 브라우저는 input:invalid 로 입력칸 자신은 골라 줬지만 그걸 감싼 div 나 옆에 있는 label 은 고를 방법이 없었다. CSS 선택자는 아래로만 내려가지 위로는 못 올라갔기 때문이다. 그래서 검증 스타일은 JS 몫이었다. Bootstrap 은...

Read More