패스 - SVG: Scalable Vector Graphics

패스
==

* « 이전
* 다음 » (en-US)

`<path>` 엘리먼트는 SVG 기본 도형 라이브러리에서 가장 강력한 엘리먼트이다. 선과 곡선, 호 등 다양한 형태를 그릴 수 있다.

패스는 여러 개의 직선과 곡선을 합쳐서 복잡한 도형을 그릴 수 있게 해준다. 직선으로만 이루어진 복잡한 도형은 polylines으로도 그릴 수 있지만, 곡선을 묘사할 때 polylines은 패스로 그린 도형에 비해 더 많은 직선이 필요에 확대가 잘 되지 않을 수 있다. 그렇기에 SVG를 그릴 때 패스에 대해 이해하는 것은 매우 중요하다고 할 수 있다. 복잡한 패스를 XML 편집기 또는 일반적인 텍스트 에디터로 그리는 것은 권장하지 않지만, SVG가 표시될 때 문제점을 찾고 고치는 데는 충분히 도움이 될 것이다.

패스의 모양은 `d (en-US)` 속성 하나로 정의된다(basic shapes 참조). `"d"` 속성은 여러 개의 명령어와 그 파라미터들로 이루어진다.

각각 명령은 특정 알파벳으로 시작한다. 예를 들면 현재 그려지는 위치를 XY 좌표계의 (10, 10)으로 이동할 때 "Move To" 명령을 사용하게 되는데, 이 명령은 알파벳 M으로 호출한다. SVG 처리기가 이 문자를 읽게 되면 다른 위치로 이동하라는 명령으로 이해하게 된다. 즉, (10, 10)으로 이동하려면 명령어 "M 10 10"을 쓰면 된다. 이후에 처리기는 다음 명령어를 읽기 시작한다.

모든 명령어는 2가지 변형이 존재하는데, 알파벳이 **대문자**일 경우(예를 들면 대문자 M), 뒤따르는 좌표는 페이지의 절대 좌표를 참조하며, **소문자** 알파벳(m)일 경우 마지막 위치에 대한 상대적 좌표로 참조된다.

"d" 속성의 좌표는 **절대 단위가 붙지 않으며,** 패스의 위치나 형태가 어떻게 변형될 수 있는지는 나중에 배우도록 한다.

선(Line) 명령어
-----------

`<path>` 노드에는 다섯 개의 선 명령어가 있다. 이름에서 알 수 있듯이 각각의 명령어는 두 점 사이에 선을 그리는 역할을 한다. 첫 번째 명령어는 'Move To(이동하기)' 혹은 'M' 이다. 이 명령어는 두 개의 파라미터로 x와 y 좌표를 받는다. 그리기 커서가 이미 페이지의 다른 곳에 있었더라도 두 점 사이에 점이 그려지지는 않는다. 'Move To' 명령어는 다음과 같이 패스의 맨 처음에 와서 그리기를 시작할 위치를 지정한다:
```

 M x y
```

혹은
```

 m dx dy
```

아래의 예제에서는 좌표 (10,10)에만 점을 찍었다. 일반적으로 패스를 그릴 때는 이 점이 나타나지 않는다는 점에 주의해야 한다.

![10x10 크기의 흰색 사각형에 빨간색 점이 그려집니다. 이 점은 일반적으로 표시되지 않지만 "이동 위치" 명령 후 커서가 시작되는 위치의 예로 사용됩니다.](/ko/docs/Web/SVG/Tutorial/Paths/blank_path_area.png)

```xml
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">

  <path d="M10 10"/>

  <!-- 점 -->
  <circle cx="10" cy="10" r="2" fill="red"/>

</svg>
```

선을 그리는 명령어는 세 가지가 있다. 가장 일반적인 것은 'L'이라 부르는 "Line To(선 그리기)" 명령어이다. L 명령어는 x, y라는 두 개의 파라미터를 받아서 현재 위치에서 새 위치로 선을 긋는다.
```

 L x y (혹은 l dx dy)
```

가로선과 세로선을 그리는 축약 명령어도 있다. 'H'는 가로선을 그리고, 'V'는 세로선을 그릴 수 있다. 두 명령어는 한 좌표축으로만 이동하므로 하나의 파라미터만을 받는다.
```

 H x (혹은 h dx)
 V y (혹은 v dy)
```

도형 그리기부터 시작해 보자. 사각형을 그려볼 텐데(`<rect>`를 이용해 쉽게 그릴 수도 있다), 시작점부터 가로, 세로선도 함께 사용되었다.

![검은색으로 채워진 흰색 사각형이 그려집니다. 검은색 사각형의 모서리는 (10,10) 좌표에서 시작하여 (90,10) 위치로 수평 이동하고, (90,90)로 수직 이동하며, (10,90)로 수평 이동한뒤 원래 위치(10,10)로 돌아옵니다](/ko/docs/Web/SVG/Tutorial/Paths/path_line_commands.png)

```xml
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">

  <path d="M10 10 H 90 V 90 H 10 L 10 10"/>

  <!-- 점 -->
  <circle cx="10" cy="10" r="2" fill="red"/>
  <circle cx="90" cy="90" r="2" fill="red"/>
  <circle cx="90" cy="10" r="2" fill="red"/>
  <circle cx="10" cy="90" r="2" fill="red"/>

</svg>
```

'Z'라는 "Close Path(패스 닫기)" 명령어를 통해 쉽게 패스를 마무리할 수 있다. 이 명령어는 현 위치에서 시작점으로 직선을 그린다. 항상은 아니지만 패스의 끝에 자주 쓰인다. 대문자와 소문자 사이의 차이는 없다.
```

 Z (혹은 z)
```

위 코드를 짧게 줄여보면:

```xml
<path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black"/>
```

위의 형태를 상대좌표로도 표현해볼 수 있다. 상대좌표 명령어는 앞서 기술된 바와 같이 소문자로 되어 있는 명령어인데, 패스를 움직일 때 정확한 위치를 지정해주는 것이 아니라 현재 위치로부터 얼마나 움직여야 하는지를 기술해준다. 예를 들면 위 80x80 상자를 아래와 같이 표현할 수 있다.

```xml
<path d="M10 10 h 80 v 80 h -80 Z" fill="transparent" stroke="black"/>
```

여기서 패스는 (10,10)에서 시작하여 수평으로 80포인트**만큼 오른쪽**으로 움직이고 수직으로 80포인트**만큼 아래로** 이동하고 다시 시작점으로 이동하게 된다.

위 예제의 모양을 만드는 데는 <polygon> 태그나 <polyline> 태그가 더 간편해보일 수 있지만, 패스는 SVG를 그릴 때 자주 사용되므로 개발자 입장에서 더 편할 수도 있다. 성능 면에서는 둘 모두 비슷비슷하니, 편한 것으로 사용하자.

곡선 (Curve) 명령어
--------------

부드러운 곡선을 그릴 수 있는 세 가지 명령어가 있다. 이 중 두 가지는 '베지어 곡선'이며, 나머지 하나는 원의 조각인 '호'이다. 베지어 곡선은 아마 일러스트레이터나 포토샵, 잉크스케이프 등의 벡터 그래픽 기반의 툴을 통해서 경험해봤을 것이다. 베지어 곡선의 수학적 배경은 위키피디아를 참조하길 바란다. 베지어 곡선의 종류는 무한하지만, 패스 엘리먼트에서는 가장 간단한 두 종류만을 지원한다. 하나는 'C'라고 부르는 3차(Cubic) 베지어 곡선이고, 다른 하나는 'Q'로 사용되는 2차(Quadratic) 베지어 곡선이다.

### 베지어 곡선

3차 베지어 곡선인 'C'는 조금 복잡한 곡선이다. 3차 베지어 곡선은 선을 잇는 두 점에 하나씩 제어점을 가지고 있다. 그러므로 3차 베지에 곡선을 그리려면 총 세 개의 좌표가 필요하다.
```

 C x1 y1, x2 y2, x y (혹은 c dx1 dy1, dx2 dy2, dx dy)
```

마지막으로 지정된 좌표 (x, y)는 곡선의 끝점이다. 나머지 두 개는 제어점이며, 첫 번째 제어점은 (x1, y1), 두 번째 제어점은 (x2, y2)이다. 제어점은 기본적으로 시작점과 끝점에서 곡선의 방향을 기술한다. 베지어 함수는 각 제어점의 방향을 이용해 부드러운 곡선을 만드는 기능을 한다.

![Cubic Bézier Curves with grid](/ko/docs/Web/SVG/Tutorial/Paths/cubic_bezier_curves_with_grid.png)

```xml
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">

  <path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
  <path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/>
  <path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="transparent"/>
  <path d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="transparent"/>
  <path d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="transparent"/>
  <path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="transparent"/>
  <path d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/>
  <path d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="transparent"/>
  <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="transparent"/>

</svg>
```

위 예제에서는 아홉 개의 베지어 곡선을 그린다. 왼쪽으로 갈수록 곡선이 수평에 가까워지고, 오른쪽으로 갈수록 제어점이 원점에서 멀어진다. 여기서 주목해야 할 점은 곡선이 첫 번째 제어점 방향으로 시작한 다음, 두 번째 제어점 방향으로 구부러지고 있다는 것이다.

여러 베지어 곡선을 연결하여 확장된 곡선 형태를 만들 수도 있다. 한 선의 제어점을 다른 선의 제어점과 반대 방향으로 그어서 완만한 경사를 만들어야 할 때가 많은데, 이 경우에는 간단한 형태의 3차 베지어 곡선 명령어인 'S' (혹은 's')를 사용해서 구현할 수 있다.
```

 S x2 y2, x y (혹은 s dx2 dy2, dx dy)
```

`S`는 위와 같은 형태의 곡선을 그리지만, 다른 `S`나 `C` 명령어 다음에 올 경우 첫 번째 제어점은 이전에 사용했던 제어점을 뒤집은 것으로 간주된다. `S` 명령어가 다른 `S`나 `C` 명령어 다음에 오지 않을 경우에는 현재 커서 위치가 첫 번째 제어점으로 사용되며, 이 경우에 그려지는 결과는 Q 명령어로 같은 파라미터를 사용해서 그린 결과와 같게 된다. 아래에 이 명령어의 예제가 있으며, 왼쪽의 미리보기에서 패스에 명시적으로 표시된 제어점은 빨간색, 생략된 제어점은 파란색으로 표시한다.

![ShortCut_Cubic_Bezier_with_grid.png](/ko/docs/Web/SVG/Tutorial/Paths/shortcut_cubic_bezier_with_grid.png)

```xml
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
</svg>
```

3차 베지어 곡선보다 간단한 다른 형태의 곡선은 'Q'라고 부르는 2차 베지어 곡선이며, 하나의 제어점이 시작점과 끝점의 방향을 모두 결정한다. 이 명령어는 매개변수로 제어점과 곡선의 끝점 2개를 받는다.
```

 Q x1 y1, x y (혹은 q dx1 dy1, dx dy)
```

![격자에 그려진 2차 베지어 곡선](/ko/docs/Web/SVG/Tutorial/Paths/quadratic_b%C3%A9zier_with_grid.png)

```xml
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
</svg>
```

3차 베지어 곡선과 같이 2차 베지어 곡선을 연결하는 단축 명령어가 있으며, T라고 부른다.
```

 T x y (혹은 t dx dy)
```

이 축약 명령어는 이전에 사용한 제어점으로부터 새로운 제어점을 만들어낸다. 즉, 처음에 제어점 하나만을 기술하면 끝점만을 계속 이어서 꽤 복잡한 도형을 만들 수 있다.

**참고:** Q나 T 명령어 다음에 올 때만 적용된다. 그렇지 않을 경우 제어점은 시작점의 좌표로 간주되며, 직선만 그릴 수 있게 된다.

![](/ko/docs/Web/SVG/Tutorial/Paths/shortcut_quadratic_b%C3%A9zier_with_grid.png)

```xml
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" fill="transparent"/>
</svg>
```

두 종류의 곡선이 비슷한 결과를 만들어내긴 하지만, 3차 곡선의 경우 모양을 더 자유롭게 수정할 수 있다. 둘 중 어느 것이 좋은지는 그때그때 다르며, 선 모양이 얼마나 대칭적인지에 따라 달라진다.

### 원호

SVG로 그릴 수 있는 다른 형태의 곡선으로는 A라고 부르는 호(arc)가 있다. 호는 원이나 타원의 일부분을 말한다. x, y축 반지름이 주어졌을 때, (두 점이 충분히 가깝다고 가정할 때) 두 점을 연결할 수 있는 타원은 2개가 있으며, 각각의 타원에서 두 점을 잇는 경로 또한 2개씩 있기 때문에 어떤 상황에서든 네 종류의 호를 그릴 수 있다. 이러한 성질 때문에 호 명령어는 꽤 많은 파라미터를 받는다:
```

 A rx ry x축-회전각 큰-호-플래그 쓸기-방향-플래그 x y
 a rx ry x축-회전각 큰-호-플래그 쓸기-방향-플래그 dx dy
```

A 명령어는 일단 x축, y축 반지름을 매개변수로 받는다. 혹시 필요하다면 ellipse 문서에서 두 매개변수가 어떻게 작동하는지 확인해볼 수 있다. 세 번째 매개변수는 호의 회전각을 기술한다. 이는 아래 예제에서 잘 확인할 수 있다.

![SVGArcs_XAxisRotation_with_grid](/ko/docs/Web/SVG/Tutorial/Paths/svgarcs_xaxisrotation_with_grid.png)

```xml
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
  <path d="M10 315
 L 110 215
 A 30 50 0 0 1 162.55 162.45
 L 172.55 152.45
 A 30 50 -45 0 1 215.1 109.9
 L 315 10" stroke="black" fill="green" stroke-width="2" fill-opacity="0.5"/>
</svg>
```

이 예제는 페이지를 대각선으로 가로질러 이동하는 패스인데, 그 중간에 두 개의 타원형 호가 절단되어 있다(x축 반지름 = 30, y축 반지름 = 50). 첫 번째는 x축 회전각이 0이므로 호의 기준이 되는 타원(회색으로 표시)은 위아래로 똑바로 서 있다. 두 번째 호는 x축 회전각이 -45도이므로 회전을 해서 예제에서 보이는 것처럼 타원의 단축과 패스 방향이 나란해졌다.

위에서 언급한 네 가지 경로는 이어지는 두 개의 매개변수 플래그에 의해 결정된다. 앞서 언급했듯이, 두 점을 잇는 타원도 2개, 각각 취할 수 있는 방향도 2개이므로 모두 네 가지 경로가 가능하다. 첫 번째 인수는 큰 호 플래그(large-arc-flag)이며, 중심각이 180도 이상이 될지를 결정한다. 결국, 이 플래그는 호가 주어진 원의 어느 방향을 따라 돌지를 결정한다. 두 번째 인수는 쓸기 방향 플래그(sweep-flag)이며, 호가 이동해야 할 각이 음인지 양인지를 결정한다. 이 각은 본질적으로 두 개의 원 중 어느 쪽을 따를지를 결정한다. 아래 예는 네 가지 가능한 조합을 각 사례별로 두 개의 원과 함께 표시하고 있다.

![Show the 4 arcs on the Ellipse example](/ko/docs/Web/SVG/Tutorial/Paths/svgarcs_xaxisrotation_with_grid_ellipses.png)

```xml
<svg width="325" height="325" xmlns="http://www.w3.org/2000/svg">
  <path d="M80 80
 A 45 45, 0, 0, 0, 125 125
 L 125 80 Z" fill="green"/>
  <path d="M230 80
 A 45 45, 0, 1, 0, 275 125
 L 275 80 Z" fill="red"/>
  <path d="M80 230
 A 45 45, 0, 0, 1, 125 275
 L 125 230 Z" fill="purple"/>
  <path d="M230 230
 A 45 45, 0, 1, 1, 275 275
 L 275 230 Z" fill="blue"/>
</svg>
```

![](/ko/docs/Web/SVG/Tutorial/Paths/svgarcs_flags.png)

마지막 두 개의 매개변수는 호가 끝나는 x와 y 좌표를 지정한다. 호는 도면에서 원 또는 타원 조각을 쉽게 만들 수 있는 방법이다. 예를 들어 원그래프는 각 조각마다 다른 호가 필요하다.

원을 한 바퀴 도는 패스의 경우 시작점과 끝점이 같으므로 선택할 수 있는 원이 무한히 있으며, 그러므로 실제 패스가 정의되지 않는다. 이때는 시작점과 끝점을 살짝 비뚤어지게 배치하고 이 둘을 다른 패스 선으로 마저 이음으로써 비슷하게 만들 수 있지만, 이때는 실제 원이나 타원 노드를 쓰는 것이 쉬울 때가 많다.

캔버스에서 SVG로 넘어오는 사람에게는 호가 가장 배우기 어려울 수도 있지만, 그런 만큼 강력하기도 하다. 다음 반응형 예제를 보면 SVG 호의 개념을 이해하는 데 도움이 될 것이다. http://codepen.io/lingtalfi/pen/yaLWJG (크롬과 Firefox로만 테스트했으므로 일부 브라우저에서 동작하지 않을 수 있음)

* « 이전
* 다음 » (en-US)


SVG 이미지 요소 - SVG: Scalable Vector Graphics

SVG 이미지 요소
==========

* « 이전 (en-US)
* 다음 » (en-US)

SVG `<image>` (en-US) 요소는 비트맵 이미지를 SVG 객체와 함께 표시할 수 있도록 해 준다.

이 기본 예제에서, `href (en-US)` 속성으로 참조된 a .jpg 이미지는 SVG 객체 내부에 표시될 것이다:

```xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="5cm" height="4cm" version="1.1"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">
  <image xlink:href="firefox.jpg" x="0" y="0" height="50px" width="50px"/>
</svg>
```

다음 몇가지를 주의하라(W3 specs 참조):

* x 또는 y 속성을 설정하지 않으면 0이 된다.
* height 또는 width 속성을 설정하지 않으면, 0이 된다.
* height 또는 width 속성이 0이면 이미지는 표시되지 않을 것이다.
* « 이전 (en-US)
* 다음 » (en-US)


SVG In HTML Introduction - SVG: Scalable Vector Graphics

SVG In HTML Introduction
========================

### 개요

이 문서와 관련된 예제는 form의 배경 그림을 제공하기 위해서 inline SVG를 어떻게 사용하는지를 보여줍니다. 정규 XHTML을 작성하는 것과 같은 방식으로 그 그림들을 조작하기 위해 JavaScript와 CSS의 사용법도 설명합니다. 예제들은 XHTML(HTML이 아님)과 SVG integration을 지원하는 웹브라우져에서만 동작함을 유의하시기 바랍니다.

### 소스

예제에 대한 소스는 여기:
```

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>XTech SVG Demo</title>
  <style>
    stop.begin { stop-color:yellow; }
    stop.end { stop-color:green; }
    body.invalid stop.end { stop-color:red; }
    #err { display:none; }
    body.invalid #err { display:inline; }
  </style>
  <script>
    function signalError() {
      document.getElementById('body').setAttribute("class", "invalid");
    }
  </script>
</head>
<body id="body"
   style="position:absolute; z-index:0; border:1px solid black; left:5%; top:5%; width:90%; height:90%;">
  <form>
     <fieldset>
       <legend>HTML Form</legend>
       <p><label>Enter something:</label>
          <input type="text"/>
          <span id="err">Incorrect value!</span></p>
       <p><button onclick="signalError();">Activate!</button></p>
     </fieldset>
  </form>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1"
    viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice"
    style="width:100%; height:100%; position:absolute; top:0; left:0; z-index:-1;">
    <linearGradient id="gradient">
      <stop class="begin" offset="0%"/>
      <stop class="end" offset="100%"/>
    </linearGradient>
    <rect x="0" y="0" width="100" height="100" style="fill:url(#gradient)" />
    <circle cx="50" cy="50" r="30" style="fill:url(#gradient)" />
  </svg>
</body>
</html>
```

### Discussion

위 페이지는 주로 정규 XHTML, CSS, JavaScript입니다. 다만 흥미로운 부분은 위 페이지에 포함되어 있는 `<svg>`원소입니다. 이 원소와 그 자식들은 SVG 네임스페이스 상에서 선언되어 있습니다. 이 원소는 하나의 색변화도(그라데이션)와 이 색변화도에 따라 내부가 채워진 두개의 도형을 포함하고 있습니다. 색변화도의 양끝의 색깔은 CSS에서 지정된 색을 가집니다. 만약 사용자가 form에 잘못된 내용을 입력하였다면 스크립트는 `<body>`태그에 `invalid`속성을 설정하고 스타일 규칙은 색변화도의 `end-stop`색을 빨간색으로 변경합니다. (나머지 스타일 규칙에 따라 에러 메시지가 출력됩니다.)

이 방식은 수고면에서 다음과 같은 특징을 가집니다:

* 우리는 기존의 웹사이트들에서 이전부터 사용되어온 정규 XHTML의 form을 사용했으며 여기에 매력적이고 인터랙티브한 배경그림까지도 추가했습니다.
* 이 방식은 SVG를 지원하지 않는 웹브라우져와 하위 호완성을 가집니다; 단순히 이들 웹브라우져에서는 배경그림만 없을 뿐입니다.
* 단순한 방식이며 아주 잘 동작합니다.
* 그림은 동적으로 필요한 크기에 따라 영리하게 스스로 크기를 변경합니다.
* HTML과 SVG 모두에게 적용될 수 있는 선언적 스타일 규칙들을 가질 수 있습니다.
* 같은 스크립트가 HTML과 SVG 모두를 조작할 수 있습니다.
* 문서는 완전히 표준에 기반하고 있습니다.
### Details

