전체 글 513

z-index를 높여도 가려지는 이유

드롭다운에 z-index: 9999를 넣어도 옆 공지 영역 뒤로 숨는다. 메뉴를 fixed로 바꾸면 이번에는 창 아래가 아니라 카드 안쪽에 붙는다. 둘 다 “앞으로 나오지 않는다”라고 말하기 쉽지만, 첫 문제는 그리는 순서이고 두 번째는 위치의 기준이다. 카드 경계에서 메뉴가 사라지는 경우에는 내용 잘림도 따로 구분해야 한다.z-index는 페이지 전체의 절대 순위가 아니라, 같은 쌓임 맥락 안에서 비교하는 값이다. 자식의 숫자를 바꾸기 전에 그 자식이 어느 묶음에 속하는지 찾아야 한다. 여기서 쌓임 맥락은 stacking context를 뜻한다. 메뉴의 부모가 낮은 순서의 묶음에 들어 있으면, 그 안에서 가장 높은 메뉴도 바깥의 다른 묶음을 넘지 못할 수 있다.아래 화면은 직접 작성한 HTML과 CSS..

Bash trap은 언제 정리 코드를 실행할까?

작업이 실패하면 임시 자료를 지우도록 trap cleanup EXIT를 등록했습니다. 그런데 중단 요청을 받은 뒤에도 다음 명령이 실행되거나, 정리 메시지는 남았는데 호출자는 성공으로 판단할 수 있습니다. trap이 실행됐다는 사실만으로 작업 중단, 자원 회수, 실패 전달이 모두 해결된 것은 아닙니다.trap은 지정한 사건이 발생할 때 셸이 실행할 명령을 정합니다. EXIT는 셸의 종료 시점이고, TERM은 운영체제 신호이며, ERR는 Bash가 특정 실패 문맥에서 실행하는 처리입니다. 셋을 같은 오류 처리 통로로 보면 실행 시점과 실행되지 않는 조건을 놓칩니다. 어떤 사건에서 어떤 상태로 끝낼지 먼저 정해야 정리 코드의 역할도 분명해집니다.아래 화면은 macOS의 Bash 3.2.57에서 실행한 출력과..

ETag는 캐시와 동시 수정을 어떻게 구분할까?

문서를 읽을 때 받은 ETag를 다음 요청에 그대로 넣었다. GET에는 304가 돌아왔는데 PUT에는 412가 돌아왔다. 같은 버전 문자열을 보냈는데 왜 결과가 달라질까? 조건부 요청은 문자열의 일치 여부만 묻지 않는다. 가지고 있는 본문을 다시 써도 되는지, 읽은 뒤 누군가 바꾼 문서를 덮어써도 되는지에 따라 질문과 비교 방식이 달라진다.ETag는 그 질문에 사용할 표현의 검증자다. 캐시를 켜는 스위치도, 변경 권한을 주는 비밀키도 아니다. 캐시가 응답을 얼마나 오래 재사용할 수 있는지는 Cache-Control이 정하고, 갱신을 허용할지는 요청 조건과 실제 변경 처리가 함께 정한다. 이 역할을 나누면 ETag가 있는데도 매번 통신하는 이유와, 캐시가 잘 동작하는데도 동시 편집이 덮어써지는 이유를 설명..

Python dict는 언제 같은 키로 볼까?

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.정수 ID에 해당하는 값을 넣은 뒤 참·거짓 상태를 같은 딕셔너리에 저장했는데, 항목 수가 늘지 않는다. {1: 'number', True: 'flag', 1.0: 'float'}에는 세 항목이 아니라 하나만 남는다. 숫자 1, 논리값 True, 실수 1.0은 서로 다른 타입이지만 Python의 딕셔너리에서는 같은 항목을 가리킬 수 있다. 타입 이름이나 화면에 출력되는 모양만으로 키의 독립성을 판단하면 입력을 받는 순간부터 값을 덮어쓸 수 있다.이 문제는 해시값이 우연히 겹친 것과 다르다. 같은 해시값을 갖더라도 서로 다른 키로 남는 객체가 있고, 자기 자신과 같지 않은 NaN도 같은 객체를 보관하면 다시 찾을 수 있다...

URLSearchParams는 쿼리를 보존할까?

?q=a%20~라는 쿼리에서 검색어를 읽으면 a ~가 나온다. 값을 바꾸지 않고 searchParams.sort()만 호출했는데 쿼리가 ?q=a+%7E로 달라진다. 키가 하나라 순서가 달라질 여지도 없다. 그런데도 URL 문자열을 전후 비교하면 같지 않다. 읽어 낸 값이 같다는 사실과 처음 받은 표기를 보존했다는 사실은 별개이기 때문이다.URLSearchParams는 원래 쿼리의 철자를 보관하는 편집기가 아니다. 이름과 값의 목록을 읽고 수정한 뒤 정해진 형식으로 직렬화하는 도구다. 따라서 검색 필터를 만드는 데 유용하지만, 외부에서 받은 주소를 손대지 않고 전달하거나 서명된 요청의 표현을 유지하는 문제까지 자동으로 해결하지는 않는다. 어떤 동일성을 지켜야 하는지에 따라 원문 문자열과 해석한 데이터의 역..

