mirror of
https://github.com/apache/httpd.git
synced 2025-06-03 10:42:03 +03:00
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@103107 13f79535-47bb-0310-9956-ffa450edef68
584 lines
21 KiB
XML
584 lines
21 KiB
XML
<?xml version='1.0' encoding='EUC-KR' ?>
|
|
<!DOCTYPE manualpage SYSTEM "./style/manualpage.dtd">
|
|
<?xml-stylesheet type="text/xsl" href="./style/manual.ko.xsl"?>
|
|
<!-- English Revision: 1.7 (outdated: 1.16) -->
|
|
|
|
<!--
|
|
Copyright 2003-2004 The Apache Software Foundation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
-->
|
|
|
|
<manualpage metafile="content-negotiation.xml.meta">
|
|
|
|
<title>내용협상 (Content Negotiation)</title>
|
|
|
|
<summary>
|
|
|
|
<p>아파치는 HTTP/1.1 규약에 기술된 내용협상(content
|
|
negotiation)을 지원한다. 내용협상은 media type, 언어, 문자집합,
|
|
인코딩 등에 대해 브라우저가 제공한 선호도에 따라 자원의
|
|
가장 적합한 표현을 선택한다. 또 불완전한 협상 정보를 보내는
|
|
브라우저의 요청을 지능적으로 처리하는 기능도 있다.</p>
|
|
|
|
<p>기본적으로 컴파일되는 <module>mod_negotiation</module>
|
|
모듈이 내용협상 기능을 제공한다.</p>
|
|
</summary>
|
|
|
|
<section id="about"><title>내용협상에 대해</title>
|
|
|
|
<p>자원은 여러 다른 표현을 가질 수 있다. 예를 들어, 다른
|
|
언어나 다른 media type 혹은 둘 모두가 다른 표현들이 있을
|
|
수 있다. 가장 적당한 표현을 선택하는 한가지 방법은 사용자에게
|
|
목록 페이지를 보여주고 선택하게 하는 것이다. 그러나 서버가
|
|
자동으로 선택하는 것도 가능하다. 이는 브라우저가 요청의
|
|
일부로 그들이 선호하는 표현에 대한 정보를 보내기때문에
|
|
가능하다. 예를 들어, 브라우저는 가능한한 불어로, 그러나
|
|
없다면 영어로 정보를 보고싶다고 알려줄 수 있다. 브라우저는
|
|
요청의 헤더로 그들의 기호를 나타낸다. 오직 불어로된 표현만을
|
|
요청한다면 브라우저는 다음과 같이 보낸다.</p>
|
|
|
|
<example>Accept-Language: fr</example>
|
|
|
|
<p>이런 기호는 표현이 언어별로 다를 경우에만 고려된다.</p>
|
|
|
|
<p>다음은 더 복잡한 요청의 예로 브라우저가 불어와 영어를
|
|
받을 수 있지만, 불어를 더 선호하고, 여러 media type을 받을
|
|
수 있지만, 일반 텍스트 보다는 HTML, 다른 media type 보다는
|
|
GIF와 JPEG을 선호한다고 알려준다.</p>
|
|
|
|
<example>
|
|
Accept-Language: fr; q=1.0, en; q=0.5<br />
|
|
Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1
|
|
</example>
|
|
|
|
<p>아파치는 HTTP/1.1 규약에 정의된 '서버 주도(server driven)'
|
|
내용협상을 지원한다. 아파치는 Accept, Accept-Language,
|
|
Accept-Charset, Accept-Encoding 요청 헤더를 모두 지원한다.
|
|
또, 아파치는 RFC 2295와 RFC 2296에 정의된 실험적인 내용협상인
|
|
'자연스러운(transparent)' 요청 헤더도 지원한다.</p>
|
|
|
|
<p><strong>자원(resource)</strong>은 (RFC 2396) URI로 구별하는
|
|
개념적인 존재다. 아파치와 같은 웹서버는 자원의
|
|
<strong>표현(representations)</strong>을 제공한다. 표현은
|
|
지정된 media type, 문자집합, 인코딩 등을 가진 바이트들로
|
|
되있다. 자원은 여러 표현과 (때로는 없을 수도 있다) 연관된다.
|
|
자원에 여러 표현이 있다면 자원을
|
|
<strong>협상가능하다고(negotiable)</strong> 부르며, 이때
|
|
각 표현을 <strong>변형(variant)</strong>이라고 한다.
|
|
협상가능한 자원의 변형 종류를 협상의
|
|
<strong>범위(dimension)</strong>라고 한다.</p>
|
|
</section>
|
|
|
|
<section id="negotiation"><title>아파치의 협상</title>
|
|
|
|
<p>자원을 협상하기위해 서버는 각 변형에 대한 정보가 필요하다.
|
|
다음 두가지 방법중 하나로 정보를 얻는다:</p>
|
|
|
|
<ul>
|
|
<li>변형을 담은 파일들을 직접 열거한 type map을 (<em>예를
|
|
들어</em>, <code>*.var</code> 파일) 사용하거나,</li>
|
|
|
|
<li>직접 지정하지않아도 서버가 파일명에서 규칙을 찾아서
|
|
결과를 선택하는 'MultiViews'를 사용한다.</li>
|
|
</ul>
|
|
|
|
<section id="type-map"><title>type-map 파일 사용하기</title>
|
|
|
|
<p>type map은 <code>type-map</code>이란 핸들러와 연결된
|
|
(혹은 이전 아파치 설정과 호환을 위해 mime type이
|
|
<code>application/x-type-map</code>인) 문서다. 이 기능을
|
|
사용하려면 설정에서 <code>type-map</code> 핸들러에 대한
|
|
파일 확장자를 지정해야 한다. 서버 설정파일에 다음과 같이
|
|
설정하는 것이 좋다.</p>
|
|
<example>AddHandler type-map .var</example>
|
|
|
|
<p>Type map 파일은 해당하는 자원과 이름이 같아야 하고,
|
|
각 변형에 대한 항목이 있어야 한다. 항목은 여러 HTTP형식
|
|
헤더 줄로 구성된다. 변형에 대한 각각의 항목들은 빈줄로
|
|
구분한다. 항목안에서 빈줄을 사용할 수 없다. (이렇게 할
|
|
필요가 없고, 있어도 무시하지만) 여러 항목이 공통으로 가지고
|
|
있는 내용으로 map 파일을 시작하는 것이 보통이다. 다음은
|
|
map 파일 예다. 이 파일의 이름은 <code>foo.var</code>로,
|
|
<code>foo</code>라는 자원을 설명한다.</p>
|
|
|
|
<example>
|
|
URI: foo<br />
|
|
<br />
|
|
URI: foo.en.html<br />
|
|
Content-type: text/html<br />
|
|
Content-language: en<br />
|
|
<br />
|
|
URI: foo.fr.de.html<br />
|
|
Content-type: text/html;charset=iso-8859-2<br />
|
|
Content-language: fr, de<br />
|
|
</example>
|
|
<p>typemap 파일이 파일명 확장자 보다, 심지어 Multiviews를
|
|
사용하여도, 우선권을 가짐을 주의하라. 변형이 서로 다른 품질을
|
|
가진다면, 다음과 같이 (jpeg, gif, ASCII-art에 해당하는)
|
|
media type에 "qs" 파라미터로 품질(source quality)을 표시할
|
|
수 있다:</p>
|
|
|
|
<example>
|
|
URI: foo<br />
|
|
<br />
|
|
URI: foo.jpeg<br />
|
|
Content-type: image/jpeg; qs=0.8<br />
|
|
<br />
|
|
URI: foo.gif<br />
|
|
Content-type: image/gif; qs=0.5<br />
|
|
<br />
|
|
URI: foo.txt<br />
|
|
Content-type: text/plain; qs=0.01<br />
|
|
</example>
|
|
|
|
<p>qs 값은 0.000에서 1.000 사이다. qs 값이 0.000인 변형은
|
|
절대 선택되지 않음을 주의하라. 'qs' 값이 없는 변형은 1.0으로
|
|
취급된다. qs 값은 클라이언트의 능력과는 관계없이 다른 변형들과
|
|
비교하여 그 변형의 상대적인 '품질'을 나타낸다. 예를 들어,
|
|
사진을 나타내려는 경우 jpeg 파일이 ascii 파일보다는 항상
|
|
높은 품질을 가진다. 그러나 자원이 원래 ascii art였다면
|
|
ascii 표현이 jpeg 표현보다 더 높은 품질을 가질 수 있다.
|
|
그러므로 어떤 변형의 qs 값은 표현하려는 자원의 성질에
|
|
따라 다르다.</p>
|
|
|
|
<p>지원하는 모든 헤더 목록은 <a
|
|
href="mod/mod_negotiation.html#typemaps">mod_negotation
|
|
typemap</a> 문서를 참고하라.</p>
|
|
</section>
|
|
|
|
<section id="multiviews"><title>Multiviews</title>
|
|
|
|
<p><code>MultiViews</code>는 디렉토리별 옵션이므로,
|
|
<code>httpd.conf</code>의
|
|
<directive module="core" type="section">Directory</directive>,
|
|
<directive module="core" type="section">Location</directive>,
|
|
<directive module="core" type="section">Files</directive>
|
|
섹션 혹은 (<directive module="core">AllowOverride</directive>가
|
|
적절히 설정되었다면) <code>.htaccess</code> 파일의
|
|
<directive module="core">Options</directive> 지시어에 설정할
|
|
수 있다. <code>Options All</code>은 <code>MultiViews</code>를
|
|
포함하지않음을 주의하라. 따로 직접 써줘야 한다.</p>
|
|
|
|
<p><code>MultiViews</code>를 사용하면 다음과 같은 일이 일어난다:
|
|
서버가 <code>/some/dir/foo</code>에 대한 요청을 받고
|
|
<code>/some/dir/foo</code>에 <code>MultiViews</code>가 동작하며
|
|
<code>/some/dir/foo</code>가 존재하지 <em>않을</em> 경우,
|
|
서버는 디렉토리에서 이름이 foo.*인 파일들을 모든 포함하는
|
|
가상의 type map을 만든다. 클라이언트가 요청한 media type과
|
|
content-encoding을 가지고 이중에 가장 적합한 것을 선택한다.</p>
|
|
|
|
<p><code>MultiViews</code>는 서버가 디렉토리를 참조할때
|
|
파일을 찾는 <directive
|
|
module="mod_dir">DirectoryIndex</directive> 지시어에도
|
|
적용된다. 설정파일이 다음과 같다면,</p>
|
|
<example>DirectoryIndex index</example>
|
|
<p><code>index.html</code>과 <code>index.html3</code>이
|
|
모두 있다면 서버는 이둘 중에 하나를 결정한다. 둘 모두 없고
|
|
<code>index.cgi</code>가 있다면, 서버는 그것을 실행한다.</p>
|
|
|
|
<p>디렉토리를 읽을때 파일중 하나가 Charset, Content-Type,
|
|
Language, Encoding를 판단하는 <code>mod_mime</code>이 모르는
|
|
확장자를 가진다면, 결과는 <directive
|
|
module="mod_mime">MultiViewsMatch</directive> 지시어 설정에
|
|
달렷다. 이 지시어는 핸들러, 필터, 다른 확장형들이 MultiViews
|
|
협상에 참여할지 여부를 결정한다.</p>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="methods"><title>협상방법</title>
|
|
|
|
<p>아파치가 type-map 파일이나 디렉토리에 있는 파일명들로
|
|
주어진 자원에 대한 변형 목록을 얻게되면 '최적의' 변형을
|
|
결정하기위해 두 방법중 하나를 사용한다. 아파치 내용협상
|
|
기능을 사용하기위해 정확히 협상이 어떻게 일어나는지 자세히
|
|
알 필요는 없다. 그러나 궁금한 사람을 위해 이 방법을 설명한다.</p>
|
|
|
|
<p>두가지 협상방법이 있다:</p>
|
|
|
|
<ol>
|
|
<li><strong>아파치 알고리즘을 사용하여 서버가 주도하는
|
|
협상</strong>은 일반적인 경우에 사용한다. 아파치 알고리즘은
|
|
아래서 자세히 설명한다. 이 알고리즘을 사용하면 아파치는
|
|
더 나은 결과를 얻기위해 종종 특정 범위의
|
|
품질계수(quality factor)를 '조작한다'. 아파치가 품질계수를
|
|
조작하는 방법은 아래서 자세히 설명한다.</li>
|
|
|
|
<li><strong>자연스러운(Transparent) 내용협상</strong>은
|
|
브라우저가 RFC 2295에 정의된 방법으로 요청할 경우에만
|
|
사용한다. 이 협상방법은 '최적의' 변형을 결정할 권한을
|
|
브라우저에게 부여한다. 그래서 결과는 브라우저의 알고리즘에
|
|
달렸다. 자연스러운 협상과정중에 브라우저는 아파치에게
|
|
RFC 2296에 정의된 '원격 변형선택 알고리즘(remote variant
|
|
selection algorithm)'을 요청할 수 있다.</li>
|
|
</ol>
|
|
|
|
<section id="dimensions"><title>협상의 범위</title>
|
|
|
|
<table>
|
|
<tr valign="top">
|
|
<th>범위</th>
|
|
|
|
<th>설명</th>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td>Media Type</td>
|
|
|
|
<td>브라우저는 Accept 헤더로 선호를 나타낸다. 각 항목은
|
|
품질계수를 가질 수 있다. 변형의 설명도 품질계수를 ("qs"
|
|
파라미터) 가질 수 있다.</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td>Language</td>
|
|
|
|
<td>브라우저는 Accept-Language 헤더로 선호를 나타낸다.
|
|
각 항목은 품질계수를 가질 수 있다. 변형은 여러 언어를
|
|
가질 (혹은 아무 언어도 없을) 수 있다.</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td>Encoding</td>
|
|
|
|
<td>브라우저는 Accept-Encoding 헤더로 선호를 나타낸다.
|
|
각 항목은 품질계수를 가질 수 있다.</td>
|
|
</tr>
|
|
|
|
<tr valign="top">
|
|
<td>Charset</td>
|
|
|
|
<td>브라우저는 Accept-Charset 헤더로 선호를 나타낸다.
|
|
각 항목은 품질계수를 가질 수 있다. 변형은 media type의
|
|
파라미터로 문자집합을 나타낼 수 있다.</td>
|
|
</tr>
|
|
</table>
|
|
</section>
|
|
|
|
<section id="algorithm"><title>아파치 협상 알고리즘</title>
|
|
|
|
<p>아파치는 브라우저에게 보낼 '최적의' 변형을 (있다면)
|
|
선택하기위해 아래 알고리즘을 사용한다. 이 알고리즘은 변경할
|
|
수 없다. 다음와 같이 동작한다:</p>
|
|
|
|
<ol>
|
|
<li>먼저, 협상의 각 범위에 대해 해당하는 <em>Accept*</em>
|
|
헤더를 검사하고, 각 변형에 품질값을 매긴다. 어떤 범위의
|
|
<em>Accept*</em> 헤더가 받아들이지 않는 변형은 후보에서
|
|
제외한다. 어떤 변형도 남지않으면 4 단계로 간다.</li>
|
|
|
|
<li>
|
|
후보에서 하나씩 제외하여 '최적의' 변형을 찾는다. 다음
|
|
각 검사는 순서대로 일어난다. 각 검사에서 선택되지않은
|
|
변형은 제외된다. 각 검사후 한 변형만 남으면 이를 최적의
|
|
변형으로 선택하고 3 단계로 간다. 여러 변형이 남으면
|
|
다음 검사를 진행한다.
|
|
|
|
<ol>
|
|
<li>Accept 헤더의 품질계수와 변형의 media type에 대한
|
|
품질값을 곱하여 가장 높은 값을 가진 변형을 선택한다.</li>
|
|
|
|
<li>가장 높은 언어(language) 품질계수를 가진 변형을
|
|
선택한다.</li>
|
|
|
|
<li>Accept-Language 헤더에 (있다면) 나온 언어의 순서
|
|
혹은 <code>LanguagePriority</code> 지시어에 (있다면)
|
|
나온 언어의 순서를 가지고 가장 적합한 언어를 가진
|
|
변형을 선택한다.</li>
|
|
|
|
<li>가장 높은 (text/html media type의 버전을 나타내는)
|
|
'level' media 파라미터를 가진 변형을 선택한다.</li>
|
|
|
|
<li>Accept-Charset 헤더를 가지고 가장 적합한 charset
|
|
media 파라미터를 가진 변형을 찾는다. 헤더가 없다면
|
|
ISO-8859-1 문자집합을 가장 선호한다. <code>text/*</code>
|
|
media type을 가지지만 명시적으로 특정 문자집합과
|
|
연결되지않은 변형은 ISO-8859-1로 가정한다.</li>
|
|
|
|
<li>ISO-8859-1이 <em>아닌</em> charset media 파라미터를
|
|
가진 변형들을 선택한다. 그런 변형이 없다면, 대신 모든
|
|
변형을 선택한다.</li>
|
|
|
|
<li>가장 적합한 인코딩을 가진 변형을 선택한다.
|
|
user-agent에 적합한 인코딩을 가진 변형이 있다면 그
|
|
변형만을 선택한다. 그렇지않고 인코딩된 변형과 인코딩안된
|
|
변형이 같이 있다면 인코딩안됨 변형만을 선택한다. 변형이
|
|
모두 인코딩되었거나 모두 인코딩안된 경우 모든 변형을
|
|
선택한다.</li>
|
|
|
|
<li>content length가 가장 적은 변형을 선택한다.</li>
|
|
|
|
<li>남은 것중 첫번재 변형을 선택한다. 이는 type-map
|
|
파일의 앞에 나왔거나, 디렉토리에서 변형을 읽은 경우
|
|
파일명을 ASCII 코드 순서로 하여 앞에 나오는 것이다.</li>
|
|
</ol>
|
|
</li>
|
|
|
|
<li>이제 알고리즘이 '최적의' 변형을 선택했다. 이것을 응답으로
|
|
보낸다. HTTP 응답 헤더 Vary는 협상의 범위를 나타내게 된다.
|
|
(브라우저와 캐쉬는 자원을 캐쉬할때 이 정보를 사용할 수
|
|
있다.) 끝.</li>
|
|
|
|
<li>이 단계에 도달했다면 (모두 브라우저가 받지못하기 때문에)
|
|
어떤 변형도 선택이 안된 경우다. ("No acceptable
|
|
representation"를 뜻하는) 상태 406과 내용으로 사용가능한
|
|
변형의 목록을 담은 HTML 문서를 응답을 보낸다. 또, HTML
|
|
Vary 헤더는 변형의 범위를 나타낸다.</li>
|
|
</ol>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="better"><title>품질계수 조작하기</title>
|
|
|
|
<p>아파치는 종종 위의 아파치 협상 알고리즘을 엄격히 지키지않고
|
|
품질계수를 변경한다. 이유는 완전하고 정확한 정보를 보내지않는
|
|
브라우저에게 (알고리즘의) 더 나은 결과를 보내기 위해서다.
|
|
널리 쓰이는 브라우저중 일부는 자주 잘못된 변형을 선택하도록
|
|
Accept 헤더를 보낸다. 브라우저가 완전하고 올바른 정보를
|
|
보낸다면, 조작을 하지않는다.</p>
|
|
|
|
<section id="wildcards"><title>Media Type과 와일드카드</title>
|
|
|
|
<p>Accept: 요청 헤더는 media type에 대한 선호를 나타낸다.
|
|
또, *는 어떤 문자열이라도 가능하기때문에 "image/*"나 "*/*"
|
|
같이 '와일드카드' media type을 사용할 수도 있다. 그래서
|
|
다음과 같은 요청은:</p>
|
|
|
|
<example>Accept: image/*, */*</example>
|
|
|
|
<p>"image/"로 시작하는 어떤 type과 다른 어떤 type도 가능함을
|
|
의미한다. 어떤 브라우저는
|
|
자신이 실제로 다룰 수 있는 type에 추가로 와일드카드를 보낸다.
|
|
예를 들면:</p>
|
|
|
|
<example>
|
|
Accept: text/html, text/plain, image/gif, image/jpeg, */*
|
|
</example>
|
|
<p>이유는 직접 열거한 type을 선호하지만 다른 표현이 있다면
|
|
그것도 괜찮음을 나타내기 위해서다. 브라우저가 실제로 원한
|
|
것은 다음과 같이 명시적으로 품질값을 사용한 것이다.</p>
|
|
<example>
|
|
Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01
|
|
</example>
|
|
<p>직접 열거한 type은 품질계수가 없어서 기본값인 (가장 높은)
|
|
1.0을 가진다. 와일드카드 */*는 낮은 선호도 0.01을 가지므로
|
|
직접 열거한 type에 맞는 변형이 없는 경우에만 다른 type들이
|
|
사용된다.</p>
|
|
|
|
<p>Accept: 헤더에 q 계수가 전혀 <em>없고</em> "*/*"가 있다면,
|
|
아파치는 바람직한 행동을 위해 q 값으로 0.01을 지정한다.
|
|
또, "type/*" 형태의 와일드카드에는 ("*/*"보다는 더 선호하도록)
|
|
0.02를 지정한다. Accept: 헤더에서 q 계수를 가지는 media type이
|
|
있다면 이런 특별한 값을 추가하지 <em>않는다</em>. 그래서
|
|
명시적인 정보를 보내는 브라우저의 요청은 요청한데로 처리한다.</p>
|
|
</section>
|
|
|
|
<section id="exceptions"><title>언어(language) 협상의 예외</title>
|
|
|
|
<p>아파치 2.0은 언어 협상이 실패한 경우 부드럽게 복구하기위해
|
|
협상 알고리즘에 새로 예외를 몇개 추가했다.</p>
|
|
|
|
<p>클라이언트가 서버에 페이지를 요청했을때 서버가 브라우저가
|
|
보낸 Accept-language에 맞는 페이지를 단 한개만 찾으면 문제가
|
|
없지만, 그러지 않은 경우 서버는 클라이언트에게 "No Acceptable
|
|
Variant"나 "Multiple Choices" 응답을 보낸다. 이런 오류문을
|
|
피하기위해 이 경우 Accept-language를 무시하고 클라이언트의
|
|
요청에 명확히 맞지는 않지만 문서를 보내도록 아파치를 설정할
|
|
수 있다. <directive
|
|
module="mod_negotiation">ForceLanguagePriority</directive>
|
|
지시어는 서버가 이런 오류문중 하나 혹은 둘다를 무시하고
|
|
<directive module="mod_negotiation">LanguagePriority</directive>
|
|
지시어로 판단하도록 한다.</p>
|
|
|
|
<p>또, 서버는 맞는 언어를 못찾은 경우 부모언어를 찾을 수도
|
|
있다. 예를 들어 클라이언트가 영국영어를 뜻하는
|
|
<code>en-GB</code> 언어로 문서를 요청한 경우, HTTP/1.1 표준에
|
|
따르면 서버는 <code>en</code>으로만 표시된 문서를 일반적으로
|
|
선택하지 못한다. (그래서 영국영어를 이해하는 독자가 일반적인
|
|
영어도 이해할 수 있으므로 Accept-Language 헤더에
|
|
<code>en-GB</code>만 포함하고 <code>en</code>을 포함하지않으면
|
|
거의 확실히 잘못된 설정임을 유의하라. 불행히도 현재 많은
|
|
클라이언트들은 이런 식으로 기본설정되있다.) 다른 언어를
|
|
찾지 못하여 서버가 "No Acceptable Variants" 오류를 보내거나
|
|
<directive module="mod_negotiation">LanguagePriority</directive>로
|
|
돌아가야 한다면, 서버는 하위언어 규약을 무시하고
|
|
<code>en-GB</code>를 <code>en</code> 문서에 대응한다.
|
|
암묵적으로 아파치는 부모언어를 매우 낮은 품질값으로
|
|
클라이언트의 허용언어 목록에 추가한다. 그러나 클라이언트가
|
|
"en-GB; q=0.9, fr; q=0.8"을 요청하고 서버에 "en"과 "fr"
|
|
문서가 있다면, "fr" 문서가 선택됨을 주의하라. 이는 HTTP/1.1
|
|
표준을 지키고, 올바로 설정된 클라이언트와 효율적으로
|
|
동작하기위함이다.</p>
|
|
|
|
<p>사용자가 선호하는 언어를 알아내기위한 (쿠키나 특별한
|
|
URL-경로 같은) 고급 기법을 지원하기위해 아파치 2.1부터
|
|
<module>mod_negotiation</module>은 <code>prefer-language</code>라는
|
|
<a href="env.html">환경변수</a>를 인식한다. 이 환경변수가
|
|
존재하고 적절한 언어태그를 포함한다면,
|
|
<module>mod_negotiation</module>은 해당하는 변형을 선택하려고
|
|
시도한다. 그런 변형이 없다면 일반적인 협상과정을 시작한다.</p>
|
|
|
|
<example><title>예제</title>
|
|
SetEnvIf Cookie "language=(.+)" prefer-language=$1
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="extensions"><title>자연스러운(transparent) 내용협상의 확장</title>
|
|
|
|
<p>아파치는 다음과 같이 자연스러운 내용확장 프로토콜을 (RFC 2295)
|
|
확장한다. 변형 목록의 새로운 <code>{encoding ..}</code>는 특정
|
|
content-encoding을 가진 변형만을 지칭한다. RVSA/1.0 알고리즘은
|
|
(RFC 2296) 목록에서 인코딩된 변형을 인식할 수 있고, 인코딩이
|
|
Accept-Encoding 요청 헤더에 맞는 경우 인코딩된 변형들도 후보로
|
|
사용하도록 확장되었다. RVSA/1.0 구현은 최적의 변형을 찾기 전에
|
|
계산된 품질계수를 소수점 5자리에서 반올림하지 않는다.</p>
|
|
</section>
|
|
|
|
<section id="naming"><title>하이퍼링크와 이름규칙에 대하여</title>
|
|
|
|
<p>언어(language) 협상을 사용한다면 파일은 여러 확장자를
|
|
가지고 확장자의 순서는 보통 관계없으므로 파일명에 여러 다른
|
|
이름규칙을 사용할 수 있다. (자세한 내용은 <a
|
|
href="mod/mod_mime.html#multipleext">mod_mime</a> 문서를
|
|
참고하라.)</p>
|
|
|
|
<p>전형적인 파일은 MIME-type 확장자 (<em>예를 들어</em>,
|
|
<code>html</code>), 경우에 따라 encoding 확장자 (<em>예를
|
|
들어</em>, <code>gz</code>), 파일에 여러 언어 변형이 있는
|
|
경우 물론 언어 확장자를 (<em>예를 들어</em>, <code>en</code>)
|
|
가진다.</p>
|
|
|
|
<p>예제:</p>
|
|
|
|
<ul>
|
|
<li>foo.en.html</li>
|
|
|
|
<li>foo.html.en</li>
|
|
|
|
<li>foo.en.html.gz</li>
|
|
</ul>
|
|
|
|
<p>다음은 몇몇 파일명과 그 파일에 대한 유효하고 유효하지않은
|
|
하이퍼링크를 보인다:</p>
|
|
|
|
<table border="1" cellpadding="8" cellspacing="0">
|
|
<tr>
|
|
<th>파일명</th>
|
|
|
|
<th>유효한 하이퍼링크</th>
|
|
|
|
<th>유효하지않은 하이퍼링크</th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td><em>foo.html.en</em></td>
|
|
|
|
<td>foo<br />
|
|
foo.html</td>
|
|
|
|
<td>-</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td><em>foo.en.html</em></td>
|
|
|
|
<td>foo</td>
|
|
|
|
<td>foo.html</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td><em>foo.html.en.gz</em></td>
|
|
|
|
<td>foo<br />
|
|
foo.html</td>
|
|
|
|
<td>foo.gz<br />
|
|
foo.html.gz</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td><em>foo.en.html.gz</em></td>
|
|
|
|
<td>foo</td>
|
|
|
|
<td>foo.html<br />
|
|
foo.html.gz<br />
|
|
foo.gz</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td><em>foo.gz.html.en</em></td>
|
|
|
|
<td>foo<br />
|
|
foo.gz<br />
|
|
foo.gz.html</td>
|
|
|
|
<td>foo.html</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td><em>foo.html.gz.en</em></td>
|
|
|
|
<td>foo<br />
|
|
foo.html<br />
|
|
foo.html.gz</td>
|
|
|
|
<td>foo.gz</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p>위 표를 보면 하이퍼링크에 어떤 확장자도 없는 이름을
|
|
(<em>예를 들어</em>, <code>foo</code>) 항상 사용할 수 있음을
|
|
알 수 있다. 이 경우 장점은 문서의 실제 종류를 숨길 수 있어서,
|
|
<em>예를 들어</em> 하이러링크 참조를 수정하않고
|
|
<code>html</code> 파일을 <code>shtml</code>이나
|
|
<code>cgi</code>로 변경할 수 있다는 점이다.</p>
|
|
|
|
<p>계속 하이퍼링크에 MIME-type을 (<em>예를 들어</em>,
|
|
<code>foo.html</code>) 사용하고 싶다면 (encoding 확장자가
|
|
있다면 이것도 포함하여) 언어 확장자를 MIME-type 확장자보다
|
|
오른쪽에 (<em>예를 들어</em>, <code>foo.html.en</code>)
|
|
두어야한다.</p>
|
|
</section>
|
|
|
|
<section id="caching"><title>캐쉬에 대하여</title>
|
|
|
|
<p>캐쉬가 표현을 저장하면 표현과 요청 URL을 연관시킨다.
|
|
다음번 그 URL을 요청하면 캐쉬는 저장된 표현을 사용한다.
|
|
그러나 서버와 협상이 가능한 자원인 경우 첫번째 요청한 변형만
|
|
캐쉬되어 이후 요청은 캐쉬된 잘못된 응답을 얻을 수 있다.
|
|
이를 막기위해 아파치는 보통 내용협상후 반환되는 모든 요청에
|
|
HTTP/1.0 클라이언트가 캐쉬를 못하도록 표시를 한다. 또, 아파치는
|
|
협상한 응답의 캐쉬를 허용하는 HTTP/1.1 프로토콜의 기능을
|
|
지원한다.</p>
|
|
|
|
<p><directive
|
|
module="mod_negotiation">CacheNegotiatedDocs</directive>
|
|
지시어는 HTTP/1.0 호환 클라이언트(브라우저 혹은 캐쉬)가
|
|
보낸 요청에 대해 협상한 응답을 캐쉬할 수 있게 한다. 이 지시어는
|
|
서버나 가상호스트 설정에 사용하며, 아규먼트를 받지않는다.
|
|
이 지시어는 HTTP/1.1 클라이언트의 요청과는 관계가 없다.</p>
|
|
</section>
|
|
|
|
<section id="more"><title>다른 정보</title>
|
|
|
|
<p>내용협상에 대한 다른 정보는 Alan J. Flavell가 쓴 <a
|
|
href="http://ppewww.ph.gla.ac.uk/~flavell/www/lang-neg.html">Language
|
|
Negotiation Notes</a>를 참고하라. 그러나 이 문서는 아직
|
|
아파치 2.0의 변화를 반영하지 않을 수 있다.</p>
|
|
</section>
|
|
|
|
</manualpage>
|