사진을 바로 세웠는데 썸네일과 본문이 서로 다른 방향의 크기를 사용한다면 레이아웃은 다시 흔들릴 수 있다. 나는 실제 표시 코드에서 원본 치수와 화면 치수를 따로 유지한 이유를 읽었다. 새 사진을 만들지 않고도 검산할 수 있도록 작은 가상 크기와 기존 배율 모듈로 그 관계를 풀었다.

사진을 다시 만드는 일과 바로 세워 보여 주는 일을 나눴다

옆으로 누운 사진을 바로 세우는 방법은 파일을 다시 저장하는 것만 있는 게 아니었다. 선택한 코드의 표시 회전 함수는 검수 장부에서 각도를 읽고 사진 메타데이터에 반영한다. 그 함수 안에는 원본 이미지를 열어 픽셀을 다시 저장하는 처리가 없다. 원본을 보관하면서 보여 줄 방향을 정하는 선택이었다.

이번에는 실제 사진을 열어 방향을 새로 판정하지 않았다. 이전 작업의 회전·단계 검수 기록과 현재 표시 코드를 읽었다. 마감 보정처럼 새 이미지가 필요한 작업은 별도 흐름이다. 표시 회전을 했다는 사실을 사진 보정 완료로 세거나, 코드 검토를 현장 원본 검수로 넓혀 말하지 않으려 했다.

원본 크기와 표시 크기가 다른 순간을 기록했다

회전 장부는 검수 상태가 checked인 항목의 각도를 사용하고, 그렇지 않으면 0으로 둔다. 허용 값은 0·90·180·270도다. 90도와 270도에서는 표시할 가로와 세로를 바꾸되 raw_width와 raw_height에 원래 치수를 남긴다. 같은 숫자 두 개라도 어느 방향을 기준으로 한 크기인지 역할이 다르다.

예를 들어 1200×800이라는 가상 원본을 90도 돌리면 표시 상자는 800×1200이다. 원본의 가로 사진이라는 속성만 뒤의 레이아웃에 넘기면 바로 세운 결과는 세로인데 가로 배치를 고를 수 있다. 이전 갤러리 글은 표시 방향이 전후 쌍 조건에 쓰인다는 점을 다뤘다. 이번에는 그 크기가 본문과 썸네일로 전달되는 경로를 더 따라갔다.

회전 각도만 붙이면 사진 틀의 계산이 끝나는 것은 아니었다

본문 렌더러는 표시 크기로 세로 사진 여부와 상자의 비율을 정한다. 90도와 270도에는 사진 요소의 가로 배율을 표시 높이/표시 너비로, 세로 배율을 그 역수로 둔다. CSS는 요소를 가운데 놓고 회전한다. 가상 800×1200 표시 상자에 1.5와 2/3를 적용하면 회전 전 요소는 다시 1200×800 모양이 된다.

이는 선택한 렌더러와 CSS의 결합을 읽고 숫자로 확인한 것이다. 실제 브라우저가 이미지 로딩 뒤 같은 결과를 그렸다는 검수는 아니다. 회전된 경로에서 일반 srcset 문자열을 생략하는 조건도 보였지만, 그것을 모든 사이트의 최적화 지침으로 바꾸지 않았다. 이 글은 해당 코드가 어떤 표시 계약을 사용했는지 설명한다.

작은 썸네일도 같은 방향의 크기로 계산했다

썸네일 함수는 표시 너비와 높이로 min(94/너비, 53/높이)를 구한다. 그 배율로 표시 틀의 크기를 만들고 안쪽 사진에는 원래 치수를 곱한 크기를 준다. 가상 1200×800 원본을 90도 돌린 경우에는 작은 표시 틀이 약 35.33×53이 된다. 원본 가로 비율로 계산하면 다른 크기가 나오는 지점이다.

이미 있는 주석 좌표 모듈의 contain 계산을 이 작은 검산에 재사용했다. 표시 방향이 정해진 가상 크기와 전체 영역을 넣고 94×53 틀 안에 들어오는 크기를 비교했다. 이 모듈의 가운데 여백 좌표까지 원래 썸네일 DOM의 실제 위치라고 주장하지 않는다. 재사용한 것은 선언한 크기의 배율 계산이며 화면 배치는 별도 확인 대상이다.

코드와 구현 살펴보기

가상 90도 회전의 실제 계산 기록