Git reset은 무엇을 되돌릴까?

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.마지막 커밋을 취소했는데 파일은 그대로 남아 있다. 반대로 같은 커밋을 대상으로 reset을 했더니 방금 편집한 내용까지 사라졌다. 두 결과는 모순이 아니다. reset에서 지정한 커밋은 돌아갈 기준이고, 옵션은 그 기준에 맞춰 어디까지 바꿀지를 결정한다. “커밋 취소”라는 말만으로는 실행 뒤의 파일 상태를 정할 수 없다.예를 들어 value.txt를 A, B, C 순서로 고쳐 각각 커밋한 다음, D로 고쳐 등록하고 E로 다시 편집했다고 하자. 이 상태에는 최신 커밋 C, 다음 커밋 후보 D, 화면에 보이는 파일 E가 동시에 존재한다. 여기서 B로 돌아간다는 요청은 세 내용을 모두 B로 바꾸라는 뜻일 수도 있고, C라는 ..

Bash 변수는 왜 한 인자가 아닐까?

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.value='red blue'로 저장한 뒤 show $value를 실행하면 두 인자가 전달되고, show "$value"로 바꾸면 한 인자가 전달됩니다. 변수에는 같은 문자열이 들어 있지만 명령이 받는 입력은 다릅니다. 화면에서 공백 하나로 이어 보이는 문자열과 프로그램에 전달하는 인자 목록을 같은 것으로 생각할 때 생기는 차이입니다.더 헷갈리는 경우는 값 자체에 따옴표를 넣었을 때입니다. value='"red blue"'처럼 저장해도 show $value는 하나의 인자를 만들지 않습니다. 따옴표가 데이터 안에 있다는 사실과, Bash가 명령을 읽을 때 따옴표 문법을 사용했다는 사실은 다릅니다. 이 구분을 이해하면 공백뿐..

Python 제너레이터는 왜 두 번째에 비어 있을까?

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.같은 숫자 묶음의 합계는 60인데, 바로 다음 줄에서 다시 합계를 구하면 0이 나온다. 원소를 지우는 코드는 없다. 입력을 리스트에서 제너레이터 식으로 바꿨을 뿐인데 검증·집계·출력 중 뒤쪽 단계가 빈 자료를 받는다. 이때 확인할 것은 숫자 계산보다 앞선다. 여러 함수에 넘긴 대상이 다시 읽을 수 있는 자료인지, 이미 진행 중인 읽기 위치 하나인지가 다르다.제너레이터는 값을 필요할 때 생산하므로 결과 전체를 미리 쌓지 않는 처리에 유용하다. 대신 한 번 꺼낸 값을 자동으로 보관하거나 처음으로 되감지는 않는다. 같은 변수를 다시 전달해도 새 작업이 시작되는 것이 아니다. 한 번 읽는 인터페이스를 여러 번 읽는 코드에 연결한..

Flex 아이템은 왜 줄어들지 않을까?

너비가 360px인 줄에 긴 제목과 72px 버튼을 놓았다. 제목에는 flex: 1 1 auto가 있고, 버튼은 줄어들지 않게 했다. 그런데 제목이 버튼을 바깥으로 밀어낸다. flex-shrink를 더 크게 줘도 배치가 기대대로 돌아오지 않는다. 여기에 min-width: 0을 추가하면 버튼은 제자리로 오지만 이번에는 제목 글자가 버튼 뒤로 흘러간다. 같은 화면의 가로 넘침처럼 보여도 두 단계의 문제가 이어진 결과다.아이템의 박스가 줄어들 수 있는지와, 그 박스 안의 내용을 어떻게 보여 줄지는 별개다. Flex의 자동 최소 크기는 첫 번째를 제한하고, 줄바꿈·말줄임·스크롤은 두 번째를 결정한다. 따라서 최소 너비 한 줄을 모든 요소에 추가하는 것보다, 어떤 항목이 공간을 양보하고 어떤 정보는 끝까지 남겨..

HTTP 재시도: 응답이 없으면 실패일까?

본문 중간의 쿠팡 추천 상품 구매시 쿠팡 파트너스에서 일정액의 수수료를 제공받습니다.주문 생성 요청을 보냈는데 응답 대신 연결 오류가 돌아왔다. 같은 요청을 다시 보냈더니 이번에는 성공했고 주문 번호도 받았다. 이 결과만으로 주문이 한 건 생성됐다고 볼 수 있을까? 응답을 보내기 직전에 연결을 끊는 시험용 HTTP 처리기에서는 달랐다. 첫 요청에서 이미 한 건이 만들어졌고 재전송이 두 번째 한 건을 추가했다. 클라이언트가 본 실패와 서버에서 일어난 변경은 일치하지 않았다.재시도 여부를 정할 때 필요한 것은 오류 이름 하나가 아니다. 앞선 시도가 어떤 상태까지 갔는지, 같은 의도를 다시 전달하는 방법이 있는지, 기다릴 시간과 추가 부하를 감당할 수 있는지를 함께 판단해야 한다. 특히 데이터 변경 요청에서는..

페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사