SVG를 파헤치게 된 이유…
블록 코딩 사이트를 만드는 팀 프로젝트를 진행하면서 blockly라는 블록 조립 라이브러리를 사용하게 되었다. 기획대로 UI를 수정하려고 보니 라이브러리의 많은 UI 요소들이 SVG로 만들어져 있었다. 이를 제대로 다루기 위해서는 SVG에 대한 이해가 선행되어야 된다고 생각했고 그래서 이 글에서 svg에 대해 알아보기로 했다.
SVG 알아보기
SVG는 뭐길래 안 깨지는 거니?
SVG(Scalable Vector Graphics)는 이름에서 알 수 있듯이 벡터 기반의 그래픽 파일 포맷이다. JPEG와 같은 픽셀 기반의 래스터 파일과는 달리, SVG는 점과 선 등 기하학적 요소에 수학 공식을 적용해 이미지를 생성한다. 그래서 그래픽의 크기를 마음대로 조절해도 화질이 깨지지 않아 특히 아이콘이나 로고 같은 단순한 그래픽을 표현하는 데 매우 유용하다. 또한, SVG는 1999년 W3C에 채택된 이후 꾸준히 발전해와서 현재는 대부분의 모던 브라우저에서 지원된다.
안 깨지는 것 외의 장점은?
- 작은 용량: 단순한 그래픽의 경우 래스터 이미지보다 파일 크기가 작다.
- SEO 친화적: XML 코드로 작성되어 모양을 텍스트 정보로 저장하게 된다. 그래서 검색 엔진이 그래픽의 키워드(TEXT 태그 등)를 읽을 수 있다.
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="red" />
<circle cx="150" cy="100" r="80" fill="green" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>
👉 SVG의 xmlns 속성은 무엇일까?
xmlns는 XML Namespace를 정의하는 속성이다. 마크업 내의 내용을 어떤 규칙으로 해석해야 하는지 알려주는 용도다.
예를 들어, 서로 다른 XML 스키마를 병합할 때 같은 이름이 존재해 충돌이 발생할 수 있다. 이런 상황을 방지하기 위해 xmlns 속성에 namespace 값을 주어 이를 구분하는 것이다.
그러나 인라인 svg의 경우 웹 브라우저에서 렌더링을 할 때 xmlns과 version 옵션을 필요로 하지 않는다.
그럼 단점은 뭐야?
SVG는 고품질 디지털 사진을 표현하기에는 적합하지 않다. 고품질 사진은 SVG로 만들면 용량이 어마어마하게 늘어나기 때문에 디테일이 많다면 JPEG를 사용하는 것이 좋다.
SVG 작성법
🚨 잠깐! SVG 작성 시 주의할 점
SVG는 XML 코드로 작성되는데, XML의 경우 대소문자를 구분하기 때문에 요소를 작성할 때 대소문자 구분에 주의해야 한다. 또한, 속성 값은 반드시 따옴표로 둘러싸야 한다.
SVG 레이아웃
- Canvas and Viewport
Canvas는 svg 콘텐츠가 렌더링되는 공간이다. 그래서 공간 내에서 무한한 좌표를 사용할 수 있다.
Viewport는 너비와 높이를 설정해 이 svg가 실제로 화면에 보여지는 공간을 의미한다.
<svg width="512" height="512"> ... </svg>
- Viewbox
viewBox는 viewport 내에서 svg 요소의 크기를 확대/축소 또는 위치 변경을 할 수 있게 도와주는 속성이다. min-x min-y width height와 같은 형태로 값을 전달 받는다.
사실 정확히 어떤 역할을 하는지 이해가 안 가서 직접 viewBox 값을 조절하며 테스트했다. viewBox 값을 아래와 같이 조절하면 처음에 그려졌던 도형을 svg 태그에 주었던 width="100" height="100"에 맞춰서 그린 후 viewport를 min-x min-y 으로 이동하고 width height로 사이즈를 변경하는 것 같다.<svg width="100" height="100" viewBox="0 0 100 100" style="background-color: green"> <circle cx="50" cy="50" r="50" /> </svg>
기본 도형 그리기
사각형, 원, 타원, 직선, 폴리라인, 다각형과 같은 기본 도형을 그릴 수 있다. 속성 값이 간단해서 금방 보고 따라 그릴 수 있다.
<svg>
<rect width="너비" height="높이" />
<circle cx="원의 중심 X 좌표" cy="원의 중심 Y 좌표" r="반지름" />
<ellipse cx="원의 중심 X 좌표" cy="원의 중심 Y 좌표" rx="X축 반지름" ry="Y축 반지름" />
<line x1="시작점" y1="시작점" x2="끝점" y2="끝점" />
<polyline points="x점,y점 x점,y점 x점,y점 x점,y점" />
<polygon points="x점,y점 x점,y점 x점,y점 x점,y점" />
</svg>
패스 도형 그리기
좀 더 복잡한 도형은 패스 자체를 정의해서 그릴 수 있다. path 태그를 이용하면 되고 패스의 그리는 방법은 d 속성에 작성하면 된다. 명령어의 대문자는 절대 좌표, 소문자는 상대 좌표를 의미한다.
<svg>
<path
d="M248.761,92c0,9.801-7.93,17.731-17.71,17.731c-0.319,0-0.617,0-0.935-0.021c-10.035,37.291-51.174,65.206-100.414,65.206 c-49.261,0-90.443-27.979-100.435-65.334c-0.765,0.106-1.531,0.149-2.317,0.149c-9.78,0-17.71-7.93-17.71-17.731 c0-9.78,7.93-17.71,17.71-17.71c0.787,0,1.552,0.042,2.317,0.149C39.238,37.084,80.419,9.083,129.702,9.083c49.24,0,90.379,27.937,100.414,65.228h0.021c0.298-0.021,0.617-0.021,0.914-0.021C240.831,74.29,248.761,82.22,248.761,92z"
fill="#f9ef21" stroke="#f9cf01" stroke-width="7" stroke-linejoin="round" />
</svg>
이동(moveTo) | M, m | 패스를 시작할 위치를 지정한다. |
닫기(closePath) | Z, z | 현재 점에서 시작 점까지 직선을 그린다. |
직선(lineTo) | L, l | 현재 점에서 다음 전까지 직선을 그린다. |
직선(lineTo) | H, h | 현재 점에서 수평선을 그린다. |
직선(lineTo) | V, v | 현재 점에서 수직선을 그린다. |
커브(curve) - Cubic Bézier | C, c | C x1 y1, x2 y2, x y |
커브(curve) - Cubic Bézier | S, s | S x2 y2, x y |
커브(curve) - Quadratic Bézier | Q, q | Q x1 y1, x y |
커브(curve) - Quadratic Bézier | T, t | T x y |
커브(curve) - Elliptical arc | A, a | A rx ry x축-회전각 큰-호-플래그 쓸기-방향-플래그 x y a rx ry x축-회전각 큰-호-플래그 쓸기-방향-플래그 dx dy |
마치며
위 내용을 모두 기억하지는 못 하겠지만 한 번 쯤은 SVG에 대해 알아보는 것도 좋은 것 같다.
참고
https://developer.mozilla.org/ko/docs/Web/SVG
https://www.adobe.com/kr/creativecloud/file-types/image/vector/svg-file.html
https://a11y.gitbook.io/graphics-aria/svg-graphics/svg-paths-shape
'Frontend' 카테고리의 다른 글
Mixpanel을 활용한 사용자 행동 패턴 분석(1) (1) | 2025.01.12 |
---|---|
Chromium의 렌더링 파이프라인: Blockly는 왜 움직이는 블록을 다른 레이어로 분리할까? (3) | 2025.01.01 |
div 테두리 겹침 현상 해결하기 (1) | 2024.10.13 |
offsetWidth으로 강제로 랜더링시키기 (1) | 2024.09.08 |