{
  "geometry": {
    "raw": {
      "width": 1200,
      "height": 800
    },
    "rotation_cw": 90,
    "display": {
      "width": 800,
      "height": 1200
    },
    "element_scale_x": 1.5,
    "element_scale_y": 0.6666666666666666
  },
  "thumbnail_box": {
    "x": 29.333333333333332,
    "y": 0,
    "width": 35.333333333333336,
    "height": 53
  },
  "thumbnail_scale": 0.04416666666666667,
  "pixels_rotated": false,
  "raw_annotation_coordinates_transformed": false,
  "browser_rendering_checked": false
}

회전 정보가 단계 정정을 덮어쓰지 않게 읽었다

화면 자료를 읽는 함수는 원본 JSON을 새로 읽은 뒤 방향, 단계 검수, 면적, 선별, 보정 표시 순으로 적용한다. 선택한 시험 소스에는 단계 정정 뒤에도 90도 회전과 서로 다른 검수 출처가 남는지 확인하는 항목이 있다. 사진을 시공전으로 바로잡는 일과 사진의 위아래를 맞추는 일은 서로 다른 장부의 판단이다.

이 순서를 봤다고 이미 변형된 같은 사전을 아무 횟수나 다시 처리해도 안전하다고 말할 수는 없다. 이번 독립 함수는 매번 기준 치수와 각도로 새 결과를 만든다. 같은 기준으로 다시 호출하거나 각도를 0으로 바꾸는 검사도 넣었다. 이것은 새 예제의 계약이며 원래 프로그램의 모든 반복 적용 조건을 시험한 결과가 아니다.

기존 모듈은 재사용하고 새로 필요한 계산만 드러냈다

본문의 quarterTurnGeometry는 이번 설명을 위해 새로 만든 독립 메타데이터 함수다. 크기는 1부터 10000 사이 정수, 각도는 네 가지 회전으로 제한한다. 입력 크기를 바꾸지 않고 기준 크기·표시 크기·회전 전 요소 배율을 돌려준다. 파일을 읽거나 이미지를 돌리는 기능은 없으며 원래 사진 코드의 대체 설치본도 아니다.

기존 공개 ZIP을 내려받아 바이트와 해시를 대조하고 추출한 시험 15개를 실행했다. 새 함수와 그 크기를 기존 contain 계산에 연결하는 18개 검사도 통과했다. 다섯 사용 기록은 시험 개수에 더하지 않는다. 아래 코드는 이 글에서 복사할 수 있고, 연결한 기존 ZIP에는 주석/배율 모듈이 들어 있다. 새 함수가 그 옛 ZIP에 추가됐다고 설명하지 않는다.

코드와 구현 살펴보기

새 독립 함수 · 픽셀/주석 회전 없음

// Independent metadata calculation only. Does not rotate image pixels or points.
export function quarterTurnGeometry(raw, rotationCw) {
 if (!raw || Object.keys(raw).sort().join(',') !== 'height,width') throw Error('raw size fields');
 if (![raw.width, raw.height].every(n => Number.isInteger(n) && n >= 1 && n <= 10000)) throw Error('bounded integer size');
 if (![0, 90, 180, 270].includes(rotationCw)) throw Error('quarter-turn angle');
 const swapped = rotationCw === 90 || rotationCw === 270;
 const width = swapped ? raw.height : raw.width;
 const height = swapped ? raw.width : raw.height;
 return { raw: { ...raw }, rotation_cw: rotationCw, display: { width, height },
   element_scale_x: swapped ? height / width : 1,
   element_scale_y: swapped ? width / height : 1 };
}

화면에서 확인해야 할 일은 계산 뒤에도 남는다

표시 크기가 맞아도 실제 이미지의 방향과 촬영 장면이 맞다는 결론은 나오지 않는다. EXIF 해석, 픽셀 회전, 원본 좌표에 있던 주석의 회전은 이번 함수가 처리하지 않는다. 기존 좌표 모듈에 원본 방향의 박스를 그대로 넣으면 이 예제의 전제와 달라진다. 통합할 때는 크기와 영역이 어느 방향을 기준으로 했는지 함께 맞춰야 한다.

원래 사진·검수 장부·보정 결과와 고객 사이트는 이번 작업에서 바꾸지 않았다. 실제 렌더링이나 모바일 조작도 검사하지 않았다. 나는 이런 경계를 남긴 코드가 다음 제작자에게 더 쓸모 있다고 본다. 원본을 보존한 채 방향과 크기를 다루는 작은 계산부터 검산하면, 화면을 고치려다 사진의 근거와 다른 판단까지 함께 바꾸는 일을 줄일 수 있다.