`viewBox`속성은 SVG 그림의 좌표계에 상대적인 논리적 좌표계를 생성합니다. 이 경우 그림은 100x100크기의 뷰포트에 놓여집니다.

`preserveAspectRatio`속성은 주어진 크기내에 그림을 넣을때 그림의 높이나 폭을 최대로 해서 주어진 크기에 맞게 그림을 맞추고 넘어가는 부분들을 잘라냄으로써 그림의 비율이 보존되도록 지정합니다.

`style`속성은 SVG 원소를 form의 배경에 고정시킵니다.

### Related Links

* Another SVG in XHTML example: A swarm of motes
* Inline SVG page on SVG wiki


SVG와 CSS - SVG: Scalable Vector Graphics

SVG와 CSS
========

이 페이지는 그래픽을 만들기 위한 특별한 언어 SVG를 설명합니다.

*SVG*(Scalable Vector Graphics, 스케일러블 벡터 그래픽)은 그래픽을 만들어내기 위한 XML-기반 언어입니다.

움직이지 않는 이미지(static image)를 위해 사용될 수 있으며, 또한 애니메이션 과 사용자 인터페이스를 위해서도 사용될 수 있습니다.

다른 XML-기반 언어들과 같이, SVG는 CSS 스타일 시트를 지원하여 그래픽에 사용되는 스타일을 그래픽의 내용물과 분리시킬 수 있게 합니다.

또한, 다른 문서 마크업 언어들과 함께 사용되는 스타일 시트들도 이미지가 요구되는 곳에 SVG 그래픽의 URL을 지정할 수 있습니다. 예를들면, HTML 문서와 함께 사용하는 스타일 시트에서 `background` 속성 값에 SVG값의 URL을 지정할 수 있습니다.

예제
--

새로운 SVG 문서를 텍스트 파일 `doc8.svg`로 만드세요. 아래의 내용물을 복사해서 붙여넣되 스크롤해서 전체를 다 넣을 수 있도록 하세요:

```html
<svg
 width="600px"
 height="600px"
 viewBox="-300 -300 600 600"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink">
  <link rel="stylesheet" href="style8.css" type="text/css" />

  <title>SVG demonstration</title>
  <desc>Mozilla CSS Getting Started - SVG demonstration</desc>

  <defs>
    <radialGradient
 id="fade"
 cx="0"
 cy="0"
 r="200"
 gradientUnits="userSpaceOnUse">
      <stop id="fade-stop-1" offset="33%" />
      <stop id="fade-stop-2" offset="95%" />
    </radialGradient>
  </defs>

  <text id="heading" x="-280" y="-270">SVG demonstration</text>
  <text id="caption" x="-280" y="-250">
    Move your mouse pointer over the flower.
  </text>

  <g id="flower">
    <circle
 id="overlay"
 cx="0"
 cy="0"
 r="200"
 stroke="none"
 fill="url(#fade)" />

    <g id="outer-petals">
      <g class="quadrant">
        <g class="segment">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(18)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(36)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(54)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(72)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>

      <g class="quadrant">
        <g class="segment" transform="rotate(90)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(108)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(126)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(144)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(162)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>

      <g class="quadrant">
        <g class="segment" transform="rotate(180)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(198)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(216)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(234)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(252)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>

      <g class="quadrant">
        <g class="segment" transform="rotate(270)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(288)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(306)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(324)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(342)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>
    </g>

    <g id="inner-petals" transform="rotate(9) scale(0.33)">
      <g class="quadrant">
        <g class="segment">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(18)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(36)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(54)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(72)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>

      <g class="quadrant">
        <g class="segment" transform="rotate(90)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(108)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(126)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(144)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(162)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>

      <g class="quadrant">
        <g class="segment" transform="rotate(180)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(198)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(216)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(234)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(252)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>

      <g class="quadrant">
        <g class="segment" transform="rotate(270)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(288)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(306)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(324)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
        <g class="segment" transform="rotate(342)">
          <path class="segment-fill" d="M0,0 v-200 a40,40 0 0,0 -62,10 z" />
          <path class="segment-edge" d="M0,-200 a40,40 0 0,0 -62,10" />
        </g>
      </g>
    </g>
  </g>
</svg>
```

새로운 CSS 문서를 텍스트 파일 `style8.css`로 만드세요. 아래의 내용물을 복사해서 붙여넣되 스크롤해서 전체를 다 넣을 수 있도록 하세요:

```css
/\*\*\* SVG demonstration \*\*\*/

/\* page \*/
svg {
  background-color: beige;
}

#heading {
  font-size: 24px;
  font-weight: bold;
}

#caption {
  font-size: 12px;
}

/\* flower \*/
#flower:hover {
  cursor: crosshair;
}

/\* gradient \*/
#fade-stop-1 {
  stop-color: blue;
}

#fade-stop-2 {
  stop-color: white;
}

/\* petals \*/
.segment-fill {
  fill: var(--segment-fill-fill);
  stroke: var(--segment-fill-stroke);
  stroke-width: var(--segment-fill-stroke-width);
}

.segment-fill:hover {
  fill: var(--segment-fill-fill-hover);
  stroke: var(--segment-fill-stroke-hover);
}

.segment-edge {
  fill: var(--segment-edge-fill);
  stroke: var(--segment-edge-stroke);
  stroke-width: var(--segment-edge-stroke-width);
}

.segment-edge:hover {
  stroke: var(--segment-edge-stroke-hover);
}

/\* outer petals \*/
#outer-petals {
  opacity: 0.75;
  --segment-fill-fill: azure;
  --segment-fill-stroke: lightsteelblue;
  --segment-fill-stroke-width: 1;
  --segment-edge-fill: none;
  --segment-edge-stroke: deepskyblue;
  --segment-edge-stroke-width: 3;
  --segment-fill-fill-hover: plum;
  --segment-fill-stroke-hover: none;
  --segment-edge-stroke-hover: slateblue;
}

/\*
 Non-standard way of styling elements referenced via <use> elements,
 supported by some older browsers
\*/
#outer-petals .segment-fill {
  fill: azure;
  stroke: lightsteelblue;
  stroke-width: 1;
}

#outer-petals .segment-edge {
  fill: none;
  stroke: deepskyblue;
  stroke-width: 3;
}

#outer-petals .segment:hover > .segment-fill {
  fill: plum;
  stroke: none;
}

#outer-petals .segment:hover > .segment-edge {
  stroke: slateblue;
}

/\* inner petals \*/
#inner-petals {
  --segment-fill-fill: yellow;
  --segment-fill-stroke: yellow;
  --segment-fill-stroke-width: 1;
  --segment-edge-fill: none;
  --segment-edge-stroke: yellowgreen;
  --segment-edge-stroke-width: 9;
  --segment-fill-fill-hover: darkseagreen;
  --segment-fill-stroke-hover: none;
  --segment-edge-stroke-hover: green;
}

/\*
 Non-standard way of styling elements referenced via <use> elements,
 supported by some older browsers
\*/
#inner-petals .segment-fill {
  fill: yellow;
  stroke: yellow;
  stroke-width: 1;
}

#inner-petals .segment-edge {
  fill: none;
  stroke: yellowgreen;
  stroke-width: 9;
}

#inner-petals .segment:hover > .segment-fill {
  fill: darkseagreen;
  stroke: none;
}

#inner-petals .segment:hover > .segment-edge {
  stroke: green;
}
```

문서를 SVG 기능이 있는(SVG-enabled) 브라우저에서 여세요. 마우스 포인터(mouse pointer)를 그래픽위로 움직여 보세요.

### 결과

이 예제에서 주의할 점:

* SVG 문서는 전처럼 스타일 시트에 링크되어 있습니다.
* SVG는 그 자신만의 CSS 스타일 시트와 값을 가지고 있습니다. 이들중 몇가지는 HTML을 위한 CSS의 속성과 비슷합니다.

| 스타일 시트를 변경해서, 마우스 포인터가 안쪽 꽃잎들 중 한개 위에 오게 되면, 바깥 쪽 꽃잎이 작동하는 방식은 바뀌지 않은채 모든 안쪽꽃잎 색이 핑크(pink)색으로 변하게 하세요 |
| --- |

그럼 다음은?
-------

If you had difficulty understanding this page, or if you have other comments about it, please contribute to its Discussion page.

이 예제에서 SVG 기능이 있는(SVG enabled) 브라우저는 이미 SVG 엘리먼트를 디스플레이하는 방법을 알고 있습니다. 스타일 시트는 단지 그 디스플레이를 특정 방식으로 수정할 뿐 입니다. 그러나 디스플레이하는 방식이 미리 지정되어 있지 않은 범용(general-purpose) XML 문서를 위해서 CSS를 사용할 수있습니다. 다음 페이지에서는 이를 실행해 봅니다: **XML data**


소개 - SVG: Scalable Vector Graphics

소개
==

* « 이전
* 다음 »

![Mozilla dino logo](/ko/docs/Web/SVG/Tutorial/Introduction/dino.svg)

SVG는 XHTML과 비슷한 XML 언어로 오른쪽에 있는 것과 같은 그래픽을 그리는 데 사용된다. SVG 이미지는 필요한 모든 선과 모양을 직접 일일이 지정하거나, 이미 존재하는 래스터 이미지를 수정하거나, 이 두 가지 방법을 조합해서 만들 수 있다. 이미지와 그 구성요소들은 변형되고, 조합되고, 필터링될 수 있으며, 이를 통해 원래의 형태를 완전히 바꿀 수도 있다.

SVG는 비슷한 경쟁 포맷들이 W3C에 제출되었지만 완전히 승인되지는 않았던 1999년에 등장했다. 명세는 오랫동안 존재해 왔지만 웹 브라우저에서 느리게 받아들여졌기 때문에, 웹 문서에서 바로 SVG를 포함하는 컨텐츠는 2009년까지도 많지 않았다. 사용할 수 있는 구현조차도 경쟁기술인 HTML5 캔버스나 (애플리케이션 인터페이스로서) 어도비 플래시보다 느린 편이다. SVG는 캔버스나 플래시와 비교했을 때 DOM 인터페이스를 사용할 수 있는 점과 서드파티 확장을 필요로 하지 않는 이점을 가지고 있다. SVG를 활용할 지는 사용자의 목적에 달려있다.

Can I Use...에서 확인할 수 있듯이, SVG 지원은 2009년부터 확대되어 왔다.

### 기본적인 요소들

HTML은 헤더, 문단, 표와 같은 요소들을 제공한다. SVG도 마찬가지로 원, 사각형, 간단한 곡선과 복잡한 곡선을 그릴 수 있는 요소들을 제공한다. 간단한 SVG 문서는 `<svg>` (en-US) 루트 요소와 그래픽을 구성하기 위한 몇몇 기본 도형들로 구성된다. 또한 `<g>` (en-US) 요소를 통해 간단한 모양들을 조합할 수 있다.

이를 통해서 SVG 이미지는 아주 복잡해질 수도 있다. SVG는 그라디언트, 회전, 필터 효과, 애니메이션, JavaScript를 통한 조작을 지원한다. 하지만 SVG의 이러한 추가적인 기능들은 그래픽 영역을 정의하는 비교적 작은 요소들의 집합에 의존하고 있다.

### 시작하기 전에

잉크스케이프(Inkscape)를 비롯해 SVG를 네이티브 포맷으로 활용하는 무료 드로잉 애플리케이션들이 있다. 하지만 이 튜토리얼에서는 순수하게 XML과 (독자가 선택한) 텍스트 에디터만을 사용한다. 이는 SVG의 내부 구조에 대한 이해를 돕기 위함이며, 이렇게 하기 위해서는 직접 마크업 언어를 경험해보는 것이 무엇보다 중요하다. SVG를 배우는 이유를 되새겨보자. 모든 SVG 뷰어가 같은 방식으로 구현되어 있지는 않기 때문에, 어떤 애플리케이션에서 잘 보여지도록 작성된 SVG가 다른 애플리케이션에서는 의도한 대로 작동하지 않을 수도 있다. 이는 SVG 명세나 SVG와 함께 사용되는 JavaScript나 CSS를 지원하는 수준이 서로 상이하기 때문에 발생하는 문제이다.

SVG는 모든 모던 웹 브라우저에서 지원하고 있으며, 이전부터 지원해오던 경우도 있다. Can I use에서 SVG 지원 현황을 표로 확인할 수 있다. Firefox는 1.5 버전에서부터 SVG를 지원해오고 있으며, 매 버전이 나올 때마다 SVG 지원 범위도 넓어지고 있다. 바라건대 이 튜토리얼과 MDN 문서가 개발자들이 Gecko와 다른 주요 구현체들의 차이를 이해하는 데 도움이 되길 바란다.

SVG를 시작하기에 앞서, 기초적인 XML 문법이나 HTML 같은 다른 마크업 언어를 이해할 필요가 있다. XML에 익숙하지 않다면 다음 사항들을 유념하기 바란다.

* XML은 (HTML과 달리) 대소문자를 구분하는 언어이므로 SVG 요소와 속성은 반드시 예제에 보이는 대로 입력해야 한다.
* SVG에서 속성 값은 숫자라고 할지라도 반드시 따옴표로 둘러싸야 한다.

SVG의 명세는 아주 길다. 이 튜토리얼에서는 기초적인 부분만을 다룬다. 이미 SVG에 익숙하다면 요소 레퍼런스나 인터페이스 레퍼런스 (en-US)에서 필요한 부분을 찾아보면 된다.

### SVG의 종류

2003년에 권고가 된 후 최신의 완전한(full) SVG 버전은 1.1이다. 1.1은 1.0을 기반으로 작성되었으나 구현을 쉽게 하기 위해 좀 더 모듈화되었다. SVG 1.1 두번째 에디션은 2011년에 권고되었다. 완전한 SVG 1.2가 SVG의 다음 주요 릴리즈였다. 1.2 대신 현재 활발히 개발중인 SVG 2.0으로 넘어갈 것이다. SVG 2.0에서는 CSS 3과 마찬가지로 구성요소들이 느슨히 결합된 명세들로 분리될 것이다.

완전한 SVG 권고와는 별도로 W3C 워킹 그룹에서는 2003년에 SVG Tiny와 SVG Basic을 내놓았다. SVG Tiny와 SVG Basic은 모바일 기기를 위한 것이다. 먼저 SVG Tiny에 따르면 적은 리소스를 가진 작은 기기에서도 그래픽을 생성할 수 있어야 한다. SVG Basic은 완전한 SVG 명세의 많은 부분을 지원하지만 구현하기 어렵거나 애니메이션과 같이 무거운 렌더 작업은 포함하지 않는다. 2008년에는 SVG Tiny 1.2가 W3C 권고가 되었다.

다중 페이지 지원 및 더 나은 색상 관리를 위한 SVG 프린트 명세도 계획되어 있었다. 이 작업은 현재 진행되지 않고 있다.

* « 이전
* 다음 »


시작하기 - SVG: Scalable Vector Graphics

시작하기
====

* « 이전
* 다음 »
### 간단한 예제

다음의 코드와 같이 간단한 예제로 시작해보겠습니다.

```xml
<svg version="1.1"
 baseProfile="full"
 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>
```

코드를 복사하여 demo1.svg로 저장하고, Firefox 에서 실행해 봅시다. 아래와 같은 화면이 그려질 것입니다.(Firefox 사용자 : 링크)

![빨간색 배경 중앙에 녹색 원이 있습니다. 원 가운데에 있는 흰색 텍스트는 SVG입니다.](/ko/docs/Web/SVG/Tutorial/Getting_Started/svgdemo1.png)

화면이 그려지는 과정은 다음과 같습니다.

1. SVG 루트 요소(Element)부터 시작합니다.
    * DTD기반의 SVG유효성 검사는 해결할 수 있는 것보다 많은 문제를 야기하기 때문에 (X)HTML로 알려진 Doctype 선언은 사용하지 않습니다.
    * 다른 유형의 유효성 검사를 위해 SVG버전을 식별하려면 항상 version과 baseProfile 속성(Attribute)을 사용해야 합니다.
    * XML 특수언어(dialect)로서 SVG는 (xmlsn 속성에서) 항상 네임 스페이스(namespace)를 올바르게 바인딩 해야합니다. 자세한 내용은네임 스페이스 충돌 과정 (en-US) 페이지를 참조하십시오.
2. 전체 이미지 영역을 포함하는 사각형 <rect />을 그려 배경을 빨간색으로 설정합니다.
3. 빨간색 직사각형의 중앙에 반경 80px의 녹색 원 <circle />이 그려집니다
4. 텍스트 "SVG"가 그려집니다. 각 문자의 내부는 흰색으로 채워집니다. 텍스트는 중심점이 되고자 하는 지점에 앵커를 설정하여 배치됩니다.이 경우 중심점은 녹색 원의 중심에 일치해야합니다. 글꼴 크기와 수직 위치를 미세 조정하여 심미적으로 뛰어난 최종 결과를 얻을 수 있습니다.
### SVG 파일의 기본 속성

* 가장 먼저 주목해야 할 것은 요소를 렌더링하는 순서입니다. SVG 파일 전체에서 유효한 규칙은, 내용의 *위에서 부터 아래로* 렌더링된다는 것입니다. 요소는 아래에 위치할수록 더 잘보이게 됩니다.
* 웹의 SVG 파일은 브라우저에 직접 표시되거나 HTML파일에 여러가지 방법을 통해 포함될 수 있습니다:
    + HTML이 XHTML이고 application/xhtml+xml 유형으로 제공되는 경우 SVG는 XML 소스에 직접 포함될 수 있습니다.
    + HTML이 HTML5이고 브라우저가 HTML5 브라우저를 준수하는 경우 SVG를 직접 삽입 할 수도 있습니다. 그러나 HTML5 사양을 준수하는 데 필요한 구문 변경이 있을 수 있습니다.
    + SVG 파일은 object 요소로 참조 할 수 있습니다:

    ```
            <object data="image.svg" type="image/svg+xml" />

    ```
    + 마찬가지로 iframe 요소로 사용할 수 있습니다:

    ```
            <iframe src="image.svg"></iframe>

    ```
    + 이론적으로, img 요소로 사용될 수 있습니다만 4.0 이전의 Firefox에서는 작동하지 않습니다.
    + 마지막으로 SVG는 JavaScript로 동적으로 생성되어 HTML DOM에 삽입 될 수 있습니다. 이는 SVG를 처리 할 수없는 브라우저에서 대체하여 구현할 수 있다는 장점이 있습니다.이 주제에 대해 깊이있게 다루기 위해 이 문서를 참조하십시오.
* SVG에서 크기와 단위를 처리하는 방법에 대해서는 다음 페이지에서 설명 할 것입니다.
### SVG 파일 형식

SVG 파일은 두 가지 형태로 제공됩니다. 일반 SVG 파일은 SVG 마크업이 포함 된 간단한 텍스트 파일입니다. 이러한 파일의 권장 파일 확장자는 소문자로 ".svg"입니다.

일부 응용 프로그램 (예 : 지리적 응용 프로그램)에 사용될 때 매우 큰 크기의 SVG 파일이 있을 수 있기 때문에 SVG 사양에서는 gzip으로 압축 된 SVG 파일을 허용합니다. 이러한 파일의 권장 파일 확장자는 소문자로 ".svgz"입니다. 하지만 안타깝게도 gzip으로 압축 된 SVG 파일을 Microsoft IIS 서버에서 서비스 할 때 모든 SVG 가능 브라우저(사용자 에이전트)에서 안정적으로 작동하게 하려면 문제가 많습니다. 그리고 Firefox는 로컬 컴퓨터에서 gzip으로 압축 된 SVG를 로드 할 수 없습니다. 웹 서버에 게시 할 때를 제외하고는 gzip으로 압축 된 SVG를 피하십시오 (아래 참조).

### 웹서버 관련 한 마디

이제 기본 SVG 파일을 만드는 방법에 대해 알아봤으므로 다음 단계는 웹 서버에 업로드하는 것입니다. 이 단계에서는 몇 가지 문제가 있습니다. 보통, SVG 파일의 경우 서버는 다음과 같이 HTTP 헤더를 보내야합니다.
```

Content-Type: image/svg+xml
Vary: Accept-Encoding
```

gzip으로 압축 된 SVG 파일의 경우, 서버는 다음과 같이 HTTP 헤더를 보내야합니다.
```

Content-Type: image/svg+xml
Content-Encoding: gzip
Vary: Accept-Encoding
```

네트워크 모니터 패널이나 web-sniffer.net과 같은 사이트를 사용하여 서버가 SVG 파일과 함께 올바른 HTTP 헤더를 보내고 있는지 확인할 수 있습니다. SVG 파일 중 하나의 URL을 전송하고 HTTP 응답 헤더를 확인해 보십시오. 서버가 위의 값으로 헤더를 보내지 않으면 웹 호스트에 문의해야합니다. 서버에 SVG를 올바르게 구성하도록하는 데 문제가 있으면 직접 할 수있는 방법이있을 수 있습니다. 다양한 간단한 솔루션에 대해서는 w3.org의 서버 구성 페이지를 참조하십시오.

