Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
<?xml version="1.0" encoding="EUC-KR"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko"><head>
<meta content="text/html; charset=EUC-KR" http-equiv="Content-Type" />
<!--
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This file is generated from xml source: DO NOT EDIT
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-->
<title>내용협상 (Content Negotiation) - Apache HTTP Server Version 2.4</title>
<link href="./style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
<link href="./style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
<link href="./style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="./style/css/prettify.css" />
<script src="./style/scripts/prettify.min.js" type="text/javascript">
</script>
<link href="./images/favicon.ico" rel="shortcut icon" /></head>
<body id="manual-page"><div id="page-header">
<p class="menu"><a href="./mod/">모듈</a> | <a href="./mod/directives.html">지시어들</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="./glossary.html">용어</a> | <a href="./sitemap.html">사이트맵</a></p>
<p class="apache">Apache HTTP Server Version 2.4</p>
<img alt="" src="./images/feather.png" /></div>
<div class="up"><a href="./"><img title="<-" alt="<-" src="./images/left.gif" /></a></div>
<div id="path">
<a href="http://www.apache.org/">Apache</a> > <a href="http://httpd.apache.org/">HTTP Server</a> > <a href="http://httpd.apache.org/docs/">Documentation</a> > <a href="./">Version 2.4</a></div><div id="page-content"><div id="preamble"><h1>내용협상 (Content Negotiation)</h1>
<div class="toplang">
<p><span>가능한 언어: </span><a href="./en/content-negotiation.html" hreflang="en" rel="alternate" title="English"> en </a> |
<a href="./fr/content-negotiation.html" hreflang="fr" rel="alternate" title="Français"> fr </a> |
<a href="./ja/content-negotiation.html" hreflang="ja" rel="alternate" title="Japanese"> ja </a> |
<a href="./ko/content-negotiation.html" title="Korean"> ko </a> |
<a href="./tr/content-negotiation.html" hreflang="tr" rel="alternate" title="Türkçe"> tr </a></p>
</div>
<div class="outofdate">이 문서는 최신판 번역이 아닙니다.
최근에 변경된 내용은 영어 문서를 참고하세요.</div>
<p>아파치는 HTTP/1.1 규약에 기술된 내용협상(content
negotiation)을 지원한다. 내용협상은 media type, 언어, 문자집합,
인코딩 등에 대해 브라우저가 제공한 선호도에 따라 자원의
가장 적합한 표현을 선택한다. 또 불완전한 협상 정보를 보내는
브라우저의 요청을 지능적으로 처리하는 기능도 있다.</p>
<p>기본적으로 컴파일되는 <code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code>
모듈이 내용협상 기능을 제공한다.</p>
</div>
<div id="quickview"><a href="https://www.apache.org/foundation/contributing.html" class="badge"><img src="https://www.apache.org/images/SupportApache-small.png" alt="Support Apache!" /></a><ul id="toc"><li><img alt="" src="./images/down.gif" /> <a href="#about">내용협상에 대해</a></li>
<li><img alt="" src="./images/down.gif" /> <a href="#negotiation">아파치의 협상</a></li>
<li><img alt="" src="./images/down.gif" /> <a href="#methods">협상방법</a></li>
<li><img alt="" src="./images/down.gif" /> <a href="#better">품질계수 조작하기</a></li>
<li><img alt="" src="./images/down.gif" /> <a href="#extensions">자연스러운(transparent) 내용협상의 확장</a></li>
<li><img alt="" src="./images/down.gif" /> <a href="#naming">하이퍼링크와 이름규칙에 대하여</a></li>
<li><img alt="" src="./images/down.gif" /> <a href="#caching">캐쉬에 대하여</a></li>
</ul><h3>참고</h3><ul class="seealso"><li><a href="#comments_section">Comments</a></li></ul></div>
<div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="about" id="about">내용협상에 대해</a></h2>
<p>자원은 여러 다른 표현을 가질 수 있다. 예를 들어, 다른
언어나 다른 media type 혹은 둘 모두가 다른 표현들이 있을
수 있다. 가장 적당한 표현을 선택하는 한가지 방법은 사용자에게
목록 페이지를 보여주고 선택하게 하는 것이다. 그러나 서버가
자동으로 선택하는 것도 가능하다. 이는 브라우저가 요청의
일부로 그들이 선호하는 표현에 대한 정보를 보내기때문에
가능하다. 예를 들어, 브라우저는 가능한한 불어로, 그러나
없다면 영어로 정보를 보고싶다고 알려줄 수 있다. 브라우저는
요청의 헤더로 그들의 기호를 나타낸다. 오직 불어로된 표현만을
요청한다면 브라우저는 다음과 같이 보낸다.</p>
<div class="example"><p><code>Accept-Language: fr</code></p></div>
<p>이런 기호는 표현이 언어별로 다를 경우에만 고려된다.</p>
<p>다음은 더 복잡한 요청의 예로 브라우저가 불어와 영어를
받을 수 있지만, 불어를 더 선호하고, 여러 media type을 받을
수 있지만, 일반 텍스트 보다는 HTML, 다른 media type 보다는
GIF와 JPEG을 선호한다고 알려준다.</p>
<div class="example"><p><code>
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
</code></p></div>
<p>아파치는 HTTP/1.1 규약에 정의된 '서버 주도(server driven)'
내용협상을 지원한다. 아파치는 <code>Accept</code>,
<code>Accept-Language</code>, <code>Accept-Charset</code>,
<code>Accept-Encoding</code> 요청 헤더를 모두 지원한다.
또, 아파치는 RFC 2295와 RFC 2296에 정의된 실험적인 내용협상인
'자연스러운(transparent)' 요청 헤더도 지원한다. 그러나 이
RFC에 정의된 '기능 협상(feature negotiation)'은 지원하지
않는다.</p>
<p><strong>자원(resource)</strong>은 (RFC 2396) URI로 구별하는
개념적인 존재다. 아파치와 같은 웹서버는 자원의
<strong>표현(representations)</strong>을 제공한다. 표현은
지정된 media type, 문자집합, 인코딩 등을 가진 바이트들로
되있다. 자원은 여러 표현과 (때로는 없을 수도 있다) 연관된다.
자원에 여러 표현이 있다면 자원을
<strong>협상가능하다고(negotiable)</strong> 부르며, 이때
각 표현을 <strong>변형(variant)</strong>이라고 한다.
협상가능한 자원의 변형 종류를 협상의
<strong>범위(dimension)</strong>라고 한다.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="negotiation" id="negotiation">아파치의 협상</a></h2>
<p>자원을 협상하기위해 서버는 각 변형에 대한 정보가 필요하다.
다음 두가지 방법중 하나로 정보를 얻는다:</p>
<ul>
<li>변형을 담은 파일들을 직접 열거한 type map을 (<em>예를
들어</em>, <code>*.var</code> 파일) 사용하거나,</li>
<li>직접 지정하지않아도 서버가 파일명에서 규칙을 찾아서
결과를 선택하는 'MultiViews'를 사용한다.</li>
</ul>
<h3><a name="type-map" id="type-map">type-map 파일 사용하기</a></h3>
<p>type map은 <code>type-map</code>이란 핸들러와 연결된
(혹은 이전 아파치 설정과 호환을 위해 MIME type이
<code>application/x-type-map</code>인) 문서다. 이 기능을
사용하려면 설정에서 <code>type-map</code> 핸들러에 대한
파일 확장자를 지정해야 한다. 서버 설정파일에 다음과 같이
설정하는 것이 좋다.</p>
<div class="example"><p><code>AddHandler type-map .var</code></p></div>
<p>Type map 파일은 해당하는 자원과 이름이 같아야 하고,
각 변형에 대한 항목이 있어야 한다. 항목은 여러 HTTP형식
헤더 줄로 구성된다. 변형에 대한 각각의 항목들은 빈줄로
구분한다. 항목안에서 빈줄을 사용할 수 없다. (이렇게 할
필요가 없고, 있어도 무시하지만) 여러 항목이 공통으로 가지고
있는 내용으로 map 파일을 시작하는 것이 보통이다. 다음은
map 파일 예다. 이 파일의 이름은 <code>foo.var</code>로,
<code>foo</code>라는 자원을 설명한다.</p>
<div class="example"><p><code>
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 />
</code></p></div>
<p>typemap 파일이 파일명 확장자 보다, 심지어 Multiviews를
사용하여도, 우선권을 가짐을 주의하라. 변형이 서로 다른 품질을
가진다면, 다음과 같이 (JPEG, GIF, ASCII-art에 해당하는)
media type에 "qs" 파라미터로 품질(source quality)을 표시할
수 있다:</p>
<div class="example"><p><code>
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 />
</code></p></div>
<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>
<h3><a name="multiviews" id="multiviews">Multiviews</a></h3>
<p><code>MultiViews</code>는 디렉토리별 옵션이므로,
<code>httpd.conf</code>의
<code class="directive"><a href="./mod/core.html#directory"><Directory></a></code>,
<code class="directive"><a href="./mod/core.html#location"><Location></a></code>,
<code class="directive"><a href="./mod/core.html#files"><Files></a></code>
섹션 혹은 (<code class="directive"><a href="./mod/core.html#allowoverride">AllowOverride</a></code>가
적절히 설정되었다면) <code>.htaccess</code> 파일의
<code class="directive"><a href="./mod/core.html#options">Options</a></code> 지시어에 설정할
수 있다. <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>는 서버가 디렉토리를 참조할때
파일을 찾는 <code class="directive"><a href="./mod/mod_dir.html#directoryindex">DirectoryIndex</a></code> 지시어에도
적용된다. 설정파일이 다음과 같다면,</p>
<div class="example"><p><code>DirectoryIndex index</code></p></div>
<p><code>index.html</code>과 <code>index.html3</code>이
모두 있다면 서버는 이둘 중에 하나를 결정한다. 둘 모두 없고
<code>index.cgi</code>가 있다면, 서버는 그것을 실행한다.</p>
<p>디렉토리를 읽을때 파일중 하나가 Charset, Content-Type,
Language, Encoding를 판단하는 <code>mod_mime</code>이 모르는
확장자를 가진다면, 결과는 <code class="directive"><a href="./mod/mod_mime.html#multiviewsmatch">MultiViewsMatch</a></code> 지시어 설정에
달렷다. 이 지시어는 핸들러, 필터, 다른 확장형들이 MultiViews
협상에 참여할지 여부를 결정한다.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="methods" id="methods">협상방법</a></h2>
<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>
<h3><a name="dimensions" id="dimensions">협상의 범위</a></h3>
<table>
<tr valign="top">
<th>범위</th>
<th>설명</th>
</tr>
<tr valign="top">
<td>Media Type</td>
<td>브라우저는 <code>Accept</code> 헤더로 선호를 나타낸다.
각 항목은 품질계수를 가질 수 있다. 변형의 설명도 품질계수를
("qs" 파라미터) 가질 수 있다.</td>
</tr>
<tr valign="top">
<td>Language</td>
<td>브라우저는 <code>Accept-Language</code> 헤더로 선호를
나타낸다. 각 항목은 품질계수를 가질 수 있다. 변형은
여러 언어를 가질 (혹은 아무 언어도 없을) 수 있다.</td>
</tr>
<tr valign="top">
<td>Encoding</td>
<td>브라우저는 <code>Accept-Encoding</code> 헤더로 선호를
나타낸다. 각 항목은 품질계수를 가질 수 있다.</td>
</tr>
<tr valign="top">
<td>Charset</td>
<td>브라우저는 <code>Accept-Charset</code> 헤더로 선호를
나타낸다. 각 항목은 품질계수를 가질 수 있다. 변형은
media type의 파라미터로 문자집합을 나타낼 수 있다.</td>
</tr>
</table>
<h3><a name="algorithm" id="algorithm">아파치 협상 알고리즘</a></h3>
<p>아파치는 브라우저에게 보낼 '최적의' 변형을 (있다면)
선택하기위해 아래 알고리즘을 사용한다. 이 알고리즘은 변경할
수 없다. 다음와 같이 동작한다:</p>
<ol>
<li>먼저, 협상의 각 범위에 대해 해당하는 <em>Accept*</em>
헤더를 검사하고, 각 변형에 품질값을 매긴다. 어떤 범위의
<em>Accept*</em> 헤더가 받아들이지 않는 변형은 후보에서
제외한다. 어떤 변형도 남지않으면 4 단계로 간다.</li>
<li>
후보에서 하나씩 제외하여 '최적의' 변형을 찾는다. 다음
각 검사는 순서대로 일어난다. 각 검사에서 선택되지않은
변형은 제외된다. 각 검사후 한 변형만 남으면 이를 최적의
변형으로 선택하고 3 단계로 간다. 여러 변형이 남으면
다음 검사를 진행한다.
<ol>
<li><code>Accept</code> 헤더의 품질계수와 변형의
media type에 대한 품질값을 곱하여 가장 높은 값을
가진 변형을 선택한다.</li>
<li>가장 높은 언어(language) 품질계수를 가진 변형을
선택한다.</li>
<li><code>Accept-Language</code> 헤더에 (있다면)
나온 언어의 순서 혹은 <code>LanguagePriority</code>
지시어에 (있다면) 나온 언어의 순서를 가지고 가장
적합한 언어를 가진 변형을 선택한다.</li>
<li>가장 높은 (text/html media type의 버전을 나타내는)
'level' media 파라미터를 가진 변형을 선택한다.</li>
<li><code>Accept-Charset</code> 헤더를 가지고 가장
적합한 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 응답 헤더 <code>Vary</code>는 협상의 범위를
나타내게 된다. (브라우저와 캐쉬는 자원을 캐쉬할때 이 정보를
사용할 수 있다.) 끝.</li>
<li>이 단계에 도달했다면 (모두 브라우저가 받지못하기 때문에)
어떤 변형도 선택이 안된 경우다. ("No acceptable
representation"를 뜻하는) 상태 406과 내용으로 사용가능한
변형의 목록을 담은 HTML 문서를 응답을 보낸다. 또, HTML
<code>Vary</code> 헤더는 변형의 범위를 나타낸다.</li>
</ol>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="better" id="better">품질계수 조작하기</a></h2>
<p>아파치는 종종 위의 아파치 협상 알고리즘을 엄격히 지키지않고
품질계수를 변경한다. 이유는 완전하고 정확한 정보를 보내지않는
브라우저에게 (알고리즘의) 더 나은 결과를 보내기 위해서다.
널리 쓰이는 브라우저중 일부는 자주 잘못된 변형을 선택하도록
<code>Accept</code> 헤더를 보낸다. 브라우저가 완전하고 올바른
정보를 보낸다면, 조작을 하지않는다.</p>
<h3><a name="wildcards" id="wildcards">Media Type과 와일드카드</a></h3>
<p><code>Accept:</code> 요청 헤더는 media type에 대한 선호를
나타낸다. 또, *는 어떤 문자열이라도 가능하기때문에 "image/*"나
"*/*" 같이 '와일드카드' media type을 사용할 수도 있다. 그래서
다음과 같은 요청은:</p>
<div class="example"><p><code>Accept: image/*, */*</code></p></div>
<p>"image/"로 시작하는 어떤 type과 다른 어떤 type도 가능함을
의미한다. 어떤 브라우저는
자신이 실제로 다룰 수 있는 type에 추가로 와일드카드를 보낸다.
예를 들면:</p>
<div class="example"><p><code>
Accept: text/html, text/plain, image/gif, image/jpeg, */*
</code></p></div>
<p>이유는 직접 열거한 type을 선호하지만 다른 표현이 있다면
그것도 괜찮음을 나타내기 위해서다. 브라우저가 실제로 원한
것은 다음과 같이 명시적으로 품질값을 사용한 것이다.</p>
<div class="example"><p><code>
Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01
</code></p></div>
<p>직접 열거한 type은 품질계수가 없어서 기본값인 (가장 높은)
1.0을 가진다. 와일드카드 */*는 낮은 선호도 0.01을 가지므로
직접 열거한 type에 맞는 변형이 없는 경우에만 다른 type들이
사용된다.</p>
<p><code>Accept:</code> 헤더에 q 계수가 전혀 <em>없고</em>
"*/*"가 있다면, 아파치는 바람직한 행동을 위해 q 값으로 0.01을
지정한다. 또, "type/*" 형태의 와일드카드에는 ("*/*"보다는
더 선호하도록) 0.02를 지정한다. <code>Accept:</code> 헤더에서
q 계수를 가지는 media type이 있다면 이런 특별한 값을 추가하지
<em>않는다</em>. 그래서 명시적인 정보를 보내는 브라우저의
요청은 요청한데로 처리한다.</p>
<h3><a name="exceptions" id="exceptions">언어(language) 협상의 예외</a></h3>
<p>아파치 2.0은 언어 협상이 실패한 경우 부드럽게 복구하기위해
협상 알고리즘에 새로 예외를 몇개 추가했다.</p>
<p>클라이언트가 서버에 페이지를 요청했을때 서버가 브라우저가
보낸 <code>Accept-language</code>에 맞는 페이지를 단 한개만
찾으면 문제가 없지만, 그러지 않은 경우 서버는 클라이언트에게
"No Acceptable Variant"나 "Multiple Choices" 응답을 보낸다.
이런 오류문을 피하기위해 이 경우 <code>Accept-language</code>를
무시하고 클라이언트의 요청에 명확히 맞지는 않지만 문서를
보내도록 아파치를 설정할 수 있다. <code class="directive"><a href="./mod/mod_negotiation.html#forcelanguagepriority">ForceLanguagePriority</a></code>
지시어는 서버가 이런 오류문중 하나 혹은 둘다를 무시하고
<code class="directive"><a href="./mod/mod_negotiation.html#languagepriority">LanguagePriority</a></code>
지시어로 판단하도록 한다.</p>
<p>또, 서버는 맞는 언어를 못찾은 경우 부모언어를 찾을 수도
있다. 예를 들어 클라이언트가 영국영어를 뜻하는
<code>en-GB</code> 언어로 문서를 요청한 경우, HTTP/1.1 표준에
따르면 서버는 <code>en</code>으로만 표시된 문서를 일반적으로
선택하지 못한다. (그래서 영국영어를 이해하는 독자가 일반적인
영어도 이해할 수 있으므로 <code>Accept-Language</code> 헤더에
<code>en-GB</code>만 포함하고 <code>en</code>을 포함하지않으면
거의 확실히 잘못된 설정임을 유의하라. 불행히도 현재 많은
클라이언트들은 이런 식으로 기본설정되있다.) 다른 언어를
찾지 못하여 서버가 "No Acceptable Variants" 오류를 보내거나
<code class="directive"><a href="./mod/mod_negotiation.html#languagepriority">LanguagePriority</a></code>로
돌아가야 한다면, 서버는 하위언어 규약을 무시하고
<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.0.47부터
<code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code>은 <code>prefer-language</code>라는
<a href="env.html">환경변수</a>를 인식한다. 이 환경변수가
존재하고 적절한 언어태그를 포함한다면,
<code class="module"><a href="./mod/mod_negotiation.html">mod_negotiation</a></code>은 해당하는 변형을 선택하려고
시도한다. 그런 변형이 없다면 일반적인 협상과정을 시작한다.</p>
<div class="example"><h3>예제</h3><p><code>
SetEnvIf Cookie "language=(.+)" prefer-language=$1
</code></p></div>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="extensions" id="extensions">자연스러운(transparent) 내용협상의 확장</a></h2>
<p>아파치는 다음과 같이 자연스러운 내용확장 프로토콜을 (RFC 2295)
확장한다. 변형 목록의 새로운 <code>{encoding ..}</code>는 특정
content-encoding을 가진 변형만을 지칭한다. RVSA/1.0 알고리즘은
(RFC 2296) 목록에서 인코딩된 변형을 인식할 수 있고, 인코딩이
<code>Accept-Encoding</code> 요청 헤더에 맞는 경우 인코딩된
변형들도 후보로 사용하도록 확장되었다. RVSA/1.0 구현은 최적의
변형을 찾기 전에 계산된 품질계수를 소수점 5자리에서 반올림하지
않는다.</p>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="naming" id="naming">하이퍼링크와 이름규칙에 대하여</a></h2>
<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 class="bordered">
<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>
</div><div class="top"><a href="#page-header"><img alt="top" src="./images/up.gif" /></a></div>
<div class="section">
<h2><a name="caching" id="caching">캐쉬에 대하여</a></h2>
<p>캐쉬가 표현을 저장하면 표현과 요청 URL을 연관시킨다.
다음번 그 URL을 요청하면 캐쉬는 저장된 표현을 사용한다.
그러나 서버와 협상이 가능한 자원인 경우 첫번째 요청한 변형만
캐쉬되어 이후 요청은 캐쉬된 잘못된 응답을 얻을 수 있다.
이를 막기위해 아파치는 보통 내용협상후 반환되는 모든 요청에
HTTP/1.0 클라이언트가 캐쉬를 못하도록 표시를 한다. 또, 아파치는
협상한 응답의 캐쉬를 허용하는 HTTP/1.1 프로토콜의 기능을
지원한다.</p>
<p><code class="directive"><a href="./mod/mod_negotiation.html#cachenegotiateddocs">CacheNegotiatedDocs</a></code>
지시어는 HTTP/1.0 호환 클라이언트(브라우저 혹은 캐쉬)가
보낸 요청에 대해 협상한 응답을 캐쉬할 수 있게 한다. 이 지시어는
서버나 가상호스트 설정에 사용하며, 아규먼트를 받지않는다.
이 지시어는 HTTP/1.1 클라이언트의 요청과는 관계가 없다.</p>
<p>HTTP/1.1 클라이언트에게 아파치는 응답의 협상 범위를
알려주는 <code>Vary</code> HTTP 응답헤더를 보낸다. 이 정보를
사용하여 다음 요청을 캐쉬된 복사본으로 대체할 수 있는지
판단할 수 있다. 헙상의 범위와 관계없이 캐쉬된 복사본을
권한다면 <code>force-no-vary</code> <a href="env.html#special">환경변수</a>를 설정한다.</p>
</div></div>
<div class="bottomlang">
<p><span>가능한 언어: </span><a href="./en/content-negotiation.html" hreflang="en" rel="alternate" title="English"> en </a> |
<a href="./fr/content-negotiation.html" hreflang="fr" rel="alternate" title="Français"> fr </a> |
<a href="./ja/content-negotiation.html" hreflang="ja" rel="alternate" title="Japanese"> ja </a> |
<a href="./ko/content-negotiation.html" title="Korean"> ko </a> |
<a href="./tr/content-negotiation.html" hreflang="tr" rel="alternate" title="Türkçe"> tr </a></p>
</div><div class="top"><a href="#page-header"><img src="./images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Comments</a></h2><div class="warning"><strong>Notice:</strong><br />This is not a Q&A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our <a href="http://httpd.apache.org/lists.html">mailing lists</a>.</div>
<script type="text/javascript"><!--//--><![CDATA[//><!--
var comments_shortname = 'httpd';
var comments_identifier = 'http://httpd.apache.org/docs/2.4/content-negotiation.html';
(function(w, d) {
if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
d.write('<div id="comments_thread"><\/div>');
var s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
(d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
}
else {
d.write('<div id="comments_thread">Comments are disabled for this page at the moment.<\/div>');
}
})(window, document);
//--><!]]></script></div><div id="footer">
<p class="apache">Copyright 2017 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
<p class="menu"><a href="./mod/">모듈</a> | <a href="./mod/directives.html">지시어들</a> | <a href="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="./glossary.html">용어</a> | <a href="./sitemap.html">사이트맵</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
if (typeof(prettyPrint) !== 'undefined') {
prettyPrint();
}
//--><!]]></script>
</body></html>