SVG를 사용하는데 있어 서버 구성 오류가 SVG로드에 실패하는 가장 일반적인 이유이기에 확인하십시오. 서버가 SVG 파일을 제공하면서 올바른 헤더를 보내도록 설정되어 있지 않다면 Firefox는 SVG파일의 마크업을 텍스트 또는 인코딩된 의미없는 값으로 표시하거나 뷰어에게 열어 볼 응용 프로그램을 선택하도록 요청할 가능성이 큽니다.

* « 이전
* 다음 »


위치 - SVG: Scalable Vector Graphics

위치
==

* « 이전
* 다음 »
그리드
---

![가운데가 파란색 상자로 표시된 X, Y 좌표 격자](/ko/docs/Web/SVG/Tutorial/Positions/canvas_default_grid.png)모든 요소(Element)에 대해 SVG는 캔버스를 포함한 컴퓨터에서 무언가 그리고자 할때 많이 사용되는 것과 유사한 좌표계 또는 그리드 시스템을 사용합니다. 즉, 문서의 왼쪽 위 모서리는 (0,0)으로 간주되며 한 지점의 위치는 왼쪽 상단 모서리에서 픽셀 단위로 표시되고 X축의 양의 방향은 오른쪽, Y축의 양의 방향은 아래쪽으로 향하게됩니다. 어린시절 배웠던 그래프와는 반대라는 점을 기억하세요. 그러나 이것은 HTML의 요소가 배치되는 것과는 같은 방법입니다 (기본적으로 LTR 문서는 X를 오른쪽에서 왼쪽으로 배치하는 RTL 문서가 아닙니다).

#### 예제

아래 요소는
```

<rect x="0" y="0" width="100" height="100" />
```

왼쪽 상단에서 100px의 정사각형을 정의합니다.

### "픽셀"이란?

기본적으로 SVG 문서에서 1픽셀은 출력 장치(화면)의 1픽셀에 매핑됩니다. 하지만 이러한 방식만 가능했다면 SVG의 이름에 "확장성(Scalable)"이란 단어가 들어가 있지는 않았겠죠. CSS의 절대 및 상대 글꼴 크기와 매우 흡사하게 SVG는 절대적인 단위 ( "pt"또는 "cm"와 같은 식별자가있는 것)를 정의하고 이것을 사용자 단위(User Unit)로 명칭하며, 이것은 별도의 식별자 없이 숫자 그대로를 사용합니다.

별도로 명시하지 않았다면, 사용자 단위와 화면 단위는 1:1의 비율로 동작합니다. SVG에는 이 비율을 변경하기 위한 몇가지 방법이 있습니다.
```

<svg width="100" height="100">
```

위 요소는 100x100px 의 SVG 캔버스를 정의합니다. 사용자 단위와 화면 단위는 1:1의 비율로 동작합니다.
```

<svg width="200" height="200" viewBox="0 0 100 100">
```

SVG 캔버스 전체 크기는 200x200 픽셀입니다. 그러나 viewBox속성을 사용하여 (0,0)에서 시작하는 100x100px의 화면을 200x200px의 화면에 출력합니다. 이렇게하면 100x100 단위 영역을 효과적으로 확대하고 이미지를 두 배 크기로 확대 할 수 있습니다.

이러한 요소 혹은 전체 이미지의 사용자 단위와 화면 단위의 매핑을 사용자 좌표계(User coordinate system)이라고 합니다. 스케일링 외에도 회전, 기울이기, 뒤집기가 가능합니다. 기본 사용자 좌표계는 하나의 사용자 픽셀을 하나의 장치 픽셀에 매핑합니다. SVG파일에서 "in"또는 "cm"과 같은 특정 치수는 결과 이미지에서 1:1로 보이도록 계산됩니다.

SVG 1.1 스펙에서는 다음과 같이 인용합니다:

>
> [...] 사용자 환경에서 "1px"이 "0.2822222mm" 에 대응한다고 가정했을때(90dpi), SVG는 다음과 같이 처리한다: [...] "1cm"는 "35.43307px"과 같다. (그리고 35.43307 사용자 단위와 같다.)
>
>
>

* « 이전
* 다음 »


calcMode - SVG: Scalable Vector Graphics

calcMode
========

« SVG Attribute reference home

이 속성은 애니메이션의 interpolation 모드를 지정합니다. 기본 모드는 linear 이지만 속성이 linear interpolation을 지원하지 않으면(예: 문자열의 경우) calcMode 속성이 무시되고 discrete interpolation이 사용됩니다.

Usage context
-------------

| Categories | Animation value attribute |
| --- | --- |
| Value | discrete | linear | paced | spline |
| Animatable | No |
| Normative document | SVG 1.1 (2nd Edition) |

discrete

이것은 애니메이션 함수가 interpolation 없이 하나의 값에서 다음 값으로 점프하도록 지정합니다.

linear

값 사이의 단순한 linear interpolation은 애니메이션 함수를 계산하는데 사용됩니다. `<animateMotion>` (en-US)의 경우를 제외하고는 이것은 기본 값입니다.

paced

Defines interpolation to produce an even pace of change across the animation. This is only supported for values that define a linear numeric range, and for which some notion of "distance" between points can be calculated (e.g. position, width, height, etc.). If paced is specified, any `keyTimes (en-US)` or `keySplines (en-US)` will be ignored. For `<animateMotion>` (en-US), this is the default value.

spline

cubic Bézier spline에 정의된 시간 함수에 따라 `values (en-US)` 목록의 한 값에서 다음 값으로 interpolation 합니다. spline의 점(point)은 `keyTimes (en-US)` 속성에 정의되고, 각 간격의 제어점은 `keySplines (en-US)` 속성에 정의됩니다.

예제
--

Elements
--------

다음 요소에서 calcMode 속성을 사용할 수 있습니다.

* `<animate>` (en-US)
* `<animateColor>` (en-US)
* `<animateMotion>` (en-US)
* `<animateTransform>` (en-US)


viewBox - SVG: Scalable Vector Graphics

viewBox
=======

« SVG Attribute reference home

`viewBox` 속성은 특수한 container element 에 fit 하기 위한 주어진 graphics stretch 의 set 을 명시한다.

`viewBox` 속성의 값은 whitespace and/or a comma 로 나뉘어진 `min-x`, `min-y`, `width`, `height` 4가지 number list 이다. 이는 주어진 element 에 의해 설정된 viewport 의 bounds 에 맵핑되어야 하는 user space 내의 rectangle 을 명시하며, `preserveAspectRatio (en-US)` 속성과 관계가 있다.

음수로 이루어진 width 또는 height 는 허용되지 않으며 zero 값은 element rendering 이 불가하다.

Usage context
-------------

| Categories | None |
| --- | --- |
| Value | *See above* |
| Animatable | Yes |
| Normative document | SVG 1.1 (2nd Edition) |

Example
-------

Elements
--------

아래 element 들은 `viewBox` 속성을 사용할 수 있다.

* `<svg>` (en-US)
* `<symbol>` (en-US)
* `<image>` (en-US)
* `<marker>` (en-US)
* `<pattern>` (en-US)
* `<view>` (en-US)
See also
--------

* SVG Getting Started: Positions


version - SVG: Scalable Vector Graphics

version
=======

**`version`** 속성은 해당 SVG 문서가 어떤 명세를 따르고 있는지 표시하기 위해 사용됩니다. 이는 오직 <svg> (en-US) 요소 내에서만 사용되며 순전히 사용되는 버전의 알림을 위한 용도로 프로세싱이나 렌더링에는 영향을 미치지 않습니다.

버전을 명시하기 위해 어떤 숫자든지 입력할 수 있지만, 현재로써 유효하게 사용되는 버전은 1.0과 1.1 두 버전만이 유일합니다.

Usage context
-------------

| Categories | None |
| --- | --- |
| Value | <number> |
| Animatable | No |
| Normative document | SVG 1.1 (2nd Edition): version attribute |


cx - SVG: Scalable Vector Graphics

cx
==

**`cx`** 속성은 중심점의 x축 좌표를 정의합니다.

다음 SVG 요소와 함께 이 속성을 사용할 수 있습니다:

* `<circle>`
* `<ellipse>`
* `<radialGradient>` (en-US)
Example
-------
```

html,
body,
svg {
  height: 100%;
}
```

```html
<svg viewBox="0 0 300 100" xmlns="http://www.w3.org/2000/svg">
  <radialGradient cx="25%" id="myGradient">
    <stop offset="0" stop-color="white" />
    <stop offset="100%" stop-color="black" />
  </radialGradient>

  <circle cx="50" cy="50" r="45" />
  <ellipse cx="150" cy="50" rx="45" ry="25" />
  <rect x="205" y="5" width="90" height="90" fill="url(#myGradient)" />
</svg>
```

circle
------

`<circle>` 의 경우, `cx`는 모양 중심의 x축 좌표를 정의합니다.

|  |  |
| --- | --- |
| Value | `<length-percentage>` |
| Default value | `0` |
| Animatable | Yes |

>
> **Note:** SVG2 `cx`로 시작하는 것은 *기하학적 속성* 입니다. 즉, 이 속성은 circle의 CSS 속성으로도 사용할 수 있습니다.
>
>
>

ellipse
-------

`<ellipse>`의 경우, `cx`는 모양 중심의 x축 좌표를 정의합니다.

|  |  |
| --- | --- |
| Value | `<length-percentage>` |
| Default value | `0` |
| Animatable | Yes |

>
> **Note:** SVG2 `cx`로 시작하는 것은 *기하학적 속성* 입니다. 이는 이 속성이 ellipse의 CSS 속성으로도 사용될 수 있음을 의미합니다.
>
>
>

radialGradient
--------------

`<radialGradient>` (en-US)의 경우 `cx`는 radial Gradient에 대한 끝 원의 x축 좌표를 정의합니다.

|  |  |
| --- | --- |
| Value | `<length>` |
| Default value | `50%` |
| Animatable | Yes |

#### 예제
```

html,
body,
svg {
  height: 100%;
}
```

```html
<svg viewBox="0 0 34 10" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <radialGradient cx="0" id="myGradient000">
      <stop offset="0%" stop-color="gold" />
      <stop offset="50%" stop-color="green" />
      <stop offset="100%" stop-color="white" />
    </radialGradient>

    <radialGradient cx="50%" id="myGradient050">
      <stop offset="0%" stop-color="gold" />
      <stop offset="50%" stop-color="green" />
      <stop offset="100%" stop-color="white" />
    </radialGradient>

    <radialGradient cx="100%" id="myGradient100">
      <stop offset="0%" stop-color="gold" />
      <stop offset="50%" stop-color="green" />
      <stop offset="100%" stop-color="white" />
    </radialGradient>
  </defs>

  <rect
 x="1"
 y="1"
 width="8"
 height="8"
 fill="url(#myGradient000)"
 stroke="black" />
  <rect
 x="13"
 y="1"
 width="8"
 height="8"
 fill="url(#myGradient050)"
 stroke="black" />
  <rect
 x="25"
 y="1"
 width="8"
 height="8"
 fill="url(#myGradient100)"
 stroke="black" />
</svg>
```

명세서
---

| Specification |
| --- |
| Scalable Vector Graphics (SVG) 2 # CX |
| Scalable Vector Graphics (SVG) 2 # RadialGradientElementCXAttribute |

같이 보기
-----

* cy (en-US)
* r (en-US)


약한 서명 알고리즘 - 웹 보안

약한 서명 알고리즘
==========

디지털 인증서 서명 (en-US)에 사용되는 해시 알고리즘의 강도는 인증서 보안의 중요한 요소입니다. 이 문서에서는 약한 것으로 알려진 서명 알고리즘에 대한 몇 가지 정보를 제공하므로 적절한 때 이 알고리즘을 피할 수 있습니다.

해시 알고리즘의 약점으로 인해 공격자가 사기성 인증서를 생성하거나 획득할 수 있는 상황이 발생할 수 있습니다. 새로운 공격이 발견되고 사용 가능한 기술이 개선됨에 따라 공격이 보다 실현 가능해지면서 이전 알고리즘의 사용은 권장되지 않으며 이에 대한 지원은 결국 제거됩니다.

SHA-1
-----

SHA-1 인증서는 2017년부터 주요 브라우저 제조업체에서 더 이상 안전한 것으로 취급하지 않습니다. 대신 보다 안전한 해시 알고리즘(예: SHA-256 또는 SHA-512)을 사용하는 인증서를 사용해야 합니다.

MD5
---

MD5 기반 서명에 대한 지원은 2012년 초에 제거되었습니다.

같이 보기
-----

* SHA-1 사용 중단에 대한 Mozilla 보안 블로그 게시물


Firefox 보안 지침 - 웹 보안

Firefox 보안 지침
=============

목적
--

이 문서는 Firefox와 Thunderbird와 같이, 모든 클라이언트 애플리케이션에 일반적으로 적용되는 보안 지침을 간략하게 설명합니다.

안전한 코딩 원칙
---------

애플리케이션이 아래 OWASP 보안 코딩 원칙을 따르는지 확인하십시오.

1. 공격 노출 영역 최소화
2. 보안 기본값 설정
3. 최소 권한의 원칙
4. 심층 방어의 원칙
5. 안전한 실패
6. 서비스를 믿지 마라
7. 보안을 단순하게 유지하라
8. 보안 문제를 올바르게 해결하라
입력 유효성 검사
---------

1. 애플리케이션이 사용자 입력을 받나요?
    1. 사용자 데이터를 받을 때 적정한 최댓값이 적용되는지 확인하기 위해 입력 위치를 샘플링하여 확인하세요.
    2. 애플리케이션이 허용된 문자 집합만 입력받는지 확인하기 위해 입력 위치를 샘플링하여 확인하세요.
    3. 거부 목록 대신 허용 목록을 사용하는지 확인하세요.
2. 애플리케이션이 어떤 방식으로든 사용자의 입력을 화면에 표시하나요?
    1. 응답에서 사용자가 제공했던 콘텐츠가 올바르게 인코딩되었는지 확인하기 위해 입력과 출력 위치를 샘플링하여 확인하세요.
Chrome JS - 위험한 함수
------------------

다음 함수 중 사용하고 있는 것이 있나요?

그렇다면 함수가 안전한지 확인하고 더 나은 대안이 있는지 확인하세요.

| 이름 | 위험 수준 | 문제 | 해결 방법 |
| --- | --- | --- | --- |
| eval | 매우 높음 | JavaScript 파서를 호출하기 때문에, 신뢰할 수 없는 입력과 함께 사용하면 위험합니다. | 가능하다면 항상 eval을 사용하지 마세요. |
| setTimeout(string, time) | 매우 높음 | eval처럼 동작합니다. | setTimeout(function, time, param1, param2, …)을 사용하세요. |

C++ - 위험한 함수
------------

다음 함수 중 사용하고 있는 것이 있나요?

그렇다면 함수가 안전한지 확인하고 더 나은 대안이 있는지 확인하세요.

| 이름 | 위험 수준 | 문제 | 해결 방법 |
| --- | --- | --- | --- |
| gets | 매우 높음 | 경계 검사 없음 | gets를 사욜하지 마세요. 대신 fgets를 사용하세요. |
| strcpy | 매우 높음 | 경계 검사 없음 | strcpy는 소스 문자열이 상수이고, 대상이 이를 수용할 만큼 큰 경우에만 안전합니다. 그렇지 않으면 strncpy를 사용하세요. |
| sprintf | 매우 높음 | 경계 검사 없음, 형식 문자열 공격 | sprintf는 안전하게 사용하기 매우 어렵습니다. 대신 snprintf를 사용하세요. |
| scanf, sscanf | 높음 | 경계 검사가 없을 수 있음, 형식 문자열 공격 | 모든 % 지시어가 해당 인수의 유형과 일치하는지 확인하세요. 경계 검사 없이 '%s' 지시문을 사용하지 마세요. x가 해당 인수의 버퍼 크기인 '%xs'를 사용하세요. 형식 문자열에 신뢰할 수 없고 검증되지 않은 데이터를 사용하지 마세요. |
| strcat | 높음 | 경계 검사 없음 | 입력 크기가 잘 알려져 있지 않고, 고정되어 있지 않으면 strncat를 대신 사용하세요. |
| printf, fprintf, snprintf, vfprintf, vsprintf, syslog | 높음 | 형식 문자열 공격 | 형식 문자열에 신뢰할 수 없고 검증되지 않은 데이터를 사용하지 마세요. 형식 문자열이 웹 콘텐츠나 사용자 입력의 영향을 받을 수 있는 경우, 이러한 함수를 호출하기 전에 % 지시문의 적절한 수와 유형을 확인하세요. 대상 크기 인수가 올바른지 확인하세요. |
| strncpy, fgets, strncat | 낮음 | null 종료가 없을 수 있음 | 항상 대상 버퍼를 null 통해 명시적으로 종료하세요. 크기 인수가 올바른지 확인하세요. null 문자를 추가할 공간을 대상 버퍼에 남겨두세요! |

URL
---

1. 애플리케이션이 신뢰할 수 없는 데이터를 사용하여 URL을 구성하나요?
    * 이런 데이터는 사용하기 전에 불필요한 부분은 적절히 삭제하고, 인코딩하세요.
    * 사용하거나 저장하기 전에 이런 URL에서 얻은 데이터를 확인하세요.
2. 애플리케이션이 리다이렉션을 따르나요?
    * 원본 요청 URI뿐만 아니라 리다이렉션에 대해서도 보안 검사가 수행되는지 확인하세요.
보안 제어
-----

1. 애플리케이션이 적절한 권한 검사를 구현하나요?
    * API가 사용 가능한 곳에서 사용 되는지 확인하세요. (예: shouldload, 등)
    * 애플리케이션이 안전하게 실패하는지 확인하세요.
원격 시스템 접근
---------

1. 애플리케이션이 원격 시스템에 접근하나요?

* TLS를 사용하지 않을 타당한 이유가 없는 한 TLS를 사용하세요.
* 사용자 동의 없이 사용자 정보가 전송되지 않도록 하세요.
정보 저장
-----

1. 파일 저장소
    1. 애플리케이션은 생성된 모든 파일이 허용된 경로에 있는지 확인해야 합니다.
    2. 파일 이름이 신뢰할 수 없는 데이터로 만들어지나요?
        * 데이터가 적절하게 인코딩되었는지 확인하세요.
    3. 파일이 허용 가능한 유형인지 확인하세요.
    4. 파일은 어느 정도의 크기 제한을 초과할 수 없습니다.
2. 데이터베이스 저장소
    1. 데이터베이스로 전송된 신뢰할 수 없는 정보가 적절하게 삭제되었는지 확인하세요.
    2. 가능하다면 주입 공격을 방지하기 위해 타입 안전 매개변수화를 사용하세요.
3. 민감한 정보
    1. 보안에 민감한 정보나 개인 정보가 적절하게 보호되는지 확인하세요(암호화 구획 참조).
    2. 자격 증명(비밀번호 등)은 특별히 주의를 기울여야 합니다. 이러한 유형의 정보로 작업할 때 무엇을 해야 할지 확실하지 않다면, 누군가에게 물어볼 가치가 충분히 있습니다.
4. 로그
    1. 위의 규칙은 일반적인 애플리케이션 데이터뿐만 아니라 로그에도 적용된다는 점을 잊지 마세요.
암호화
---

1. 애플리케이션이 암호화를 사용하나요?
2. 사용된 알고리즘은 인정된 표준인가요?
서비스 거부
------

1. 애플리케이션이 아래 항목에 대한 고갈을 보호하는지 확인하세요.
    1. 시스템 메모리
    2. 저장소
보안 경고
-----

1. 애플리케이션이 사용자에게 보안 경고를 표시하나요?
2. 명확하게 이해할 수 있고 적절한 경고인가요?
3. 신뢰할 수 없는 데이터가 사용자에게 보내지는 메시지의 의미를 바꿀 수 있나요?
    * 사용자 입력이 메시지의 의미를 변경할 수 있나요?
    * 사용자 입력이 시스템 메시지를 화면에서 강제로 표시되지 않도록 할 수 있나요?
    * 사용자 입력에 메시지의 의미를 변경할 수 있는 특수 문자가 포함될 수 있나요? (예: 쓰기를 오른쪽에서 왼쪽으로 재설정하는 유니코드 U+202E)
4. 공격자가 대화 상자의 타이밍을 이용하여 사용자가 의도하지 않은 항목을 클릭하도록 속일 수 있습니까?
정보 공개
-----

1. 애플리케이션이 사용자를 위험에 빠뜨리게할 수 있는 정보를 공개하나요?
2. 애플리케이션이 공개할 필요가 없는 정보를 공개하나요?
3. 애플리케이션이 사용자를 놀라게 하거나 화나게 할 수 있는 내용을 공개하나요?
프런트엔드
-----

1. XUL과 HTML UI 요소를 생성하는 데 안전한 메커니즘이 사용되나요?
    * 예를 들어, innerHTML이나 이와 유사한 기능 대신 createTextNode를 사용하세요.
2. 애플리케이션이 자체 docshell(탭, iframe)을 생성하나요?
    * docshell의 유형을 명시적으로 나타내는지 확인하세요. 예: iframe.setAttribute("type", "content")
참고서
---

* 웹 보안 검증
* Mozilla 보안 컴토와 모범 사례
* Mozilla와 확장 프로그램 개발자를 위한 보안 팁
* OWASP Secure Coding Practices - 빠른 참고 안내서


안전하지 않은 비밀번호 - 웹 보안

안전하지 않은 비밀번호
============

HTTP를 통한 로그인 양식은 특히 사용자의 비밀번호를 추출하는데 사용할 수 있는 다양한 종류의 공격으로 인해 위험합니다. 네트워크 도청자는 네트워크를 스니핑하거나 전송되는 페이지를 수정하여 사용자의 비밀번호를 훔칠 수 있습니다.

HTTPS 프로토콜은 네트워크에서 도청(기밀성)과 수정(무결성)으로부터 사용자 데이터를 보호하도록 설계되었습니다. 사용자 데이터를 처리하는 웹사이트는 HTTPS를 사용하여 공격자로부터 사용자를 보호해야 합니다. 웹사이트에서 HTTPS 대신 HTTP를 사용하는 경우 사용자 정보(예: 로그인 자격 증명)를 도용하는 것은 간단합니다. 이것은 Firesheep에 의해 유명하게 입증되었습니다.

이 문제를 해결하려면 서버에 SSL/TLS 인증서를 설치하고 구성하세요. 무료 및 유료 인증서를 제공하는 다양한 공급 업체가 있습니다. 클라우드 플랫폼을 사용하는 경우 HTTPS를 사용하는 고유한 방법이 있을 수 있습니다.

비밀번호 재사용에 대한 참고 사항
------------------

가끔 웹사이트는 사용자 이름과 암호를 요구하지만 실제로는 매우 민감한 데이터를 저장하지 않습니다. 예를 들어 뉴스 사이트는 사용자가 다시 읽고 싶은 뉴스 기사가 무엇인지 저장할 수 있겠지만, 사용자에 대한 다른 데이터는 저장하지 않을 수 있습니다. 뉴스 사이트의 웹 개발자는 사이트와 사용자 자격 증명을 보호하려는 의욕이 덜할 수 있습니다.

불행하게도 비밀번호 재사용은 큰 문제입니다. 사용자는 여러 사이트(뉴스 웹사이트, 소셜 네트워크, 이메일 제공업체, 은행)에서 같은 비밀번호를 사용합니다. 따라서 사이트가 사용자의 이름과 암호에 대해 접근하는 것이 큰 위험으로 보이지 않지만, 같은 이름과 암호를 사용하여 은행 계좌에 로그인한 사용자에게는 큰 위험이 됩니다. 공격자는 점점 더 똑똑해지고 있습니다. 한 사이트에서 사용자 이름/암호 쌍을 도용한 다음 더 수익성이 좋은 사이트에서 재사용하려고 합니다.

같이 보기
-----

* No More Passwords over HTTP, Please! — 더 많은 정보가 포함된 자세한 블로그 게시물, 그리고 FAQ.


동일 출처 정책 - 웹 보안

동일 출처 정책
========

**동일 출처 정책**은 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호 작용할 수 있는 방법을 제한하는 중요한 보안 메커니즘입니다.

잠재적 악성 문서를 격리하여 가능한 공격 벡터를 줄이는 데 도움이 됩니다. 예를 들어 인터넷의 악의적인 웹사이트가 브라우저에서 JS를 실행하여 (사용자가 로그인 한) 타사 웹메일 서비스나 회사 인트라넷(공용 IP 주소가 없어 공격자의 직접적인 접근으로부터 보호)에서 데이터를 읽고 공격자에게 전달하는 것을 방지합니다.

출처 정의
-----

프로토콜, 포트(명시된 경우), 그리고 호스트가 같은 경우 두 URL은 동일한 출처를 가집니다. 이것을 "스키마/호스트/포트 튜플" 또는 그냥 "튜플"로 참조되는 것을 볼 수도 있을겁니다. ("튜플"은 함께 전체를 구성하는 항목 집합입니다. 이중/삼중/사중/오중 등의 일반적인 형식입니다.)

아래 표는 URL `http://store.company.com/dir/page.html`의 출처를 비교한 예시입니다.

 | URL | 결과 | 이유 |
 | ------------------------------------------------- | --------- | ------------------------------------------- | --- |
 | `http://store.company.com/dir2/other.html` | 동일 출처 | 경로만 다름 |
 | `http://store.company.com/dir/inner/another.html` | 동일 출처 | 경로만 다름 |
 | `https://store.company.com/page.html` | 실패 | 다른 프로토콜 |
 | `http://store.company.com:81/dir/page.html` | 실패 | 다른 포트 (`http://` 는 기본적으로 80 포트) |
 | `http://news.company.com/dir/page.html` | 실패 | 다른 호스트 | |

### 출처 상속

`about:blank` 또는 `javascript:` URL이 있는 페이지에서 실행된 스크립트는 해당 URL이 포함된 문서의 출처를 상속합니다. 이러한 유형의 URL에는 원본 서버에 대한 정보가 포함되어 있지 않기 때문입니다.

예를 들어 `about:blank`는 부모 스크립트가 내용을 작성하는(예: `Window.open()` (en-US) 메커니즘을 통해) 비어 있는 새 팝업 창의 URL로 자주 사용됩니다. 이 팝업에도 JavaScript가 포함되어 있다면 해당 스크립트는 팝업을 생성한 스크립트와 같은 출처를 상속합니다.

`data:` URL은 새로운 빈 보안 컨텍스트를 받습니다.

### 파일 출처

 최신 브라우저는 일반적으로 `file:///` 스키마를 사용하여 로드된 파일의 출처를 불투명한 출처로 취급합니다.
 이는 파일에 동일한 폴더(예시로)에 있는 다른 파일이 포함된 경우, 같은 출처에서 온 것으로 간주되지 않으며 CORS 오류가 발생할 수 있다는 것을 뜻합니다.

URL 사양에 따르면 파일의 출처는 구현에 따라 다르며 일부 브라우저는 보안에 영향을 미치더라도 같은 디렉토리 또는 하위 디렉토리에 있는 파일을 동일한 출처로 취급할 수 있습니다.

출처 변경
-----

**경고:** 여기에 설명된 접근 방식(`document.domain` setter 사용)은 동일 출처 정책에서 제공하는 보안 보호를 약화시키고 브라우저의 출처 모델을 복잡하게 하여 상호 운용성 문제와 보안 버그로 이어지기 때문에 더 이상 권장되지 않습니다.

페이지는 일부 제한 사항과 함께 자신의 출처를 변경할 수 있습니다. 스크립트는 `document.domain`의 값을 현재 도메인 또는 현재 도메인의 상위 도메인으로 설정할 수 있습니다. 현재 도메인의 상위 도메인으로 설정하면 더 짧은 상위 도메인이 동일 출처 검사에 사용됩니다.

예를 들어 `http://store.company.com/dir/other.html`에 있는 문서의 스크립트가 다음을 실행한다고 가정해보겠습니다.

```js
document.domain = "company.com";
```

그런 다음, 페이지는 `http://company.com/dir/page.html`과의 동일 출처 검사를 통과할 수 있습니다. (`http://company.com/dir/page.html` 이를 표시하기 위해 `document.domain`을 `"company.com"`으로 설정한다고 가정합니다. 자세한 내용은 `document.domain`을 참조하십시오.) 그러나 `othercompany.com`은 `company.com`의 상위 도메인이 아니므로 `company.com`에서 `document.domain`을 `othercompany.com`으로 설정할 수 **없습니다**.

포트 번호는 브라우저에서 별도로 확인합니다. `document.domain = document.domain`을 포함하여 어떤 방식으로든 `document.domain`을 호출하면 포트 번호가 `null`로 덮어쓰입니다. 따라서 처음 대상에만 `document.domain = "company.com"`을 설정하면 `company.com:8080`은 `company.com`과 통신할 수 없습니다. 포트 번호가 모두 `null`이 되도록 둘 다 설정해 줘야 합니다.

이 메커니즘에는 몇 가지 제한 사항이 있습니다. 예를 들어 `document-domain` (en-US) `Permissions-Policy` (en-US)가 활성화되었거나, 문서가 샌드박스된 `<iframe>` (en-US)에 있는 경우 "`SecurityError`" `DOMException` (en-US)이 발생하며, 이러한 방식으로 출처를 변경하더라도 많은 Web API에서 사용되는 출처 확인에는 영향을 미치지 않습니다. (예: `localStorage`, `indexedDB`, `BroadcastChannel`, `SharedWorker`). 실패 사례의 전체 목록은 Document.domain > Failures에서 찾을 수 있습니다.

**참고:** 하위 도메인이 상위 도메인에 액세스하도록 허용하기 위해 `document.domain`을 사용하는 경우 상위 도메인과 하위 도메인 모두에서 `document.domain`을 같은 값으로 설정해야 합니다. 이는 상위 도메인을 원래 값으로 다시 설정하는 경우에도 필요합니다. 이렇게 하지 않으면 권한 오류가 발생할 수 있습니다.

교차 출처 네트워크 접근
-------------

동일 출처 정책은 `XMLHttpRequest`이나 `<img>` 요소를 사용하는 경우와 같이 서로 다른 두 출처 간의 상호 작용을 제어합니다. 이러한 상호 작용은 일반적으로 세 가지 범주로 분류됩니다.

* 교차 출처 쓰기는 보통 허용합니다. 예시로는 링크, 리다이렉트, 그리고 양식 제출 등이 있습니다. 일부 HTTP 요청은 프리플라이트를 요구합니다.
* 교차 출처 삽입은 보통 허용합니다. (예시는 아래에 있습니다.)
* 교차 출처 읽기는 보통 허용하지 않지만, 종종 교차 출처 삽입 과정에서 읽기 권한이 누출됩니다. 예를 들어 삽입된 이미지의 크기, 삽입된 스크립트의 작업, 또는 삽입된 리소스의 가용성을 읽을 수 있습니다.

다음은 교차 출처로 삽입할 수 있는 리소스의 일부 예시입니다.

* `<script src="…"></script>`를 사용하는 JavaScript. 구문 오류에 대한 오류 세부 정보는 동일 출처 스크립트에서만 사용할 수 있습니다.
* `<link rel="stylesheet" href="…">`로 적용된 CSS. CSS의 완화된 구문 규칙으로 인해 교차 출처 CSS에는 올바른 `Content-Type` 헤더가 요구됩니다. 브라우저는 MIME 유형이 올바르지 않고 리소스가 유효한 CSS 구성으로 시작하지 않는 교차 출처 로드인 경우 스타일시트 로드를 차단합니다.
* `<img>`로 표시하는 이미지.
* `<video>`와 `<audio>` (en-US)로 재생하는 미디어.
* `<object>`와 `<embed>`로 삽입하는 외부 리소스.
* `@font-face`로 적용하는 글꼴. 일부 브라우저는 교차 충처를 허용하지만, 다른 브라우드는 동일 출처를 요구할 수도 있습니다.
* `<iframe>` (en-US)으로 삽입하는 모든 것. 사이트는 `X-Frame-Options` 헤더를 사용하여 출처 간 프레이밍을 방지할 수 있습니다.
### 교차 출처 접근을 허용하는 방법

CORS를 사용하여 교차 출처의 접근를 허용합니다. CORS는 서버가 브라우저에 콘텐츠 로드를 허용하는 다른 호스트를 지정할 수 있도록 하는 HTTP의 일부입니다.

### 교차 출처 접근을 막는 방법

* 교차 출처 쓰기를 방지하려면 CSRF(Cross-Site Request Forgery) 토큰이라고 하는 요청에서 추측할 수 없는 토큰을 확인하십시오. 이 토큰이 필요한 페이지의 교차 출처 읽기를 막아야 합니다.
* 리소스의 교차 출처 읽기를 방지하려면 리로스를 삽입 할 수 없도록 설정하세요. 리소스 삽입 과정에서 일부 정보가 새어 나가므로 삽입을 방지하는 경우가 많습니다.
* 교차 출처 삽입을 방지하려면 리소스가 앞서 나열된 삽입 가능 형식 중 하나로 해석되지 않도록 해야 합니다. 브라우저는 `Content-Type` 헤더를 준수하지 않을 수 있습니다. 예를 들어 HTML 문서에서 `<script>` 태그를 가리키면 브라우저는 HTML을 JavaScript로 파싱려고합니다. 리소스가 사이트의 진입점이 아닌 경우 CSRF 토큰을 사용하여 삽입을 방지할 수도 있습니다.
교차 출처 스크립트 API 접근
-----------------

`iframe.contentWindow` (en-US), `window.parent` (en-US), `window.open` (en-US), 그리고 `window.opener`와 같은 JavaScript API를 사용하면 문서가 서로를 직접 참조할 수 있습니다. 두 문서의 원본이 동일하지 않은 경우 이러한 참조는 다음 두 섹션에서 설명하는 것처럼 `Window`와 `Location` 객체에 대해 매우 제한된 액세스를 제공합니다.

서로 다른 출처의 문서간 통신을 하려면 `window.postMessage`를 사용하세요.

명세: HTML Living Standard § Cross-origin objects.

### Window

다음 `Window` 속성에 대한 교차 출처 접근이 허용됩니다.

| 메서드 |
| --- |
| `window.blur` (en-US) |
| `window.close` (en-US) |
| `window.focus` (en-US) |
| `window.postMessage` |

| 속성 |  |
| --- | --- |
| `window.closed` | 읽기 전용. |
| `window.frames` (en-US) | 읽기 전용. |
| `window.length` | 읽기 전용. |
| `window.location` (en-US) | 읽기/쓰기. |
| `window.opener` | 읽기 전용. |
| `window.parent` (en-US) | 읽기 전용. |
| `window.self` | 읽기 전용. |
| `window.top` (en-US) | 읽기 전용. |
| `window.window` (en-US) | 읽기 전용. |

일부 브라우저는 위의 항목보다 더 많은 접근을 허용할 수도 있습니다.

### Location

다음 `Location` 속성에 대한 교차 출처 접근이 허용됩니다.

| 메서드 |
| --- |
| `location.replace` |

| 속성 |  |
| --- | --- |
| `location.href` (en-US) | 쓰기 전용. |

일부 브라우저는 위의 항목보다 더 많은 접근을 허용할 수도 있습니다.

교차 출처 데이터 저장소 접근
----------------

Web Storage와 IndexedDB와 같은 브라우저에 저장된 데이터에 대한 액세스는 출처별로 구분됩니다. 각 출처는 별도의 저장소를 가지며 한 출처의 JavaScript는 다른 출처에 속한 저장소에서 읽거나 쓸 수 없습니다.

쿠키는 출처에 대한 별도의 정의를 사용합니다. 페이지는 상위 도메인이 공개 접미사가 아닌 한 자체 도메인 또는 상위 도메인에 대한 쿠키를 설정할 수 있습니다. Firefox와 Chrome은 공개 접미사 목록을 사용하여 도메인이 공개 접미사인지 확인합니다. 쿠키를 설정할 때 `Domain`, `Path`, `Secure`, 그리고 `HttpOnly` 플래그를 사용하여 가용성을 제한할 수 있습니다. 쿠키를 읽을 때 쿠키가 어디에서 설정되었는지 알 수 없습니다. 안전한 https 연결만 사용하더라도 보이는 모든 쿠키는 안전하지 않은 연결을 사용하여 설정되었을 수 있습니다.

같이 보기
-----

* W3C의 Same-Origin Policy
* web.dev의 Same-origin policy
* `Cross-Origin-Resource-Policy`
* `Cross-Origin-Embedder-Policy`


혼합 콘텐츠 - 웹 보안

혼합 콘텐츠
======

사용자가 HTTPS를 통해 제공되는 페이지를 방문하면, 웹 서버와의 연결이 TLS로 암호화되므로 대부분의 스니퍼와 중간자 공격으로부터 보호됩니다. 일반 텍스트 HTTP를 사용하여 가져온 콘텐츠가 포함된 HTTPS 페이지를 혼합 콘텐츠 페이지라고 합니다. 이러한 페이지는 부분적으로만 암호화되므로 스니퍼와 중간자 공격자가 암호화되지 않은 콘텐츠에 접근할 수 있습니다. 따라서 페이지는 안전하지 않습니다.

혼합 콘텐츠의 종류
----------

혼합 콘텐츠에는 **혼합 패시브/디스플레이 콘텐츠**와 **혼합 액티브 콘텐츠**의 두 가지 범주가 있습니다. 둘의 차이점은 중간자 공격의 일환으로 콘텐츠가 재작성된 경우, 최악의 시나리오의 위협 수준에 있습니다. 패시브 콘텐츠의 위협은 더 낮습니다(페이지에 오해의 소지가 있는 콘텐츠가 포함되어 있거나 사용자의 쿠키가 도난당할 수 있음). 액티브 콘텐츠의 경우, 피싱, 민감한 데이터 공개, 악성 사이트로의 리디렉션 등의 위험이 발생할 수 있습니다.

### 혼합 패시브/디스플레이 콘텐츠

혼합 패시브/디스플레이 콘텐츠는 HTTPS 웹페이지에 포함되지만, 웹페이지의 다른 부분은 변경할 수 없는 HTTP를 통해 제공되는 콘텐츠입니다. 예를 들어, 공격자는 HTTP를 통해 제공되는 이미지를 부적절한 이미지나 메시지로 대체하여 사용자에게 보낼 수 있습니다. 또한 공격자는 사용자에게 어떤 이미지가 제공되는지 관찰하여 사용자의 활동에 대한 정보를 유추할 수도 있습니다. 이미지가 웹사이트 내의 특정 페이지에만 사용되는 경우가 많습니다. 공격자가 특정 이미지에 대한 HTTP 요청을 관찰하면 사용자가 어떤 웹 페이지를 방문하고 있는지 파악할 수 있습니다.

#### 패시브 콘텐츠 목록

이 구획은 패시브 콘텐츠로 간주되는 모든 유형의 HTTP 요청을 나열합니다.

* `<img>` (`src` 속성)
* `<audio>` (en-US) (`src` 속성)
* `<video>` (`src` 속성)
* `<object>` 하위 리소스 (`<object>`가 HTTP 요청을 수행하는 경우)
### 혼합 액티브 콘텐츠

**혼합 액티브 콘텐츠**는 HTTPS 페이지의 문서 객체 모델 전체 또는 일부에 접근할 수 있는 콘텐츠입니다. 이러한 유형의 혼합 콘텐츠는 HTTPS 페이지의 동작을 변경하고 잠재적으로 사용자의 민감한 데이터를 탈취할 수 있습니다. 따라서 위의 혼합 디스플레이 콘텐츠에 대해 설명한 위험 외에도 혼합 액티브 콘텐츠는 몇 가지 다른 공격 벡터에 대해 취약합니다.

혼합 액티브 콘텐츠의 경우, 중간자 공격자가 HTTP 콘텐츠에 대한 요청을 가로챌 수 있습니다. 또한 공격자는 악성 JavaScript 코드를 포함하도록 응답을 재작성할 수도 있습니다. 악성 액티브 콘텐츠는 사용자의 자격 증명을 훔치거나, 사용자의 민감한 데이터를 획득하거나, 브라우저 또는 플러그인의 취약점을 활용하여 사용자 시스템에 멀웨어 설치를 시도할 수 있습니다(예: 브라우저 또는 플러그인의 취약점 활용).

혼합 콘텐츠와 관련된 위험은 사용자가 방문하는 웹사이트의 유형과 해당 사이트에 노출된 데이터가 얼마나 민감한지에 따라 달라집니다. 웹페이지에는 온 세상이 볼 수 있는 공개 데이터가 있거나 인증된 경우에만 볼 수 있는 비공개 데이터가 있을 수 있습니다. 웹페이지가 공개되어 있고 사용자에 대한 민감한 데이터가 없는 경우라도, 혼합 액티브 콘텐츠를 사용하면 공격자가 사용자를 다른 HTTP 페이지로 리디렉션하고 해당 사이트에서 HTTP 쿠키를 훔칠 수 있습니다.

#### 활성 콘텐츠 예시

이 구획은 액티브 콘텐츠로 간주되는 몇 가지 유형의 HTTP 요청을 나열합니다.

* `<script>` (`src` 속성)
* `<link>` (`href` 속성) (CSS 스타일 시트 포함)
* `<iframe>` (en-US) (`src` 속성)
* `XMLHttpRequest` 요청
* `fetch()` 요청
* `url()` 값이 사용되는 CSS의 모든 경우(`@font-face`, `cursor`, `background-image` 등).
* `<object>` (`data` 속성)
* `Navigator.sendBeacon` (`url` 속성)

웹 글꼴과 워커와 같은 다른 리소스 유형은 Chrome에서와 마찬가지로 액티브 혼합 콘텐츠로 간주될 수 있습니다.

혼합 콘텐츠 불러오기
-----------

대부분의 브라우저는 혼합 액티브 콘텐츠를 불러오는 것을 막으며, 일부 브라우저는 혼합 디스플레이 콘텐츠도 차단합니다.

### 로컬에서 전달된 혼합 리소스 불러오기

브라우저는 로컬에서 전달된 혼합 리소스를 불러오는 것을 허용할 수 있습니다. 여기에는 루프백 주소(예: `http://127.0.0.1/`)에서 접근되는 `file:` URL과 콘텐츠가 포함됩니다.

* Firefox 55 이상에서는 루프백 주소 `http://127.0.0.1/`에서 혼합 콘텐츠를 불러오는 것을 허용합니다. (Firefox bug 903966 참고)
* Firefox 84 이상에서는 이제 루프백 주소에 매핑된 `http://localhost/`와 `http://*.localhost/` URL에서 혼합 콘텐츠를 불러올 수 있습니다. (Firefox bug 1220810 참고)
* Chrome도 `http://127.0.0.1/`과 `http://localhost/`의 혼합 콘텐츠를 허용합니다.
* Safari는 혼합 콘텐츠를 허용하지 않습니다.
### 혼합 디스플레이 리소스 업그레이드

브라우저는 보안 페이지에서 디스플레이/미디어 콘텐츠 요청을 HTTP에서 HTTPS로 자동 업그레이드하는 기능을 지원할 수 있습니다(일부 콘텐츠는 안전하게 로드되는 반면 다른 콘텐츠는 안전하지 않게 로드되는 혼합 콘텐츠 상태를 막습니다).

Firefox는 이 기능을 실험적인 기능으로 지원합니다. `security.mixed_content.upgrade_display_content` 설정을 사용하여 활성화할 수 있습니다.

* 업그레이드에 실패하면(미디어의 호스트가 HTTPS를 지원하지 않아서) 미디어가 로드되지 않습니다.
* 콘텐츠가 성공적으로 업그레이드되면 콘솔 경고가 표시됩니다.
* 자세한 내용은 Firefox의 실험적 기능 > 혼합 표시 콘텐츠 업그레이드 (en-US)를 참조하세요.
Firefox 웹 콘솔의 경고
----------------

웹사이트의 페이지에 이 문제가 있는 경우 Firefox 웹 콘솔은 Net 패널에 혼합 콘텐츠 경고 메시지를 표시합니다. HTTP를 통해 불러온 혼합 콘텐츠 리소스는 "mixed content"라는 텍스트와 함께 해당 콘텐츠 페이지로 연결되는 빨간색 링크가 표시됩니다.

![혼합 콘텐츠 경고를 표시하는 웹 콘솔의 스크린샷입니다.](/ko/docs/Web/Security/Mixed_content/mixed_content_-_net_pane.png)

웹 콘솔에서 이러한 경고를 찾을 수 있을 뿐만 아니라, 콘텐츠 보안 정책(CSP)을 사용하여 문제를 보고할 수도 있습니다. 웹사이트를 재귀적으로 검사하여 안전하지 않은 콘텐츠의 링크를 찾아주는 SSL-check나 Missing Padlock과 같은 온라인 크롤러를 사용할 수도 있습니다.

Firefox 23부터 혼합 액티브 콘텐츠는 기본적으로 차단됩니다(환경설정을 통해 혼합 디스플레이 콘텐츠도 차단할 수 있음). 웹 개발자가 혼합 콘텐츠 오류를 쉽게 찾을 수 있도록 차단된 모든 혼합 콘텐츠 요청은 아래와 같이 웹 콘솔의 보안 창에 기록됩니다.

![웹 콘솔의 보안 창의 차단된 혼합 콘텐츠 오류 스크린샷](/ko/docs/Web/Security/Mixed_content/mixed_content_webconsole.png)

이 유형의 오류를 해결하려면, HTTP 콘텐츠에 대한 모든 요청을 제거하고 HTTPS를 통해 제공되는 콘텐츠로 대체해야 합니다. 몇 가지 일반적인 혼합 콘텐츠의 예로는 JavaScript 파일, 스타일 시트, 이미지, 동영상, 기타 미디어 등이 있습니다.

**참고:** 콘솔에는 혼합 표시 콘텐츠가 성공적으로 HTTP에서 HTTPS로 업그레이드되고 있는지 여부를 나타내는 메시지가 표시됩니다("Loading mixed (insecure) display content"이라는 경고 대신).

같이 보기
-----

* 혼합 콘텐츠 - W3C Editor's Draft
* 혼합 콘텐츠가 있는 웹사이트를 고치는 방법


인증서 투명성 - 웹 보안

인증서 투명성
=======

**인증서 투명성**은 잘못된 인증서 발급을 방지하고 모니터링하도록 설계된 개방형 프레임워크로, RFC 9162에 정의되어 있습니다. 인증서 투명성을 통해 새로 발급된 인증서는 공개적으로 실행되고, 종종 독립적인 **CT 로그**에 '로그'됩니다. 이 로그는 발급된 TLS 인증서의 추가 전용 암호화 보증 레코드를 유지합니다.

이러한 방식으로 인증 기관(CA)은 훨씬 더 많은 공개 조사와 감독을 받을 수 있습니다. CA/B 포럼 **기본 요구 사항**을 위반하는 것과 같은 잠재적으로 악의적 사항이 있는 인증서를 훨씬 더 빠르게 감지하고 해지시킬 수 있습니다. 또한 브라우저 벤더와 루트 저장소 관리자는 그들이 불신하기로 결정할 수 있는 문제가 있는 CA에 대해 더 많은 정보에 입각한 결정을 내릴 수 있습니다.

배경
--

CT 로그는 **Merkle 트리** 데이터 구조를 기반으로 구축됩니다. 노드는 하위 노드의 **암호화 해시**로 레이블되고, 리프 노드에는 실제 데이터 조각의 해시가 포함됩니다. 따라서 루트 노드의 레이블은 트리의 다른 모든 노드에 따라 달라집니다.

인증서 투명성의 맥락에서 리프 노드에 의해 해시된 데이터는 오늘날 운영되는 다양한 CA에서 발급된 인증서입니다. 인증서 포함은 O(log n) 시간 복잡도로 효율적으로 생성되고 검증할 수 있는 **감사 증명**을 통해 검증될 수 있습니다.

인증서 투명성은 CA 침해(2011년 DigiNotar 위반), 의심스러운 결정안(2012년 Trustwave 하위 루트 사건) 및 기술적 발급 문제(말레이시아의 Digicert Sdn Bhd에 의한 512비트 취약 인증서 발급)를 배경으로 2013년에 시작되었습니다.

구현
--

인증서가 CT 로그에 제출되면 **서명된 인증서 타임스탬프**(SCT)가 생성되어 반환됩니다. 이는 인증서가 제출되었고 로그에 추가된다는 증거로 사용됩니다.

명세서에는 호환 서버가 연결할 때 **반드시** TLS 클라이언트에 이러한 다수의 SCT를 제공해야 한다고 명시되어 있습니다. 이는 다음과 같은 다양한 메커니즘을 통해 수행될 수 있습니다.

* 서명된 인증서 타임스탬프를 리프 인증서에 직접 포함하는 X.509v3 인증서 확장
* 핸드셰이크 중에 전송된 `signed_certificate_timestamp` 유형의 TLS 확장
* OCSP 스테이플링(즉, `status_request` TLS 확장) 및 하나 이상의 SCT로 `SignedCertificateTimestampList` 제공

X.509 인증서 확장을 사용하면 포함된 SCT가 발급 CA에 의해 결정됩니다. 2021년 6월부터 가장 활발하게 사용되고 공개적으로 신뢰할 수 있는 인증서에는 이 확장에 포함된 투명성 데이터가 포함되어 있습니다. 이 방법은 웹 서버를 수정할 필요가 없는 방법입니다.

후자의 방법을 사용하는 경우 필요한 데이터를 전송하려면 서버를 업데이트해야 합니다. 이 벙법의 장점은 서버 운영자가 TLS 확장/스테이플링된 OCSP 응답을 통해 전송된 SCT를 제공하는 CT 로그 소스를 사용자 정의할 수 있다는 것입니다.

브라우저 요구 사항
----------

Google Chrome은 notBefore 날짜가 2018년 4월 30일 이후인 모든 인증서 대해 CT 로그 포함을 요구합니다. 사용자는 비호환 TLS 인증서를 사용하여 사이트를 방문할 수 없습니다. 이전에 Chrome은 *Extended Validation* (EV)와 Symantec 발급 인증서에 CT 포함을 요구했었습니다.

Apple은 Safari 및 기타 서버가 서버 인증서를 신뢰하기 위해 여러개의 SCT를 요구합니다.

Firefox는 현재 사용자가 방문하는 사이트에 대해 CT 로그 사용을 확인하거나 요구하지 않습니다.


Referer 헤더: 개인 정보 보호 및 보안 문제 - 웹 보안

Referer 헤더: 개인 정보 보호 및 보안 문제
============================

Referer HTTP 헤더와 관련된 개인 정보 및 보안 위험이 있습니다. 이 문서는 이런 위험에 대해 설명하고, 이를 완화하는 방법에 대한 조언을 제공합니다.

리퍼러 문제
------

`Referer` (철자 주의) 헤더에는 요청 주소가 들어있습니다(예를 들어, 현재 요청된 페이지의 링크로 이어진 이전 웹 페이지의 주소, 이미지나 기타 리소스를 로드하는 페이지의 주소). 이는 분석, 로깅, 최적화된 캐싱을 포함하여 악의 없는 용도로 많이 사용됩니다. 하지만, 정보를 추적하거나 훔치는 것과 같이 문제가 있는 용도가 더 많이 쓰이고, 실수로 민감한 정보를 유출하는 것과 같은 부작용도 있습니다.

예를 들어, "비밀번호 재설정" 페이지 푸터에 소셜 미디어 링크가 있다고 생각해 보겠습니다. 링크를 따라갔다면, 정보가 어떻게 공유됐는지에 따라 소셜 미디어 사이트는 암호 재설정 URL을 받을 수도 있고, 공유된 정보를 계속 사용할 수 있으므로 잠재적으로 사용자 보안이 침해될 수 있습니다.

같은 논리로, 페이지에 포함된 타사 사이트의 이미지로 인해 민감한 정보가 타사에 유출될 수 있습니다. 보안이 침해되지 않더라도, 이런 정보는 사용자가 공유하길 원하지 않을 수 있습니다.

어떻게 해결할 수 있을까요?
---------------

이러한 위험의 대부분은 애플리케이션의 현명한 설계로 완화할 수 있습니다. 현명한 애플리케이션은 일회용 비밀번호 재설정 URL을 만들거나 이를 고유한 사용자 토큰과 결합하여 위험을 제거합니다. 민감한 데이터를 보다 안전한 방식으로 전송함으로써 위험을 줄일 수도 있습니다.

URL을 통해 민감한 데이터를 다른 위치로 전달하지 않기 위해선 가능한한 `GET` 대신 `POST`를 사용해야 합니다.

항상 HTTPS 사이트를 사용해야 합니다. HTTPS 사이트는 HTTPS가 아닌 사이트에 리퍼러 정보를 전송하지 않는다는 사실을 포함하여 많은 보안 이점이 있습니다. 이 조언은 현재 대부분의 웹이 HTTPS를 사용하고 있기 때문에 관련성이 적지만 여전히 고려할 가치가 있습니다.

또한 비밀번호 재설정 페이지, 결제 양식, 로그인 영역 등과 같은 웹사이트의 보안 영역에서 제3자의 콘텐츠(예: `<iframe>` (en-US)에 포함된 소셜 네트워크 위젯)를 제거하는 것을 고려해야 합니다.

다음을 사용하여 위험을 완화할 수도 있습니다.

* 서버의 `Referrer-Policy` (en-US) 헤더는 `Referer` 헤더를 통해 전송되는 정보를 제어합니다. 예를 들어 `no-referrer` 지시문은 Referer 헤더를 완전히 생략합니다.
* 이러한 정보가 유출될 위험이 있는 HTML 요소(예: `<img>`와 `<a>`)의 `referrerpolicy` 속성입니다. 예를 들어 `Referer` 헤더가 전송되는 것을 중지하도록 `no-referrer`로 설정할 수 있습니다.
* 이러한 정보가 유출될 위험이 있는 HTML 요소(예: `<img>`와 `<a>`)에서 `rel` 속성을 `noreferrer` (en-US)로 설정합니다.
* 전체 문서에 대한 Referer 헤더를 비활성화하기 위해 `referrer`의 name과 콘텐츠가 `no-referrer`으로 설정된 `<meta>` 요소. HTML과 Referrer-Policy 통합 (en-US)을 참조하십시오.
* Exit page 기술.

보안에 민감한 서버 측 프레임워크는 이러한 문제에 대한 완화 기능을 내장하는 경우가 많습니다. 예를 들어 다음과 같습니다.

* Django의 보안(특히 교차 사이트 요청 위조(CSRF) 보호 참조).
* helmetjs referrer-policy — Node.js/Express 앱에서 Referrer-Policy를 설정하기 위한 미들웨어입니다(자세한 보안 규정은 helmetjs 참조).
정책 및 요구 사항
----------

관련 위험을 완화하기 위해 프로젝트 팀에 이러한 기능의 사용을 특정하는 일련의 보안 및 개인 정보 보호 요구 사항을 정하는 것이 좋습니다. 웹 보안 전문가의 도움을 받아 이런 요구 사항을 작성하고, 사용자 요구 사항과 복지는 물론, EU 일반 데이터 보호 규정(GDPR)과 같은 법률에 의해 시행되는 정책과 규정과 같은 기타 문제도 모두 고려해야 합니다.

같이 보기
-----

* Referrer-Policy에 대한 Mozilla 보안 팀 지침


무인증 IFrame - 웹 보안

무인증 IFrame
==========

**실험적:** **이 기능은 실험적인 기능입니다.**
프로덕션 환경에서 사용하기 전에 브라우저 호환성 표를 주의 깊게 확인하세요.

**비표준:** 이 기능은 비표준이므로 실제 프로덕션에서 사용하지 마세요. 모든 사용자 환경에서 작동하지 않을 수 도 있으며, 미래에 호환성 문제가 생길 수 있습니다.

**무인증 IFrame**은 개발자가 새로운 임시 컨텍스트를 사용하여 `<iframe>` (en-US)에서 타사 리소스를 로드할 수 있는 메커니즘을 제공합니다. 이는 일반 원본의 네트워크, 쿠키, 그리고 저장소 데이터에 액세스할 수 없습니다. 최상위 문서의 수명에 대해 새로운 컨텍스트 공간을 사용합니다. 그 결과 `Cross-Origin-Embedder-Policy`(COEP)가 해제될 수 있으므로 COEP가 설정된 문서는 COEP가 설정되지 않은 타사 문서를 포함할 수 있습니다.

문제점
---

다양한 웹 API 기능은 교차 출처 격리를 선택한 사이트에서만 사용할 수 있습니다. 그 예로는 `SharedArrayBuffer`와 고해상도 타이머 (en-US)가 있습니다. 그 이유는 이러한 기능들이 스펙터 공격에 악용되어 사이드 채널을 통해 피해자의 기밀 정보가 유출되고 공격자가 캡처할 수 있는 위험이 있기 때문입니다.

교차 출처 격리를 선택하려면 `same-origin`(공격자로부터 출처를 보호) 값을 갖는 `Cross-Origin-Opener-Policy` (en-US)와 `credentialless`나 `require-corp`(원본으로부터 피해자를 보호) 값을 갖는 `Cross-Origin-Embedder-Policy`를 사용하여 리소스를 제공해야 합니다. 후자는 `Cross-Origin-Resource-Policy` 또는 교차 출처 리소스 공유를 사용하여 문서에 명시적으로 권한을 부여하지 않은 인증된 교차 출처 리소스를 문서에 로드하지 못하도록 합니다.

교차 출처 격리 채택을 제한하는 핵심적인 문제는 `Cross-Origin-Embedder-Policy`가 재귀적으로 적용된다는 사실입니다. 즉, `Cross-Origin-Embedder-Policy`가 설정된 문서에 있는 `<iframe>`에 로드된 모든 타사 콘텐츠도 `Cross-Origin-Embedder-Policy`를 배포해야 콘텐츠를 성공적으로 불러올 수 있습니다. 이는 자신의 앱에 타사 콘텐츠(예: 애드 네트워크 콘텐츠)를 삽입하는 개발자가 일반적으로 이를 제어할 수 없기 때문에 문제가 되는데, 지금까지는 타사 콘텐츠 제공 업체가 `Cross-Origin-Embedder-Policy`를 구현할 때까지 기다리는 것이 유일한 선택지였습니다.

이 문제는 무인증 IFrame으로 해결할 수 있습니다.

해결책 - 무인증 IFrame
----------------

`<iframe>`에 `credentialless` (en-US) 속성을 적용하거나 이에 상응하는 DOM 속성인 `HTMLIFrameElement.credentialless` (en-US)를 `true`로 설정하여 무인증 상태로 만들 수 있습니다.

```html
<iframe
 src="https://en.wikipedia.org/wiki/Spectre\_(security\_vulnerability)"
 title="Spectre vulnerability Wikipedia page"
 width="960"
 height="600"
 credentialless></iframe>
```

또는

```html
<iframe width="960" height="600"> </iframe>
```

```js
const iframeElem = document.querySelector("iframe");

iframeElem.credentialless = true;
iframeElem.title = "Spectre vulnerability Wikipedia page";
iframeElem.src =
  "https://en.wikipedia.org/wiki/Spectre\_(security\_vulnerability)";
```

**참고:** `<iframe>`에 삽입된 문서가 `window.credentialless` (en-US) 속성을 쿼리 하여 무인증 컨텍스트에서 실행되고 있는지 테스트할 수 있습니다. 값이 `true` 이면 삽입된 `<iframe>`이 무인증 상태임을 의미합니다.

그 결과 무인증 `<iframe>` 내부의 문서는 새롭고 임시적인 컨텍스트를 사용하여 로드되며, 이러한 컨텍스트는 출처와 관련된 데이터(예: 쿠키와 localStorage)에 접근할 수 없습니다. 무인증 저장소는 최상위 문서 당 한 번씩 설정되는 nonce("한 번 사용된 번호") 값으로 수정된 저장소 키를 통해 개별적으로 분할됩니다. 따라서 하나의 무인증 `<iframe>`에서 설정된 쿠키는 동일한 최상위 문서 아래에 삽입된 다른 동일 출처의 무인증 `<iframe>`에서만 접근할 수 있습니다.

nonce는 동일한 최상위 문서의 하위 문서인 모든 무인증 iframe에 공유되지만, 사용자가 탐색하는 각각의 최상위 문서마다 다르며, 사용자가 탐색하던 곳을 벗어나면 저장소에 더 이상 액세스할 수 없습니다. 무인증 IFrame은 여러 페이지에서 저장 공간을 공유하지 않습니다. 위에서 언급한 쿠키로 다시 돌아가자면, 문서를 다시 로드하면 또 다른 컨텍스트에서 무인증 `<iframe>`이 로드되므로 이전에 설정한 쿠키를 사용할 수 없게 됩니다.

추가로,

* 무인증 iframe에서 열리는 팝업은 `rel="noopener"` (en-US)가 설정된 상태로 열립니다. 이렇게 하면 무인증 iframe에서 OAuth 팝업 흐름이 사용되는 것을 방지할 수 있습니다.
* 무인증 `<iframes>`에서 브라우저 자동 완성 또는 비밀번호 관리자 기능을 사용할 수 없습니다.

그 결과, 무인증 `<iframe>`에 로드된 문서는 사용자의 민감한 정보로 꾸며지지 않은, 사실상 순정 또는 "공개" 버전으로 로드됩니다. 이러한 문서에서 유출될 수 있는 민감한 정보는 없기 때문에, 공격자에게 쓸모 있는 내용은 없고, 해당 IFrame에 대한 교차 출처 삽입 정책 요구 사항은 삭제됩니다.

하위 IFrame 내부의 재귀적 무인증
---------------------

만약 `<iframe>`에 `credentialless`가 설정되어 있다면, 해당 `<iframe>`에 내장된 자식 `<iframe>`에도 `credentialless` 설정이 상속됩니다.

실시간 데모
------

https://anonymous-iframe.glitch.me/ 데모를 사용하여 무인증 IFrame의 작동 방식을 확인할 수 있습니다.

명세서
---

| Specification |
| --- |
| Iframe credentialless  |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Cross-Origin-Opener-Policy` (en-US)
* `Cross-Origin-Embedder-Policy`
* `Cross-Origin-Resource-Policy`
* 교차 출처 리소스 공유
* `<iframe>` `credentialless` (en-US) 속성
* `HTMLIFrameElement.credentialless` (en-US)


공격 유형 - 웹 보안

공격 유형
=====

이 문서는 다양한 유형의 보안 공격과 이를 완화하는 기술을 다룹니다.

클릭재킹
----

클릭재킹은 사용자가 생각하는 것과 다른 링크, 버튼 등을 클릭하도록 사용자를 속이는 행위입니다. 예를 들어 로그인 자격 증명을 훔치거나 멀웨어를 설치하기 위해 사용자도 모르게 권한을 얻는 데 사용할 수 있습니다. (클릭재킹은 때때로 "사용자 인터페이스 교정"이라고 하지만 이는 "교정"이라는 용어를 오용한 것입니다.)

교차 사이트 스크립팅 (XSS)
-----------------

교차 사이트 스크립팅(XSS)은 공격자가 웹 사이트에 악성 클라이언트 측 코드를 주입할 수 있는 보안 공격입니다. 이 코드는 피해자에 의해 실행되며 공격자가 접근 제어를 우회하고 사용자를 가장할 수 있습니다. Open Web Application Security Project에 따르면 XSS는 2017년에 7번째로 가장 흔한 웹 앱 취약점이었습니다.

이러한 공격은 웹 앱이 충분한 유효성 검사 또는 인코딩을 사용하지 않는 경우 성공합니다. 사용자의 브라우저는 악의적인 스크립트가 신뢰할 수 없는지를 감지할 수 없으므로 쿠키, 세션 토큰 또는 다른 중요한 사이트별 정보에 대한 접근 권한을 가져가거나 악의적인 스크립트로 HTML 내용을 다시 쓸 수 있습니다.

일반적으로 교차 사이트 스크립팅 공격은 1) 데이터가 신뢰할 수 없는 소스(대부분 웹 요청)를 통해 웹 앱에 입력되거나 2) 악성 콘텐츠에 대한 유효성 검사 없이 동적 콘텐츠를 웹 사용자에게 전송될 때 발생합니다.

악성 콘텐츠에는 보통 JavaScript가 포함되지만 가끔 HTML, Flash 또는 브라우저에서 실행할 수 있는 기타 코드가 포함되기도 합니다. XSS를 기반으로 하는 공격의 종류에는 거의 제한이 없지만, 일반적으로 쿠키 또는 기타 세션 정보와 같은 개인 데이터를 공격자에게 보내거나, 공격자가 제어하는 웹 페이지로 피해자를 리다이렉션하거나, 취약한 사이트를 가장하여 사용자의 컴퓨터에서 다른 악의적인 작업을 수행하는 것이 포함됩니다.

XSS 공격은 저장(영구라고도 함), 반사(비영구라고도 함) 또는 DOM 기반의 세 가지 범주로 나눌 수 있습니다.

저장된 XSS 공격

삽입된 스크립트는 대상 서버에 영구적으로 저장됩니다. 그런 다음 피해자는 브라우저가 데이터 요청을 보낼 때 서버에서 이 악성 스크립트를 검색하게 됩니다.

반사된 XSS 공격

사용자가 속아서 악성 링크를 클릭하거나 특수 제작된 양식을 제출하거나 악성 사이트를 탐색하면 삽입된 코드가 취약한 웹 사이트로 이동합니다. 웹 서버는 오류 메시지, 검색 결과 또는 요청의 일부로 서버에 전송된 데이터를 포함하는 기타 응답과 같이 주입된 스크립트를 사용자의 브라우저에 다시 반사합니다. 브라우저는 응답이 사용자가 이미 상호 작용한 "신뢰할 수 있는" 서버에서 온 것으로 생각하기 때문에 이 코드를 실행합니다.

DOM기반 XSS 공격

페이로드는 원본 클라이언트 측 스크립트가 사용하는 DOM 환경(피해자의 브라우저에서)을 수정한 결로 실행됩니다. 즉, 페이지 자체는 변경되지 않지만 DOM 환경에 대한 악의적인 수정으로 인해 페이지에 포함된 클라이언트 측 코드가 예기치 않은 방식으로 실행됩니다.

교차 사이트 요청 위조 (CSRF)
-------------------

CSRF(XSRF라고도 함)는 관련 클래스의 공격입니다. 공격자는 사용자의 동의나 인지 없이 사용자의 브라우저가 웹사이트의 백엔드에 요청을 수행하도록 합니다. 공격자는 XSS 페이로드를 사용하여 CSRF 공격을 할 수 있습니다.

위키백과에 CSRF에 대한 좋은 예제가 있습니다. 이 상황에서는 누군가가 실제 이미지가 아닌 이미지를 삽입합니다(예: 필터링되지 않은 채팅 또는 포럼에). 대신 이 이미지는 은행 서버에 돈을 인출하라는 요청입니다.

```html
<img
 src="https://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory" />
```

이제 은행 계좌에 로그인되어 있고, 쿠키가 여전히 유효한 경우라면(다른 확인이 없는 경우) 이 이미지가 포함된 HTML을 로드하는 즉시 송금이 진행됩니다. POST 요청이 필요한 엔드포인트 경우, 페이지가 로드될 때 프로그래밍 방식으로 <form> 제출(보이지 않는 <iframe>에서)을 트리거할 수 있습니다.

```html
<form action="https://bank.example.com/withdraw" method="POST">
  <input type="hidden" name="account" value="bob" />
  <input type="hidden" name="amount" value="1000000" />
  <input type="hidden" name="for" value="mallory" />
</form>
<script>
 window.addEventListener("DOMContentLoaded", () => {
 document.querySelector("form").submit();
 });
</script>
```

이러한 일이 발생하지 않도록 하기 위해 사용해야 하는 몇 가지 기술이 있습니다.

* GET 엔드포인트는 멱등적이어야 합니다. 변경 사항을 적용하고 데이터를 검색하지 않는 작업은 POST(또는 다른 HTTP 메서드) 요청을 보내야 합니다. POST 엔드포인트는 쿼리 문자열의 매개변수를 사용하여 GET 요청을 상호 교환적으로 수락해서는 안 됩니다.
* 세션 고유 CSRF 토큰이 서버에서 브라우저로 제공되어야 합니다. 이 토큰은 브라우저에서 양식을 게시할 때마다(`<form>` 요소의 숨겨진 입력 필드에) 포함될 수 있습니다. 작업을 수행할 가능성이 있는 GET 이외의 모든 요청에 대해 서버는 전송된 토큰을 세션에 저장된 값과 비교합니다. 일치하지 않는 경우 요청이 중단됩니다.
* 이 보호 방법은 사용자에게 할당된 CSRF 토큰을 예측할 수 없는 공격자에 의존합니다. 로그인 시 토큰을 다시 생성해야 합니다.
* (세션 쿠키와 같은) 민감한 작업에 사용되는 쿠키는 SameSite 속성이 Strict 또는 Lax로 설정된 짧은 수명을 가져야 합니다. (위의 SameSite 쿠키 참조). 이는 지원되는 브라우저에서 세션 쿠키가 사이트 간 요청과 함께 전송되지 않도록 하는 효과가 있으므로 요청이 애플리케이션 서버에 대해 효과적으로 인증되지 않습니다.
* CSRF 토큰과 SameSite 쿠키를 모두 제공해야 합니다. 이렇게 하면 모든 브라우저가 보호되고 SameSite 쿠키가 도움이 되지 않는 곳에서도 보호 기능을 제공할 수 있습니다(예: 별도의 하위 도메인에서 시작된 공격).

더 많은 예방 팁은 OWASP CSRF 예방 치트 시트를 참조하십시오.

중간자 공격 (MitM)
-------------

제3자는 웹 서버와 클라이언트(브라우저) 간의 트래픽을 가로채고 데이터(예: 로그인 자격 증명 또는 신용 카드 정보)를 캡처하기 위해 웹 서버를 가장합니다. 트래픽이 통과될 때 트래픽이 변경될 수 있습니다. 개방형 Wi-Fi 네트워크는 이 공격을 실행하는 일반적인 수단입니다.

세션 하이재킹
-------

세션 하이재킹은 사용자의 인증된 세션에 액세스하고 오용하는 것으로 구성됩니다. 이는 기존 세션의 쿠키를 훔치거나 사용자(또는 브라우저)를 속여 미리 결정된 세션 ID로 쿠키를 설정함으로써 발생할 수 있습니다.

유출 경로는 엄격한 Content-Security-Policy를 배포하여 제한할 수 있습니다.

### 세션 고정

제3자는 사용자의 세션 식별자를 결정할 수 있으므로(즉, 이를 읽거나 설정하여) 해당 사용자로서 서버와 상호 작용할 수 있습니다. 쿠키를 훔치는 것도 이를 위한 방법 중 하나입니다.

application.example.com과 같은 하위 도메인은 `Domain` 속성을 다음과 같이 설정하여 example.com 또는 다른 하위 도메인에 대한 요청과 함께 쿠키가 전송되도록 설정할 수 있습니다.

```http
Set-Cookie: CSRF=e8b667; Secure; Domain=example.com
```

 취약한 응용 프로그램을 하위 도메인에서 사용할 수 있는 경우, 세션 고정 공격에서 이 메커니즘을 남용할 수 있습니다. 사용자가 부모 도메인(또는 다른 하위 도메인)의 페이지를 방문하면, 애플리케이션은 사용자 쿠키에 전송된 기존 값을 신뢰할 수 있습니다. 이로 인해 공격자는 사용자가 로그인한 후 CSRF 보호를 우회하거나 세션을 하이재킹할 수 있습니다.
 또는 상위 도메인이 `includeSubdomains`가 설정된 HTTP Strict-Transport-Security를 사용하지 않는 경우, 활성 MitM(아마도 개방형 Wi-Fi 네트워크에 연결됨)의 대상이 되는 사용자는 존재하지 않는 하위 도메인의 Set-Cookie 헤더로 응답을 받을 수 있습니다. 최종 결과는 브라우저가 불법 쿠키를 저장하고 이를 example.com 아래의 다른 모든 페이지로 보내는 것과 거의 동일합니다.

세션 고정은 주로 사용자가 인증할 때 세션 쿠키 값을 다시 생성하고(쿠키가 이미 존재하는 경우에도) CSRF 토큰을 사용자에게 연결하는 것으로 완화해야 합니다.

### 세션 사이드재킹

### 브라우저 하이재킹 멀웨어


하위 도메인 탈취 - 웹 보안

하위 도메인 탈취
=========

하위 도메인 탈취는 공격자가 대상 도메인의 하위 도메인을 제어할 때 일어납니다. 일반적으로 하위 도메인이 도메인 이름 시스템(DNS)에 정식 이름(CNAME)은 있지만 콘텐츠를 제공하는 호스트가 없을 때 발생합니다. 이는 가상 호스트가 아직 게시되지 않았거나 가상 호스트가 제거되었기 때문에 발생할 수 있습니다. 공격자는 그들만의 가상 호스트를 제공하고, 하위 도메인에 그들의 콘텐츠를 호스팅 하여 해당 하위 도메인을 장악할 수 있습니다.

공격자가 이를 수행할 수 있는 경우, 그들은 잠재적으로 기본 도메인에 설정된 쿠키를 읽거나, 교차 사이트 스크립팅을 수행하거나, 콘텐츠 보안 정책을 우회하여 보호된 정보(로그인 포함)를 가져가거나, 의심 없는 사용자에게 악의적인 콘텐츠를 보낼 수 있습니다.

하위 도메인은 전기 콘센트와 같습니다. 자신의 기기(호스트)가 연결되어 있으면 아무 문제 없습니다. 그러나, 콘센트에서 기기를 제거한 경우(또는 아직 꽂지 않은 경우), 누군가 콘센트에 다른 것을 꽂을 수 있습니다. 다른 사람이 콘센트를 사용하지 못하도록 차단기나 퓨즈박스(DNS)에서 전원을 차단해야 합니다.

어떻게 발생하나요?
----------

가상 호스트를 프로비저닝 또는 프로비저닝 해제(제거)하는 과정이 제대로 처리되지 않으면, 공격자가 하위 도메인을 장악할 기회가 있을 수 있습니다.

### 프로비저닝 과정에서

공격자는 여러분보다 먼저 여러분이 호스팅 제공자에게 구입한 하위 도메인에 가상 호스트를 등록합니다.

`example.com` 도메인을 관리한다고 가정해 보겠습니다. 여러분은 `blog.example.com`에 블로그를 추가하고 싶고, 블로그 플랫폼을 유지 관리하는 호스팅 공급자를 사용하기로 결정했습니다. ("블로그"는 "전자상거래 플랫폼", "고객 서비스 플랫폼" 또는 기타 "클라우드 기반" 가상 호스팅 시나리오로 대체할 수 있습니다.) 진행되는 프로세스는 다음과 같습니다.

1. 도메인 등록 기관에 "blog.example.com"이라는 이름을 등록합니다.
2. blog.example.com에 액세스하려는 브라우저가 가상 호스트로 이동하도록 DNS 레코드를 설정합니다.
3. 호스팅 공급자에서 가상 호스트를 생성합니다.

호스팅 공급자가 가상 호스트를 설정하는 주체가 실제 하위 도메인 이름의 소유자인지 매우 신중하게 확인하지 않는 한, 여러분보다 더 빠른 공격자는 여러분의 하위 도메인 이름을 사용하여 동일한 호스팅 공급자에서 가상 호스트를 만들 수 있습니다. 이런 경우, 2단계에서 DNS를 설정하는 즉시 공격자가 하위 도메인에서 콘텐츠를 호스트 할 수 있습니다.

### 프로비저닝 해제 과정에서

가상 호스트를 중단했지만, 공격자는 동일한 이름과 호스팅 공급자를 사용하여 새 가상 호스트를 등록합니다.

여러분(또는 여러분의 회사)은 더 이상 블로그를 유지하지 않기로 결정하여 호스팅 공급자에서 가상 호스트를 제거합니다. 그러나 호스팅 공급자를 가리키는 DNS 항목을 제거하지 않으면, 공격자가 이제 해당 공급자와 함께 자신의 가상 호스트를 만들고, 여러분의 하위 도메인을 할당하여 해당 하위 도메인 아래에서 자신의 콘텐츠를 호스팅 할 수 있습니다.

어떻게 방지하나요?
----------

하위 도메인 탈취 방지는 가상 호스트와 DNS에 대한 수명 주기 관리 작업의 순서 문제입니다. 조직의 규모에 따라 여러 부서 간의 소통과 조정이 필요할 수 있고, 이로 인해 취약한 구성 오류의 가능성만 높아질 수 있습니다.

* 호스트 프로비저닝과 프로비저닝 해제를 위한 표준 과정을 정의하세요. 모든 단계를 가능한 한 밀접하게 수행해야 합니다.
    + 먼저 가상 호스트에 요청하여 프로비저닝을 수행하고, 마지막으로 DNS 레코드를 만드세요.
    + 먼저 DNS 레코드를 제거하고 프로비저닝을 해제하세요.
* 조직의 모든 도메인과 해당 호스팅 제공 업체의 인벤토리를 생성하고, 변경 사항이 있을 때마다 업데이트하여 아무것도 남아 있지 않도록 하세요.
* 공격의 틈을 줄이기 위해 호스팅 공급 업체에 압력을 가하세요. 가상 호스트를 요구하는 누군가가 실제로 도메인 이름에 대한 정당한 권한을 가지고 있는지 어떻게 확인하고 있는지 물어봅니다. 조직 내에서 협력하여 이 부분을 공급업체의 자격 확인 과정의 일부로 만듭니다.
제 하위 도메인이 탈취되었습니다. 어떻게 해야 하나요?
------------------------------

도메인의 하위 도메인이 탈취당한 것을 발견한 경우, 가능하다면 먼저 하위 도메인에 대한 DNS 항목을 제거하여 "전원을 차단"해야 합니다. 사이트에 여러 가상화 계층(예: 가상 호스팅 외에 CDN)이 있다면, 각 계층을 조사하여 공격자가 도메인을 탈취하기 위해 가상 호스트 권한을 주장한 정확한 위치가 어디인지 확인해야 할 수도 있습니다.

더 알아보기
------

* Subdomain Takeover Vulnerabilities의 'Deep Thoughts'
* Subdomain Takeover: Basics


전송 계층 보안 - 웹 보안

전송 계층 보안
========

전송 계층 보안(TLS)을 사용하는 모든 연결의 보안은 선택된 암호화 스위트와 보안 매개변수에 강하게 의존합니다. 이 문서의 목표는 클라이언트와 서버 간 통신의 기밀성과 무결성을 보장하기 위한 결정을 내리는 데 도움을 주는 것입니다. Mozilla 운영 보안(OpSec) 팀은 서버를 위한 참조 설정이 포함된 위키 항목을 유지 관리합니다.

전송 계층 보안(TLS) 프로토콜은 네트워크로 연결된 두 개의 애플리케이션이나 장치가 비공개로 강력하게 정보를 교환할 수 있도록 하는 표준입니다. TLS를 사용하는 애플리케이션은 데이터의 보안과 안정성에 상당한 영향을 미칠 수 있는 보안 매개변수를 선택할 수 있습니다. 이 문서에서는 TLS에 대한 개요와 콘텐츠를 보호할 때 내려야 하는 결정의 종류를 제공합니다.

역사
--

HTTPS가 처음 소개되었을 땐 Netscape가 도입한 기술인 보안 소켓 계층(SSL) 2.0이 기반이었습니다. 얼마 지나지 않아 SSL 3.0으로 업데이트되었고, 사용이 확대됨에 따라 모든 웹 브라우저와 서버 간의 상호 운용성을 보장하기 위해 공통 표준 암호화 기술을 지정해야 한다는 것이 분명해졌습니다. Internet Engineering Task Force (IETF)는 1999년 1월 RFC 2246에서 TLS 1.0을 기입했습니다. TLS의 현재 버전은 1.3(RFC 8446)입니다.

이제 웹이 암호화에 TLS를 사용하고 있음에도 불구하고, 많은 사람들이 아직까지 습관적으로 TLS를 "SSL"이라고 언급합니다.

TLS가 모든 저수준의 전송 프로토콜의 위에서 사용될 수 있지만, 이 프로토콜은 원래 HTTP 트래픽을 암호화하는 것이 목적이었습니다. TLS로 암호화된 HTTP는 흔히 HTTPS라고 합니다. TLS로 암호화된 웹 트래픽은 관습적으로 443 포트를 통해 교환되었으며, 암호화되지 않은 HTTP는 기본적으로 80번 포트를 사용합니다. HTTPS는 중요한 TLS 사용 사례로 남았습니다.

HTTP 위에 TLS
-----------

TLS는 주고받는 데이터의 안전과 보안을 보장하게 하는 세 가지 주요 서비스를 제공합니다.

인증

인증을 통해 통신의 각 당사자는 상대방이 자신이 주장하는 사람인지 확인할 수 있습니다.

암호화

권한이 없는 사람이 데이터를 읽고 해석하는 것을 방지하기 위해 사용자 에이전트와 서버 사이에 데이터가 전송되는 동안 데이터가 암호화됩니다.

무결성

TLS는 데이터를 암호화, 전송, 복호화하는 동안에 정보가 없어지거나, 손실되거나, 변조되지 않는 것을 보장합니다.

TLS 연결은 클라이언트와 서버가 공유 암호에 동의하고 암호화 스위트와 같은 중요한 매개변수가 협상되는 핸드쉐이크 단계로 시작됩니다. HTTP와 같은 애플리케이션 데이터가 교환되는 매개변수와 데이터 교환 모드입니다.

### 암호화 스위트

TLS 핸드쉐이크가 협상하는 주요 파라메터들은 암호화 스위트입니다.

TLS 1.2와 그 이전 버전에서 협상된 암호화 스위트는 공유 암호 협상, 서버가 인증되는 방법, 데이터를 암호화 하는데 사용할 방법을 함께 제공하는 암호화 알고리즘의 집합을 포함합니다.

TLS 1.3의 암호와 스위트는 주로 데이터 암호화를 관리하며 키 계약과 인증에는 별도의 협상 방법이 사용됩니다.

서로 다른 소프트웨어는 같은 암호화 스위트에 대해 서로 다른 이름을 사용할 수 있습니다. 예를 들어 OpenSSL과 GnuTLS에서 사용되는 이름은 TLS 표준에서 사용되는 이름과 다릅니다. TLS 설정에 대한 Mozilla OpSec 팀 문서에 있는 암호 이름 대응 표에는 이러한 이름과 호환성, 보안 수준에 대한 정보가 나열되어 있습니다.

### 서버 설정하기

서버를 올바르게 구성하는 것은 매우 중요합니다. 일반적으로, 사이트에 연결하려는 브라우저와 호환 가능한 최신 암호화 기능으로만 한정적으로 설정하는 것이 좋습니다. 올바른 설정과 관련해서 Mozilla OpSec guide to TLS configurations 에서 추가적인 정보를 얻을 수 있습니다.

사이트 구성을 돕기 위해 Mozilla는 다음 웹 서버에 대한 설정 파일을 생성하는 유용한 TLS 설정 생성기를 제공합니다.

* Apache
* Nginx
* Lighttpd
* HAProxy
* Amazon Web Services CloudFormation Elastic Load Balancer

여러분의 필요에 맞게 설정을 생성하려면 설정기를 사용하는 것이 좋습니다. 그런 다음 복사하여 서버의 해당 파일에 붙여넣고 서버를 다시 시작하여 변경 사항을 적용하십시오. 설정 파일은 사용자 정의 설정을 포함하기 위해 약간의 조정이 필요할 수 있으므로 사용하기 전에 생성된 설정을 검토해야 합니다. 도메인 이름 등에 대한 참조가 올바른지 확인하지 않고 설정 파일을 설치하면 서버가 작동하지 않습니다.

TLS 1.3
-------

RFC 8446: TLS 1.3은 TLS의 주요 개정판입니다. TLS 1.3에는 보안과 성능을 개선하는 수많은 변경 사항이 포함되어 있습니다. TLS 1.3의 목표는 다음과 같습니다.

* TLS 1.2에서 사용하지 않고 안전하지 않은 요소들을 제거
* 설계에 강력한 보안 분석을 포함
* 더 많은 프로토콜을 암호화하여 개인 정보를 개선
* 핸드쉐이크를 성립시키는데 소요되는 시간을 단축

TLS 1.3은 프로토콜 기본 사항의 많은 부분을 변경하지만, 이전 TLS 버전의 거의 모든 기본 기능을 유지합니다. 웹의 경우 몇 가지 드문 예외를 제외하고 호환성에 영향을 주지 않으면서 TLS 1.3을 활성화할 수 있습니다(아래 참조).

TLS 1.3의 주요 변화는 다음과 같습니다.

* TLS 1.3 핸드쉐이크는 대부분의 경우에 한번의 왕복만으로 완려되어 핸드쉐이크 지연시간이 줄어듭니다.
* 서버는 0-RTT(무 왕복 시간) 핸드쉐이크를 활성화할 수 있습니다. 서버에 다시 연결하는 클라이언트는 즉시 요청을 보낼 수 있으므로 TLS 핸드쉐이크의 대기 시간이 완전히 제거됩니다. 0-RTT의 성능 향상이 상당할 수 있지만 재생 공격의 위험이 있으므로 이 기능을 활성화하기 전에 약간의 주의가 필요합니다.
* TLS 1.3은 연결이 재개되거나 사전 공유 키를 사용하지 않는 한 정방향 보안 모드만 지원합니다.
* TLS 1.3은 TLS 1.3 전용인 새로운 암호화 스위트를 정의합니다. 이러한 암호화 스위트는 모두 최신 연관 데이터 암호화 인증(AEAD) 알고리즘을 사용합니다.
* 공유 비밀을 설정하는 데 필요한 메시지를 제외한 TLS 1.3 핸드쉐이크는 암호화됩니다. 특히 이는 서버와 클라이언트 인증서가 암호화 되었다는 것을 의미합니다. 그러나 클라이언트가 서버에 보내는 서버 ID(server\_name 또는 SNI 확장자)는 암호화되지 않습니다.
* 재협상, 일반 데이터 압축, 디지털 서명 알고리즘 (DSA) 인증서, 정적 RSA 키 교환, 사용자 지정 Diffie-Hellman (DH) 그룹과의 키 교환 등의 여러 메커니즘이 비활성화되었습니다.

TLS 1.3 초안 버전 구현은 가능합니다. TLS 1.3은 0-RTT 모드를 포함하여 일부 브라우저에서 활성화되어 있습니다. TLS 1.3을 활성화한 웹 서버는 TLS 1.3이 성공적으로 작동하도록 설정을 조정해야 할 수 있습니다.

TLS 1.3은 중요한 새로운 사용 사례를 하나만 추가합니다. 0-RTT 핸드쉐이크는 웹과 같이 대기 시간에 민감한 애플리케이션에 상당한 성능 향상을 제공할 수 있습니다. 0-RTT를 활성화하려면 성공적인 배포를 보장하고 재생 공격의 위험을 관리하기 위해 추가 단계가 필요합니다.

TLS 1.3에서 재협상을 제거하면 인증서를 이용한 클라이언트 인증에 의존하는 일부 웹 서버가 영향을 받을 수 있습니다. 일부 웹 서버는 재협상을 사용하여 클라이언트 인증서가 암호화되었는지 확인하거나 특정 리소스가 요청될 때만 클라이언트 인증서를 요청합니다. 클라이언트 인증서의 개인 정보 보호를 위해 TLS 1.3 핸드쉐이크의 암호화는 클라이언트 인증서가 암호화되도록 합니다. 그러나 일부 소프트웨어 변경이 필요할 수 있습니다. 인증서를 사용하는 반응형 클라이언트 인증은 TLS 1.3에서 지원되지만 광범위하게 구현되진 않습니다. HTTP/2도 지원할 대체 메커니즘이 개발 중에 있습니다.

이전 TLS 버전 제거하기
--------------

보다 현대적이고 안전한 웹을 위한 작업을 돕기 위해 모든 주요 브라우저는 2020년 초에 TLS 1.0과 1.1에 대한 지원을 제거하기 시작했습니다. 앞으로 웹 서버가 TLS 1.2 또는 1.3을 지원하는지 확인해야 합니다.

Firefox는 버전 74부터 이전 TLS 버전을 사용하여 서버에 연결할 때 보안 연결 실패 오류를 반환합니다(Firefox 버그 1606734).

TLS 핸드쉐이크 타임아웃 값
----------------

어떤 이유로 TLS 핸드셰이크가 느려지거나 응답하지 않으면 사용자 경험에 상당한 영향을 미칠 수 있습니다. 이 문제를 완화하기 위해 최신 브라우저는 핸드셰이크 시간 제한을 구현했습니다.

어떤 이유에서든지 간에 TLS 핸드쉐이크가 느려지거나 반응이 없다면 사용자 경험에 상당한 영향을 미칠 수 있습니다. 이 문제들을 완화하기 위해 최신 브라우저들은 핸드쉐이크 타임아웃을 도입했습니다.

* Firefox는 버전 58부터 기본값이 30초인 TLS 핸드쉐이크 타임아웃을 도입했습니다. 타임아웃 값은 about:config에서 `network.http.tls-handshake-timeout` 설정을 편집하여 변경할 수 있습니다.
같이 보기
-----

* Mozilla SSL 설정 생성기와 Cipherlist.eu는 사이트를 보호하기 위해 서버에 대한 설정 파일을 생성하는 데 도움이 될 수 있습니다.
* OpSec(Mozilla Operations Security) 팀은 참조 TLS 설정이 포함된 위키 페이지를 유지 관리합니다.
* Mozilla Observatory, SSL Labs, 그리고 Cipherscan은 사이트를 테스트하여 TLS 구성이 얼마나 안전한지 확인하는 데 도움을 줄 수 있습니다.
* Secure Contexts
* Strict-Transport-Security HTTP 헤더


사용자 활성화로 제어되는 기능 - 웹 보안

사용자 활성화로 제어되는 기능
================

원하지 않은 동작으로 나쁜 사용자 경험을 제공할 수 있는 API를 애플리케이션이 남용할 수 없도록 하기 위해 일부 API는 사용자가 현재 웹 페이지와 상호 작용 중임을 의미하는 "상호 작용 활성" 상태에 있을 때, 혹은 한 번 이상 페이지와 상호 작용을 한 경우에만 사용할 수 있습니다. 브라우저는 악의적인 스크립트가 이러한 기능을 남용하지 못하도록 팝업, 전체 화면 또는 진동 API와 같은 민감한 API에 대한 액세스를 활성 사용자 상호 작용으로 제한합니다. 이 페이지에는 사용자 활성화 후에만 사용할 수 있는 웹 플랫폼 기능이 나열되어 있습니다.

사용자 활성화는 사용자가 현재 페이지와 상호 작용 중이거나 페이지 로드 이후 상호 작용을 완료했음을 의미합니다. 일반적으로 이것은 버튼 클릭 또는 UI와의 다른 사용자 상호 작용입니다.

보다 정확하게, **활성화 트리거 입력 이벤트**는 다음과 같은 이벤트입니다.

* `isTrusted` 속성이 `true`로 설정되어 있고
* 다음 유형의 이벤트인 경우
    + `keydown` (en-US)(`Esc` 키나 사용자 에이전트가 예약한 바로 가기 키 제외)
    + `mousedown` (en-US)
    + `pointerdown` (en-US) (`pointerType`이 "mouse"인 경우)
    + `pointerup` (en-US) (`pointerType`이 "mouse"가 아닌 경우)
    + `touchend` (en-US)

활성화가 트리거된 경우, 사용자 에이전트는 사용자 활성화 창 상태를 고정과 임시라는 두 가지 유형으로 구분합니다.

임시 활성화
------

임시 활성화는 사용자가 최근에 버튼을 눌렀거나, 마우스를 이동했거나, 메뉴를 사용했거나, 다른 사용자 상호 작용을 수행했음을 나타내는 창 상태입니다. 임시 활성화는 추가 상호 작용으로 갱신되지 않는한 시간 초과 후 만료되며 `Window.open()` (en-US)과 같은 일부 API에서 사용할 수도 있습니다.

임시 활성화가 필요한 예시 API는 다음과 같습니다.

* `beforeunload` 이벤트
* `Clipboard.read()` (en-US)
* `Clipboard.readText()` (en-US)
* `Clipboard.writeText()` (en-US)
* `Document.requestStorageAccess()` (en-US)
* `Element.requestFullScreen()` (en-US)
* `Element.requestPointerLock()` (en-US)
* `GPUAdapter.requestAdapterInfo()`
* `HID.requestDevice()` (en-US)
* `HTMLInputElement.showPicker()` (en-US)
* `HTMLVideoElement.requestPictureInPicture()` (en-US)
* `IdleDetector.requestPermission()` (en-US)
* `MediaDevices.selectAudioOutput()` (en-US)
* `MediaStreamTrack.sendCaptureAction()`
* `MediaDevices.getViewportMedia()`
* `MediaDevices.getDisplayMedia()` (en-US)
* `Navigator.share()`
* `PaymentRequest.show()` (en-US)
* `PresentationRequest.start()` (en-US)
* `RemotePlayback.prompt()` (en-US)
* `USB.requestDevice()` (en-US)
* `Keyboard.lock()` (en-US)
* `Window.open()` (en-US)
* `Window.showOpenFilePicker()` (en-US)
* `Window.showSaveFilePicker()` (en-US)
* `Window.showDirectoryPicker()` (en-US)
* `Window.getScreenDetails()`
* `Window.queryLocalFonts()`
* `XRSystem.requestSession()` (en-US)
고정 활성화
------

고정 활성화는 사용자가 버튼을 눌렀거나, 마우스를 이동했거나, 메뉴를 사용했거나, 다른 사용자 상호 작용을 수행했음을 나타내는 창 상태입니다. 임시 활성화와 달리 처음 설정한 후에는 다시 설정되지 않습니다.

고정 활성화가 필요한 예시 API는 다음과 같습니다.

* `Navigator.vibrate()` (en-US)
* `navigator.getAutoplayPolicy()`
* `navigator.virtualKeyboard.show()`
UserActivation API
------------------

창에 고정 또는 일시적 사용자 활성화가 있는지 프로그래밍적으로 확인하기 위해 `UserActivation` (en-US) API는 `navigator.userActivation` (en-US)을 사용하여 얻을 수 있는 두 가지 속성을 제공합니다.

* `UserActivation.hasBeenActive` (en-US)는 창에 고정 사용자 활성화 여부를 나타냅니다.
* `UserActivation.isActive` (en-US)는 창에 임시 사용자 활성화 여부를 나타냅니다.
같이 보기
-----

* Transient activation
* Sticky activation
* `UserActivation` (en-US) API
* 보안 컨텍스트로 제한된 기능들


보안 컨텍스트 - 웹 보안

보안 컨텍스트
=======

**보안 컨텍스트**는 특정한 최소 인증 및 기밀성 표준이 충족되는 `Window` 또는 `Worker`입니다. 많은 웹 API와 기능들은 보안 컨텍스트에서만 액세스할 수 있습니다. 보안 컨텍스트의 주요 목표는 MITM 공격자가 공격의 피해자를 추가로 손상시킬 수 있는 강력한 API에 접근하지 못하도록 방지하는 것입니다.

왜 일부 기능을 제한해야하나요?
-----------------

웹의 일부 API는 매우 강력하여 공격자가 다음과 같은 작업을 수행할 수 있습니다.

* 사용자의 프라이버시 침해
* 사용자 컴퓨터에 대한 저수준 엑세스 권한을 얻음
* 사용자 자격 증명과 같은 데이터에 대한 액세스 권한을 얻음
컨텍스트는 언제 안전한가요?
---------------

컨텍스트는 보안 컨텍스트 명세서에 정의된 특정한 최소 인증 및 기밀성 표준을 충족할 때 안전하다고 간주됩니다. 특정 문서는 보안 컨텍스트인 최상위 브라우징 컨텍스트(창 또는 탭)의 활성 문서일 때 보안 컨텍스트에 있는 것으로 간주됩니다.

예를 들어 `<iframe>` (en-US) 내에서 TLS를 통해 전달된 문서의 경우에도 TLS를 통해 전달되지 **않은** 상위 항목이 있는 경우 해당 컨텍스트는 안전한 것으로 간주되지 않습니다.

그러나 비(非)보안 컨텍스트로 인해 새 창이 생성되는 경우(noopener (en-US)를 지정하거나 지정하지 않고), 오프너가 안전하지 않다는 사실은 새 창이 안전한 것으로 간주되는것에 영향을 미치지 않는다는 점에 유의해야 합니다. 특정 문서가 보안 컨텍스트에 있는지 여부를 결정하는 것은 비보안 컨텍스트가 문서를 만들었는지가 아니라 연결된 최상위 브라우징 컨텍스트 내에서만 고려하기 때문입니다.

`http://127.0.0.1` URL, `http://localhost` 및 `http://*.localhost` URL(예: `http://dev.whatever.localhost/`) 그리고 `file://`과 같은 로컬에서 제공된 리소스도 안전하게 전달된 것으로 간주됩니다.

**참고:** Firefox 84 이상에서는 `http://localhost`와 `http://*.localhost` URL을 신뢰할 수 있는 원본으로 지원합니다(`localhost`가 로컬/루프백 주소로 매핑되는 것이 보장되지 않았기 때문에 이전 버전에서는 지원하지 않음).

로컬이 아닌 리소스가 안전한 것으로 간주되려면 다음 기준을 충족해야 합니다.

* `https://` 또는 `wss://` URL을 통해 제공되어야 한다.
* 리소스를 전달하는 데 사용되는 네트워크 채널의 보안 속성이 더 이상 사용되지 않는(deprecated) 것이 아니어야 한다.
기능 감지
-----

페이지는 전역 스코프에 있는 `isSecureContext` (en-US) 불리언 값을 사용하여 보안 컨텍스트에 있는지 여부를 확인하기 위해 기능 감지를 사용할 수 있습니다.

```js
if (window.isSecureContext) {
  // 페이지는 보안 컨텍스트이므로 이제 서비스 워커를 사용할 수 있습니다.
  navigator.serviceWorker.register("/offline-worker.js").then(() => {
    // …
  });
}
```

명세서
---

| Specification |
| --- |
| Secure Contexts  |

같이 보기
-----

* 보안 컨텍스트로 제한된 플랫폼 기능 — 보안 컨텍스트에서만 사용할 수 있는 기능 목록
* `isSecureContext` (en-US)
* https://permission.site — HTTP 및 HTTPS를 통해 브라우저가 사용하는 API 권한 검사를 확인할 수 있는 사이트
* Strict-Transport-Security HTTP 헤더


사이트 보안 - 웹 보안

사이트 보안
======

사이트 보안을 위해 할 수 있는 것은 많이 있습니다. 이 문서는 더 유용한 정보를 제공하는 다른 문서의 링크를 포함한 여러 가지 제안 사항을 제공합니다.

**참고:** 이 문서는 작성 중에 있어 완성되지 않았으며, 문서의 제안 사항을 따르더라도 사이트가 완전히 안전하다는 보장은 없습니다.

사용자 정보 보안
---------

양식 자동 완성을 끄는 법

Gecko는 양식 필드의 자동 완성을 지원합니다. 즉, 양식의 값을 기억하고 있다가 다음에 사이트를 방문할 때 자동으로 불러올 수 있습니다. 특정 데이터 유형의 경우, 이 기능을 비활성화할 수 있습니다.

사생활과 :visited 선택자 (en-US)

이 문서에서는 악의적인 사이트가 사용자의 검색 기록을 파악하는 기능을 제거하는 `getComputedStyle()` 메서드의 변경 사항에 대해 설명합니다.

보안 알고리즘을 이용한 해쉬 암호 (OWASP)

암호를 일반 텍스트로 저장하면 공격자가 사이트 사용자의 정확한 암호를 알고 유출하여 잠재적으로 사용자를 위험에 빠뜨릴 수 있습니다. 오래되었거나 안전하지 않은 해쉬 알고리즘(예: md5)을 사용하는 경우에도 동일한 문제가 발생할 수 있습니다. 메시지 다이제스트 알고리즘(예: md5와 sha) 대신 암호별 해쉬 알고리즘(예: Argon2, PBKDF2, scrypt 또는 bcrypt)을 사용해야 합니다. 이 문서는 암호를 저장 사용할 때 사용할 모범 사례를 보여줍니다.

콘텐츠 보안
------

서버 MIME 유형을 올바르게 구성하기 (en-US)

잘못된 MIME 유형이 사이트에 잠재적인 보안 문제를 일으킬 수 있는 몇 가지 상황이 있습니다. 이 문서는 그 중 일부를 설명하고 올바른 MIME 유형으로 파일을 제공하도록 서버를 구성하는 방법을 보여줍니다.

HTTP Strict Transport Security

`Strict-Transport-Security:` HTTP 헤더를 사용하면 웹사이트를 HTTPS를 통해서만 접근할 수 있음을 지정할 수 있습니다.

HTTP 접근 제어

Cross-Origin Resource Sharing 표준은 다른 도메인에서 로드할 수 있는 콘텐츠를 지정하는 방법을 제공합니다. 이를 사용하여 사이트가 부적절하게 사용되는 것을 방지할 수 있습니다. 또한 이를 사용하여 다른 사이트에서 사용하도록 명시적으로 허용된 리소스를 설정할 수 있습니다.

콘텐츠 보안 정책

교차 사이트 스크립팅(XSS)과 데이터 삽입 공격을 포함한 특정 유형의 공격을 감지하고 완화하는 데 도움이 되는 추가 보안 계층입니다. 이러한 공격은 데이터 도용부터 사이트 손상 또는 맬웨어 배포까지, 모든 곳에 사용됩니다. 코드는 피해자에 의해 실행되며 공격자는 접근 제어를 우회하고 사용자를 가장할 수 있습니다.

X-Frame-Options 응답 헤더

`X-Frame-Options:` HTTP 응답 헤더는 브라우저가 `<frame>` (en-US)에서 페이지를 렌더링하도록 허용해야 하는지의 여부를 나타내는 데 사용할 수 있습니다. 사이트는 이를 이용하여 콘텐츠가 다른 사이트에 포함되지 않도록 함으로써 클릭재킹 공격을 피할 수 있습니다.

웹사이트 구성을 통한 접근 제어

사이트를 보호하는 가장 좋은 방법입니다. 특정 IP를 무시하고, 웹사이트의 특정 영역에 대한 접근을 제한하고, 다른 파일을 보호하고, 이미지 핫링크로부터 보호하는 등의 작업을 할 수 있습니다. 예를 들어 .htaccess 파일은 Apache HTTP Server에서 호스팅되는 웹 사이트에 사용됩니다.

같이 보기
-----

* 공개 웹 애플리케이션 보안 프로젝트 (OWASP)
* Mozilla 웹 보안 치트 시트
* OWASP의 교차 사이트 스크립팅


하위 리소스 무결성 - 웹 보안

하위 리소스 무결성
==========

**하위 리소스 무결성**(SRI)은 브라우저가 가져온 리소스(예: CDN에서)가 예기치 않은 조작 없이 전달되었는지 검증하는 보안 기능입니다. 가져온 리소스와 일치해야 하는 암호 해시를 제공함으로써 작동합니다.

**참고:** 임베드된 문서 이외의 출처에서 제공되는 하위 리소스 무결성을 검증하기 위해, 브라우저는 추가로 교차 출처 리소스 공유 (CORS)를 사용하여 리소스를 제공하는 출처가 요청 출처와 리소스를 공유할 수 있는지 확인합니다.

하위 리소스 무결성이 어떻게 도움이 되는가?
------------------------

콘텐츠 전달 네트워크(CDN)를 사용하여 여러 사이트에서 공유되는 스크립트와 스타일시트와 같은 파일을 호스트하면 사이트의 성능을 개선하고 대역폭을 절약할 수 있습니다. 그러나, 공격자가 CDN을 제어할 수 있는 경우, CDN을 사용하게 된다면, 공격자가 임의의 악성 콘텐츠를 CDN 파일에 삽입(또는 파일을 완전히 교체)할 수 있으므로 해당 CDN에서 파일을 가져오는 모든 사이트는 잠재적인 공격 대상이 될 수 있습니다.

하위 리소스 무결성을 사용하면 웹 애플리케이션 또는 웹 문서가 가져오는 파일(CDN 또는 어디에서나)이 제삼자의 추가 콘텐츠가 삽입 없이 전달되었고, 어떤 종류의 다른 변경 사항도 전혀 적용되지 않았다는 것을 확신할 수 있어 이와 같은 공격의 일부 위험을 완화할 수 있습니다.

하위 리소스 무결성 사용하기
---------------

하위 리소스 무결성은 `<script>` 또는 `<link>` 요소의 `integrity` 속성값에 브라우저에서 가져오라고 지시한 리소스(파일)의 base64로 인코딩된 암호 해시를 지정하여 사용합니다.

`integrity` 값은 하나 이상의 문자열로 시작하고, 각 문자열에는 특정 해시 알고리즘(현재 허용되는 접두사는 `sha256`, `sha384`, 그리고 `sha512`)을 나타내는 접두사가 포함되어 있으며, 대시가 따라온 뒤, 실제 base64로 인코딩된 해시로 끝납니다.

**참고:** **integrity** 값에는 공백으로 구분된 여러 해시가 포함될 수 있습니다. 해당 해시 중 하나와 일치하는 경우 리소스가 로드됩니다.

`integrity` 문자열과 base64로 인코딩된 sha384 해시의 예제입니다.
```

sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
```

즉, `oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC`는 해시 부분이고, `sha384` 접두사는 sha384 해시임을 나타냅니다.

**참고:** 엄밀히 말해, `integrity` 값의 "해시" 부분은 어떤 입력(예: 스크립트 또는 스타일시트 파일)에 특정 해시 함수를 적용하여 형성된 **암호 다이제스트**입니다. 그러나 암호 다이제스트를 의미하기 위해 "해시"라는 단축어를 사용하는 것이 일반적이므로 이 문서에서도 그렇게 사용했습니다.

### SRI 해시 생성 도구

#### SRI 해시 생성기

SRI 해시 생성기는 SRI 해시를 생성하는 온라인 도구입니다.

#### OpenSSL 사용하기

명령줄에서 다음과 같이 **OpenSSL**을 사용하여 SRI 해시를 생성할 수 있습니다.

```bash
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
```

Windows 환경에서는 다음 코드를 사용하여 SRI 해시를 생성하는 도구를 만들 수 있습니다.

```batch
@echo off
set bits=384
openssl dgst -sha%bits% -binary %1% | openssl base64 -A > tmp
set /p a= < tmp
del tmp
echo sha%bits%-%a%
pause
```

이 코드는 다음과 같이 사용할 수 있습니다.

1. 위 코드를 여러분 환경의 Windows SendTo 폴더(예: `C:\Users\USER\AppData\Roaming\Microsoft\Windows\SendTo`)에 `sri-hash.bat` 라는 이름으로 저장합니다.
2. 파일 탐색기에서 파일을 마우스 오른쪽 버튼으로 클릭하고 **보내기...**를 선택한 다음, `sri-hash`를 선택합니다. 명령 상자에 무결성 값이 표시됩니다.
3. 무결성 값을 선택하고 마우스 오른쪽 버튼을 클릭하여 클립보드에 복사합니다.
4. 아무 키나 눌러 명령 상자를 닫습니다.

**참고:** 시스템에 OpenSSL이 설치되어 있지 않은 경우, OpenSSL 프로젝트 웹 사이트를 방문하여 다운로드와 설치에 대한 정보를 확인하십시오. OpenSSL 프로젝트 자체는 OpenSSL의 바이너리 배포판을 호스팅하지 않지만, 타사 배포판의 비공식 목록(https://wiki.openssl.org/index.php/Binaries)은 유지되고 있습니다.

#### shasum 사용하기

다음과 같은 명령 호출로 **shasum**을 사용하여 SRI 해시를 생성할 수 있습니다.

```bash
shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64
```

* `xxd` 파이프 통과 단계는 `shasum`에서 16진수 출력을 가져와 이진수로 변환합니다.
* `shasum`은 해시된 파일의 이름을 `xxd`로 전달하기 때문에 `awk` 파이프 통과 단계가 필요합니다. 파일 이름에 유효한 16진수 문자가 있는 경우, 재앙적인 결과가 초래될 수 있습니다. `xxd`도 해당 문자를 디코딩하여 `base64`로 전달하기 때문입니다.
### 교차 출처 리소스 공유 및 하위 리소스 무결성

임베드된 문서 이외의 출처에서 제공되는 하위 리소스 무결성을 검증하기 위해, 브라우저는 추가로 교차 출처 리소스 공유(CORS)를 사용하여 리소스를 제공하는 출처가 요청 출처와 리소스를 공유할 수 있는지 확인합니다. 따라서 리소스가 리소스 요청 출처와 공유될 수 있도록 하는 `Access-Control-Allow-Origin` 헤더가 함께 제공되어야 합니다. 예를 들어 다음과 같습니다.

```http
Access-Control-Allow-Origin: \*
```

예제
--

다음 예제에서 `oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC`가 `example-framework.js`라는 특정 스크립트의 기대 SHA-384 해시(다이제스트)로 이미 알려져 있고, `https://example.com/example-framework.js`에 스크립트의 복사본이 호스팅 되어있다고 가정합니다.

### <script> 요소와 하위 리소스 무결성

다음 `<script>` 요소를 사용하여 `https://example.com/example-framework.js` 스크립트를 실행하기 전, 브라우저에 먼저 스크립트를 기대 해시와 비교하고 일치하는지 확인해야 한다고 알릴 수 있습니다.

```html
<script
 src="https://example.com/example-framework.js"
 integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
 crossorigin="anonymous"></script>
```

**참고:** `crossorigin` 속성의 용도에 대한 자세한 내용은 CORS 설정 속성을 참조하십시오.

브라우저가 하위 리소스 무결성을 처리하는 방법
-------------------------

브라우저는 하위 리소스 무결성을 다음과 같이 처리합니다.

1. 브라우저가 `integrity` 속성이 있는 `<script>`나 `<link>` 요소를 발견하면, 브라우저는 스크립트를 실행하거나 `<link>` 요소에 지정된 스타일시트를 적용하기 전에 먼저 스크립트 또는 스타일시트를 `integrity` 값에 지정된 기대 해시와 비교해야 합니다.
 임베드된 문서 이외의 출처에서 제공되는 하위 리소스 무결성을 검증하기 위해, 브라우저는 추가로 교차 출처 리소스 공유 (CORS)를 사용하여 리소스를 제공하는 출처가 요청 출처와 리소스를 공유할 수 있는지 확인합니다.
2. 스크립트 또는 스타일시트가 관련 `integrity` 값과 일치하지 않는 경우, 브라우저는 스크립트 실행 또는 스타일시트 적용을 거부하고, 해당 스크립트나 스타일시트 가져오기가 실패했음을 나타내는 네트워크 오류를 대신 반환해야 합니다.
명세서
---

| Specification |
| --- |
| HTML Standard # attr-link-integrity |
| Subresource Integrity # the-integrity-attribute |
| HTML Standard # attr-script-integrity |

브라우저 호환성
--------

### html.elements.link.integrity

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### html.elements.script.integrity

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* 콘텐츠 보안 정책
* `Content-Security-Policy` (en-US) HTTP 헤더
* XSS를 할 수 없는 CDN: 하위 리소스 무결성 사용하기
* W3C의 하위 리소스 무결성 검사
* SRI 해시 생성기


차단된 혼합 콘텐츠가 있는 웹사이트를 고치는 방법 - 웹 보안

차단된 혼합 콘텐츠가 있는 웹사이트를 고치는 방법
===========================

Firefox 23부터는 기본적으로 액티브 혼합 콘텐츠를 차단합니다. 이는 Chrome에서 채택한 방식을 따른 것입니다.

이 페이지는 웹 개발자로서 알아야 할 사항을 설명합니다.

웹사이트가 고장날 수 있습니다
----------------

웹사이트가 HTTPS 페이지를 제공하는 경우, 이 페이지에서 HTTP를 통해 전달되는 모든 액티브 혼합 콘텐츠는 기본적으로 차단됩니다. 따라서 사용자에겐 웹사이트가 손상된 것처럼 보일 수 있습니다(iframe 또는 플러그인이 로드되지 않는 경우 등). 패시브 혼합 콘텐츠는 기본적으로 표시되긴 하지만, 사용자는 이러한 유형의 콘텐츠도 차단하도록 설정할 수 있습니다.

이미 Chrome부터 혼합 콘텐츠 차단을 시행했기 때문에 웹사이트가 Chrome에서 정상적으로 작동하는 경우, 혼합 콘텐츠 차단 기능이 있는 Firefox에서도 동일하게 작동할 가능성이 높습니다.

어떤 경우든 Firefox에 문제가 있는지 확인하는 가장 좋은 방법은 최신 Firefox 에디션을 다운로드하고, 검사할 여러 페이지에서 웹 콘솔을 열고 ("Security" 메시지 활성화) 웹 사이트에 접속하여 혼합 콘텐츠와 관련된 사항이 보고되는지 확인하는 것입니다. 또는 SSL-check나 Missing Padlock과 같은 무료 온라인 크롤러, HTTPSChecker와 같은 데스크톱 크롤러, 아니면 mcdetect과 같은 CLI 도구를 사용하여 웹사이트를 재귀적으로 검사하고 안전하지 않은 콘텐츠의 링크를 찾을 수 있습니다. 혼합 콘텐츠에 대한 언급이 없다면 웹사이트는 좋은 상태입니다. 계속해서 멋진 웹사이트를 만드세요!

웹사이트를 고치는 방법
------------

혼합 콘텐츠 차단을 피하는 가장 좋은 전략은 모든 콘텐츠를 HTTP가 아닌 HTTPS로 제공하는 것입니다.

**자체 도메인의 경우,** 모든 콘텐츠를 HTTPS로 제공하고 링크를 수정하세요. 콘텐츠의 HTTPS 버전이 이미 존재하는 경우가 많으므로 http://에서 https://로 링크에 "s"를 추가하기만 하면 됩니다.

그러나 경우에 따라서 해당 미디어의 경로가 올바르지 않을 수도 있습니다. linkchecker와 같이 이 문제를 해결하는 데 도움이 되는 온라인 및 오프라인 도구(운영 체제에 따라 다름)가 있습니다.

**다른 도메인의 경우,** 사용 할 수 있다면 사이트를 HTTPS 버전으로 사용하세요. HTTPS를 사용할 수 없는 경우, 해당 도메인에 연락하여 HTTPS를 통해 콘텐츠를 제공할 수 있는지 문의해 보세요.


보안 컨텍스트로 제한된 기능들 - 웹 보안

보안 컨텍스트로 제한된 기능들
================

이 참조는 보안 컨텍스트에서만 사용할 수 있는 웹 플랫폼 기능을 나열합니다. 정의와 자세한 내용은 보안 컨텍스트를 참조하세요.

보안 컨텍스트에서만 사용할 수 있는 현재 기능들
--------------------------

이 섹션에는 명세를 보안 컨텍스트에서만 사용할 수 있는 API가 나열되어 있습니다.

* Async Clipboard API (en-US)
* Background Sync (예시로 `SyncManager` (en-US)를 보세요.)
* `Cache-Control: immutable`
* Credential Management API
* Device Orientation / Device Motion (en-US)
* EyeDropper API (en-US)
* Encrypted Media Extensions (en-US)
* Generic Sensor API
* `Geolocation`
* Notifications API
* Payment Request API (en-US)
* Presentation API (en-US)
* Push API
* Reporting API (en-US)
* Service Workers
* Storage API (en-US)
* Web Authentication API (en-US)
* Web Bluetooth
* Web MIDI (en-US)
* Web Crypto API (en-US)
* WebGPU API (en-US)
* Web Share API (en-US)

추가로, 다음 메서드에는 보안 컨텍스트가 필요합니다(연결된 API가 필요하지 않더라도).

* `MediaDevices.getUserMedia()` (en-US)
* `Navigator.registerProtocolHandler()`
같이 보기
-----

* 보안 컨텍스트
* Chrome Platform Status에서 "secure context" 검색


양식 자동 완성을 끄는 방법 - 웹 보안

양식 자동 완성을 끄는 방법
===============

이 문서는 웹사이트에서 양식 필드의 자동 완성을 비활성화하는 방법에 대해 설명합니다.

기본적으로 브라우저는 사용자가 웹사이트의 `<input>` (en-US) 필드를 통해 제출한 정보를 기억합니다. 이를 통해 브라우저는 자동 완성(즉, 사용자가 입력하기 시작한 필드에 대해 가능성 있는 완성을 제안) 또는 자동 채우기(즉, 로드 시 특정 필드를 미리 채움)를 제공할 수 있습니다.

일반적으로 이러한 기능은 기본적으로 활성화되어 있지만, 사용자의 개인 정보 보호에 문제가 될 수 있으므로 사용자는 브라우저에서 이 기능을 비활성화할 수 있습니다. 그러나 양식으로 제출된 데이터 중 일부는 향후에 유용하지 않거나(예: 일회성 핀) 민감한 정보(예: 고유한 정부 식별자 또는 신용 카드 보안 코드)를 포함하기 때문에, 웹 사이트 개발자로서, 브라우저의 자동 완성 기능이 활성화된 경우에도 브라우저가 이러한 필드의 값을 기억하지 않기를 원할 수 있습니다.

실제로 WCAG 2.1 Success Criterion 1.3.5: Identify Input Purpose는 자동 완성/자동 채우기가 작동할 것을 요구하지 않습니다. 단지 특정 개인 사용자 정보와 관련된 양식 필드가 프로그래밍 방식으로 식별되기만 하면 됩니다. 즉, 양식 자체에 대한 자동 완성 기능이 꺼진 경우에도 기준을 통과할 수 있습니다(개별 양식 필드에 관련 `autocomplete` 속성을 추가하여).

자동 완성 비활성화하기
------------

양식에서 자동 완성을 비활성화하려면 `autocomplete` 속성을 "off"로 설정합니다.
```

autocomplete="off"
```

전체 양식 또는 양식의 특정 입력 요소에 대해서도 이 작업을 수행할 수 있습니다.

```html
<form method="post" action="/form" autocomplete="off">
  …
</form>
```

```html
<form method="post" action="/form">
  …
  <div>
    <label for="cc">신용 카드:</label>
    <input type="text" id="cc" name="cc" autocomplete="off" />
  </div>
</form>
```

필드에 `autocomplete="off"`를 설정하면 두 가지 효과가 있습니다.

* 브라우저에 따라 이를 준수하는 휴리스틱이 다르긴 하지만, 나중에 비슷한 양식에서 자동 완성을 위해 사용자가 입력한 데이터를 저장하지 않도록 브라우저에 지시합니다.
* 브라우저가 세션 기록에서 양식 데이터를 캐싱 하는 것을 방지합니다. 양식 데이터가 세션 히스토리에 캐시 되면, 사용자가 양식을 제출하고 원래 양식 페이지로 돌아가기 위해 뒤로 가기 버튼을 클릭했을 때, 사용자가 작성한 정보가 표시됩니다.

자동 완성을 해제한 후에도 브라우저가 계속 자동 완성을 제안하는 경우, 입력 요소의 이름 특성을 변경해야 합니다.

자동 완성의 특성과 로그인 필드
-----------------

최신 브라우저는 통합된 비밀번호 관리를 제공합니다. 사용자가 사이트에 대한 사용자 이름과 암호를 입력하면, 브라우저는 사용자를 위해 이를 기억하는 것을 제안합니다. 사용자가 사이트를 다시 방문하면 브라우저는 저장된 값으로 로그인 필드를 자동으로 채웁니다.

또한, 사용자는 브라우저에서 저장된 로그인 정보를 암호화하는 데 사용할 마스터 암호를 선택할 수 있습니다.

마스터 암호가 없더라도 브라우저 내 암호 관리는 일반적으로 전체적인 보안 향상으로 이어집니다. 사용자는 브라우저가 저장한 암호를 기억할 필요가 없기 때문에 암호를 기억해야 하는 경우보다 더 강력한 암호를 선택할 수 있습니다.

이러한 이유로, 많은 최신 브라우저가 로그인 필드에 대해 `autocomplete="off"`를 지원하지 않습니다.

* 사이트에서 사용자 이름과 암호 입력 필드가 포함된 `<form>`에 `autocomplete="off"`를 설정하면, 브라우저는 여전히 이 로그인을 기억하도록 제안하고, 사용자가 동의하면 다음에 사용자가 페이지를 방문할 때 브라우저가 해당 필드를 자동으로 채웁니다.
* 사이트에서 사용자 이름과 비밀번호 `<input>` (en-US) 필드에 `autocomplete="off"`를 설정하면, 브라우저는 여전히 이 로그인을 기억하도록 제안하고, 사용자가 동의하면 다음에 사용자가 페이지를 방문할 때 브라우저가 해당 필드를 자동으로 채웁니다.
### autocomplete="new-password"를 사용하여 자동 채우기 방지하기

사용자가 다른 사람의 새 암호를 지정할 수 있는 사용자 관리 페이지에서 암호 필드의 자동 채우기를 방지하기 위해 `autocomplete="new-password"`를 사용할 수 있습니다.

브라우저는 이 힌트를 준수할 필요가 없습니다. 그러나, 최신 브라우저는 바로 위와 같은 이유로 `autocomplete="new-password"`가 있는 `<input>` 요소의 자동 채우기를 중단했습니다. 예를 들어, Firefox 버전 67(Firefox bug 1119063 참조)은 이 경우에 대해 자동 채우기를 중지했습니다. 그러나, Firefox 70(Firefox bug 1565407 참조)은 안전하게 생성된 암호를 제안할 수 있지만, 저장된 암호를 자동으로 채우지는 않습니다. 자세한 내용은 `autocomplete` 호환성 표를 참조하세요.


지연 로딩 - 웹 성능

지연 로딩
=====

**지연 로딩**은 리소스를 논 블로킹(중요하지 않음)으로 식별하여 필요할 때만 로드하는 전략입니다. 이는 중요 렌더링 경로의 길이를 단축하는 방법으로, 페이지 로드 시간을 감소시킬 수 있습니다.

지연 로딩은 애플리케이션의 여러 순간에 발생할 수 있지만, 일반적으로 스크롤 및 내비게이션과 같은 일부 사용자의 상호 작용에서 발생합니다.

개요
--

웹이 발전함에 따라 사용자에게 보내지는 에셋의 수와 크기가 크게 증가했습니다. 2011년과 2019년 사이에 리소스 무게의 중앙값은 데스크톱의 경우 **~100KB** 에서 **~400KB**로, 모바일의 경우 **~50KB**에서 **~350KB**로 증가했습니다. 반면 이미지 크기는 테스크톱의 경우 **~250KB** 에서 **~900KB**로, 모바일의 경우 **~100KB** 에서 **~850KB**로 증가했습니다.

이 문제를 해결하기 위해 사용할 수 있는 방법 중 하나는 첫 번째 렌더링이 발생하는데 중요하지 않은 리소스를 지연 로딩하여 중요 렌더링 경로 길이를 단축시키는 것입니다. 실제적인 예제로는 장바구니 페이지/섹션으로 연결하는 링크가 있는 전자 상거래 사이트의 홈페이지에 방문했을 때, **해당 페이지로 이동할 때까지** 장바구니 페이지의 리소스(예를 들어 JavaScript, CSS, 이미지)가 다운로드되지 않는 경우를 들 수 있습니다.

전략
--

지연 로딩은 여러 리소스와 전략을 통해 적용될 수 있습니다.

### 일반적인 사용

#### 코드 분할

JavaScript, CSS, HTML을 더 작은 덩어리로 분할할 수 있습니다. 이렇게 하면 값을 제공하는데 요구되는 최소한의 코드만 미리 보내서 페이지 로드 시간을 개선할 수 있습니다. 나머지는 필요에 따라 로드될 수 있습니다.

* 진입점 분할: 앱의 진입점에 따라 코드를 분리합니다.
* 동적 분할: dynamic import() 문이 사용되는 코드를 분리합니다.
### JavaScript

#### 스크립트 type module

`type="module"`이 있는 모든 스크립트 태그는 JavaScript 모듈로 취급되며 기본적으로 지연됩니다.

### CSS

기본적으로 CSS는 렌더링 렌더링 차단 리소스로 취급되므로 브라우저는 CSSOM이 구성될 때까지 어떠한 처리된 콘텐츠를 렌더링하지 않습니다. CSS는 얇고 가능한 빠르게 전달되어야 하며 사용 미디어 타입 및 쿼리는 렌더링 차단을 해제하는 것이 좋습니다.

```html
<link href="style.css" rel="stylesheet" media="all" />
<link href="portrait.css" rel="stylesheet" media="(orientation:portrait)" />
<link href="print.css" rel="stylesheet" media="print" />
```

이를 달성하기 위해 몇몇 CSS 최적화 (en-US)를 수행할 수 있습니다.

### 폰트

기본적으로 폰트 요청은 렌더 트리가 구성될 때까지 지연되므로 텍스트 렌더링이 지연될 수 있습니다.

기본 동작을 재정의하고 `<link rel="preload">`, CSS 폰트 표시 속성 및 폰트 로딩 API (en-US)를 사용하여 웹 폰트 리소스를 미리 로드할 수 있습니다.

같이 보기: Element Link

### 이미지 및 iframes

웹페이지에는 데이터 사용량과 페이지 로드 속도에 영향을 미치는 많은 이미지가 포함되어 있는 경우가 많습니다. 이러한 이미지의 대부분은 화면 밖(중요하지 않음)에 있으므로 스크롤과 같은 사용자 상호 작용이 있어야 볼 수 있습니다.

#### 로딩 속성

`<img>` 요소의 `loading` 속성 또는 `<iframe>` (en-US)의 `loading` (en-US) 속성을 사용하여 화면 밖에 있는 이미지/iframe의 로딩을 사용자가 가까이 스크롤할 때까지 지연시키도록 브라우저에 지시할 수 있습니다. 이렇게 하면 중요하지 않은 리소스가 필요한 경우에만 로드되어 초기 페이지 로드 속도가 빨라지고 네트워크 사용량이 감소할 수 있습니다.

```html
<img src="image.jpg" alt="..." loading="lazy" />
<iframe src="video-player.html" title="..." loading="lazy"></iframe>
```

`load` 이벤트는 열심히 로드된 콘텐츠가 모두 로드되었을 때 발생합니다. 이때 visual viewport 내에 아직 로드되지 않은 느리게 로드된 이미지나 iframe이 있을 수 있습니다. (또는 그럴 가능성이 높습니다.)

지정된 이미지의 불리언 `complete` (en-US) 속성 값을 검사하여 로딩이 완료되었는지 확인할 수 있습니다.

#### Intersection Observer API

Intersection Observers는 관찰된 요소가 브라우저의 뷰포트에 들어오고 나가는 시점을 사용자가 알 수 있도록 해줍니다.

#### 이벤트 처리기

브라우저 호환성이 중요한 경우 몇 가지 옵션이 있습니다.

* polyfill intersection observer
* 특정 요소가 뷰포트에 있는지 확인하기 위해 스크롤, 크기 조정 또는 방향 변경 이벤트 처리기로 대체합니다.
명세서
---

| Specification |
| --- |
| HTML Standard # lazy-loading-attributes |

같이 보기
-----

* Render blocking CSS
* Optimizing loading and rendering
* Lazy loading images and video