반응형
반응형

출처:http://homoefficio.github.io/

Spring에서 JSON에 XSS 방지 처리 하기

고마운 lucy-xss-servlet-filter의 한계

XSS(Cross Site Scripting) 방지를 위해 널리 쓰이는 훌륭한 lucy-xss-servlet-filter는 Servlet Filter 단에서 < 등의 특수 문자를 &lt; 등으로 변환해주며, 여러 가지 관련 설정을 편리하게 지정할 수 있어 정말 좋다.

lucy-xss-servlet 는 naver에서 발표하고 Git 에서 배포된다 

https://github.com/naver/lucy-xss-servlet-filter 이곳에서도 참고 할 수 있다

그런데 그 처리가 form-data에 대해서만 적용되고 Request Raw Body로 넘어가는 JSON에 대해서는 처리해주지 않는다는 단점이 있다. 그래서 JSON을 주고 받는 API 서버의 경우에는 직접 처리를 해줘야 한다.

lucy-xss-servlet-filter를 수정해서 JSON도 처리하도록 만드는 방법도 있겠지만, 여기에서는 Response를 클라이언트로 내보내는 단계에서 처리하는 방법을 알아본다.

HandlerInterceptor

Response 쪽에서 공통적으로 처리해줘야할 일이 있다면 금방 떠오르는 것이 HanderInterceptor의 postHandle()이다. 이 메서드의 파라미터는 HttpServletRequest requestHttpServletResponse responseObject handlerModelAndView modelAndView이고, response에서 Response Body를 꺼내서, < => &lt; 등의 변환 처리를 하고 다시 response에 넣어주면 될 것 같다.

하지만 response에서 Response Body를 끄집어 내는 것도 쉽지 않고, 그 내용을 바꿔서 다시 집어넣는 것도 여의치 않다. 다른 방법이 필요하다.

MessageConverter

다음으로 생각나는 것은 MessageConverter다. 어차피 결국에는 Jackson 같은 Mapper를 통해 JSON 문자열로 Response에 담겨지므로, Mapper가 JSON 문자열을 생성할 때 XSS 방지 처리를 해주면 될 것 같다.

찾아보니 역시나 http://stackoverflow.com/questions/25403676/initbinder-with-requestbody-escaping-xss-in-spring-3-2-4 이런 자료가 있다. 좀 오래된 버전이고 군더더기도 있어서 Jackson 2.#, SpringBoot 1.# 버전 기준으로 깔끔하게, 그리고 커스터마이징 할 수 있는 부분을 추가해서 정리해봤다.

큰 흐름은 다음과 같다.

  1. 처리할 특수 문자 지정
  2. 특수 문자 인코딩 값 지정
  3. ObjectMapper에 특수 문자 처리 기능 적용
  4. MessageConverter에 ObjectMapper 설정
  5. WebMvcConfigurerAdapter에 MessageConverter 추가

처리할 특수 문자 지정

XSS 방지 처리할 특수 문자를 다음과 같이 CharacterEscapes를 상속한 클래스를 직접 만들어서 지정해준다.

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
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;
import org.apache.commons.lang3.text.translate.AggregateTranslator;
import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
import org.apache.commons.lang3.text.translate.EntityArrays;
import org.apache.commons.lang3.text.translate.LookupTranslator;
 
public class HTMLCharacterEscapes extends CharacterEscapes {
 
    private final int[] asciiEscapes;
 
    private final CharSequenceTranslator translator;
 
    public HTMLCharacterEscapes() {
 
        // 1. XSS 방지 처리할 특수 문자 지정
        asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
        asciiEscapes['<'= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['>'= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['&'= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['\"'= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['('= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes[')'= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['#'= CharacterEscapes.ESCAPE_CUSTOM;
        asciiEscapes['\''= CharacterEscapes.ESCAPE_CUSTOM;
 
        // 2. XSS 방지 처리 특수 문자 인코딩 값 지정
        translator = new AggregateTranslator(
            new LookupTranslator(EntityArrays.BASIC_ESCAPE()),  // <, >, &, " 는 여기에 포함됨
            new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE()),
            new LookupTranslator(EntityArrays.HTML40_EXTENDED_ESCAPE()),
            // 여기에서 커스터마이징 가능
            new LookupTranslator(
                new String[][]{
                    {"(",  "&#40;"},
                    {")",  "&#41;"},
                    {"#",  "&#35;"},
                    {"\'""&#39;"}
                }
            )
        );
    }
 
    @Override
    public int[] getEscapeCodesForAscii() {
        return asciiEscapes;
    }
 
    @Override
    public SerializableString getEscapeSequence(int ch) {
        return new SerializedString(translator.translate(Character.toString((char) ch)));
 
        // 참고 - 커스터마이징이 필요없다면 아래와 같이 Apache Commons Lang3에서 제공하는 메서드를 써도 된다.
        // return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
    }
}
cs


ObjectMapper에 특수 문자 처리 기능 적용 후 MessageConverter 등록

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
@Bean
public WebMvcConfigurerAdapter controlTowerWebConfigurerAdapter() {
    return new WebMvcConfigurerAdapter() {
 
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            super.configureMessageConverters(converters);
 
            // 5. WebMvcConfigurerAdapter에 MessageConverter 추가
            converters.add(htmlEscapingConveter());
        }
 
        private HttpMessageConverter<?> htmlEscapingConveter() {
            ObjectMapper objectMapper = new ObjectMapper();
            // 3. ObjectMapper에 특수 문자 처리 기능 적용
            objectMapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());
 
            // 4. MessageConverter에 ObjectMapper 설정
            MappingJackson2HttpMessageConverter htmlEscapingConverter =
                    new MappingJackson2HttpMessageConverter();
            htmlEscapingConverter.setObjectMapper(objectMapper);
 
            return htmlEscapingConverter;
        }
    };
}
cs

정리

lucy-xss-servlet-filter는 JSON에 대한 XSS는 처리해주지 않는다.

  • 따라서, JSON에 대한 XSS가 필요하다면
  • Jackson의 com.fasterxml.jackson.core.io.CharacterEscapes를 상속하는 클래스 A를 직접 만들어서 처리해야 할 특수문자를 지정하고,
  • ObjectMapper에 A를 설정하고,
  • ObjectMapper를 MessageConverter에 등록해서 Response가 클라이언트에 나가기 전에 XSS 방지 처리 해준다.



언제 개인 프로젝트에 적용해 볼까 하고 가져왔다

반응형
반응형

출처:https://code.i-harness.com/ko/q/60f0


누구든지 jQuery의 문자열에서 HTML을 쉽게 벗어날 수있는 방법을 알고 있습니까? 

임의의 문자열을 전달하고 HTML 페이지 (JavaScript / HTML 삽입 공격 방지)에 표시되도록 적절하게 

이스케이프 처리해야합니다. 이 작업을 수행하기 위해 jQuery를 확장 할 수 있다고 확신하지만

이 작업을 수행하는 데 필요한 프레임 워크에 대해 충분히 알지 못합니다.

 Answers


jQuery를 사용하기 때문에 요소의 text 속성을 설정할 수 있습니다.

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;

mustache.js의 솔루션 도 있습니다 .

var entityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}

HTML로 탈출했다면 정말 필요한 것이라고 생각할 수있는 것은 세 가지뿐입니다.

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

사용 사례에 따라 " to &quot; 와 같은 작업을 수행해야 할 수도 있습니다. 목록이 충분히 크면 배열을 사용합니다.

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent() 는 URL이 아닌 HTML 만 이스케이프 처리합니다.

나는 이것을하는 작은 기능을 썼다. 그것은 " , & , < 그리고 > 만 이스케이프합니다. (대개 필요한 것은 모두 필요합니다.

 .replace() 모든 변환 작업을 수행하기 위해 .replace() 를 사용한다는 점에서 이전 제안 된 솔루션보다 약간 더 우아합니다. 

EDIT 2 : 코드 복잡성이 줄어들어 원래 코드에 대해 궁금한 점이 있다면 함수를 더 작고 깔끔하게 만듭니다.이 답변의 끝 부분을 참조하십시오.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

이것은 일반 Javascript이며 jQuery는 사용되지 않습니다.

탈출구 ' 와 ' 도

mklement 의 코멘트에 대한 응답으로 편집하십시오.

위의 기능은 모든 문자를 포함하도록 쉽게 확장 될 수 있습니다. 이스케이프 할 문자를 더 지정하려면 

정규 표현식의 문자 클래스 (예 : /[...]/g )와 chr 객체의 항목으로 모두 삽입하기 만하면됩니다. 

EDIT 2 : 같은 방식으로이 기능을 짧게합니다.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

위의 &#39; 아포스트로피 (상징적 인 엔티티가 대신 사용될 수도 있음 - XML로 정의되었지만 원래 HTML 스펙에 포함되지 않았기 때문에

 모든 브라우저에서 지원되지 않을 수도 있음 참조 : HTML 문자 인코딩에 관한 Wikipedia 기사 ). 

또한 십진법 엔티티를 사용하는 것이 16 진수를 사용하는 것보다 더 광범위하게 지원된다는 것을 기억하지만, 지금은 소스를 찾을 수없는 것 같습니다.

 (그리고 16 진법 엔티티를 지원하지 않는 많은 브라우저가있을 수 없습니다.)

참고 : 이스케이프 된 문자 목록에 / 와 ' 를 추가하는 것은 HTML에서 특별한 의미가 없으므로 유용하지 않습니다. 이스케이프 처리 할 필요 가 없습니다.

원래 escapeHtml 함수

편집 2 : 원래 함수는 변수 ( chr )를 사용하여 .replace() 콜백에 필요한 객체를 저장합니다. 

이 변수는 범위를 지정하기 위해 익명의 추가 함수가 필요하기 때문에 함수가 불필요하게 커지고 복잡해졌습니다.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

두 버전 중 어느 버전이 더 빠르는지는 테스트하지 않았습니다. 그럴 경우 여기에서 정보와 링크를 자유롭게 추가하십시오.

쉽게 밑줄을 사용할 수 있습니다.

_.escape(string) 

Underscore 는 네이티브 j가 제공하지 않는 많은 기능을 제공하는 유틸리티 라이브러리입니다. 

밑줄과 같은 API이지만 성능이 좋도록 다시 작성된 lodash 도 있습니다.

내가이 파티에 얼마나 늦었는지 알지만, jQuery를 필요로하지 않는 아주 쉬운 해결책이있다.

escaped = new Option(unescaped).innerHTML;

편집 :이 따옴표를 이스케이프하지 않습니다. 따옴표를 이스케이프해야하는 유일한 경우는

 내용이 HTML 문자열 내의 속성에 인라인으로 붙여 넣기 될 경우입니다. 

이 일을하는 것이 좋은 디자인이라고 상상하는 것이 어렵습니다.

편집 2 : 성능이 중요한 경우 최고 성능 솔루션 (약 50 %까지)은 여전히 ​​일련의 정규식 대체품입니다. 

최신 브라우저는 정규 표현식에 연산자가없고 문자열 만 포함하고 모두를 단일 작업으로 축소한다는 사실을 감지합니다.

깨끗하고 명확한 JavaScript 함수가 여기에 있습니다. 그것은 "몇 개의 <많은"과 같은 텍스트를 "소수의 <많은>"문자로 이스케이프합니다.

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;');
}

Underscore.string lib를 사용해보십시오. jQuery와 함께 작동합니다.

_.str.escapeHTML('<div>Blah blah blah</div>')

산출:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'

마지막 테스트 후 가장 빠르고 완벽하게 크로스 브라우저 호환 원시 자바 스크립트 (DOM) 솔루션을 추천 할 수 있습니다 :

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

여러 번 반복하면 준비된 변수를 사용하여 수행 할 수 있습니다.

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

내 최종 실적 비교 ( 스택 질문 )를보십시오.

나는 문자열 객체에 escapeHTML() 메소드를 추가하는 콧수염 escapeHTML() 예제를 개선했습니다.

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

그렇게하면 "Some <text>, more Text&Text".escapeHTML() 를 사용하는 것이 매우 쉽습니다. "Some <text>, more Text&Text".escapeHTML()

escape() 및 unescape() 는 HTML이 아닌 URL의 문자열을 인코딩 / 디코딩하기위한 것입니다.

사실, 나는 프레임 워크를 필요로하지 않는 트릭을하기 위해 다음 스 니펫을 사용한다.

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');

underscore.js가 있으면 _.escape 사용 _.escape (위에 게시 된 jQuery 메서드보다 효율적입니다).

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe

위의 tghw의 예에서 오류가 발생했습니다.

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}

이것은 좋은 안전한 예입니다 ...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

전역 변수, 일부 메모리 최적화가 없습니다. 용법:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

결과는 다음과 같습니다.

"some&lt;tag&gt;and&amp;symbol&copy;"

바닐라 js로 쉽게 할 수 있습니다.

단순히 텍스트 노드를 문서에 추가하십시오. 그것은 브라우저에 의해 이스케이프됩니다.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}

NO JQUERY가 필요없는 2 가지 간단한 메소드 ...

다음과 같이 문자열의 모든 문자 를 인코딩 할 수 있습니다.

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

또는 & , 줄 바꿈, < , > , " 및 ' 대해 걱정할 주요 문자 를 대상으로 지정하십시오 .

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>

function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

매력처럼 작동합니다.

이 답변 은 jQuery와 일반 JS 메소드를 제공하지만 DOM을 사용하지 않으면이 메소드가 가장 짧습니다.

unescape(escape("It's > 20% less complicated this way."))

이스케이프 된 문자열 : It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

이스케이프 된 공간에서 문제가 발생하면 시도해보십시오.

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

이스케이프 처리 된 문자열 : It%27s %3E 20%25 less complicated this way.

유감스럽게도 JavaScript 버전 1.5 에서는 escape() 함수가 사용되지 않습니다 . 

encodeURI() 또는 encodeURIComponent() 는 대안이지만 무시하므로 ' , 마지막 코드 행은 다음과 같이 바뀝니다.

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

모든 주요 브라우저는 여전히 짧은 코드를 지원하며 이전 웹 사이트의 수를 감안할 때 곧 변경 될 것입니다.

일반 자바 스크립트 이스케이프 예 :

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"

이 정보를 데이터베이스 에 저장하는 경우 클라이언트 측 스크립트를 사용하여

HTML을 이스케이프 처리하는 것은 잘못된 것으로 서버 에서 수행해야 합니다 . 

그렇지 않으면 XSS 보호를 우회하기 쉽습니다.

내 요점을 분명히하기 위해 다음 답변 중 하나를 사용하는 예제가 있습니다.

말하자면 escapeHtml 함수를 사용하여 블로그의 주석에서 Html을 이스케이프 처리 한 다음 서버에 게시합니다.

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

사용자는 다음을 수행 할 수 있습니다.

  • POST 요청 매개 변수를 편집하고 주석을 javascript 코드로 바꿉니다.
  • 브라우저 콘솔을 사용하여 escapeHtml 함수를 덮어 씁니다.

사용자가이 스 니펫을 콘솔에 붙여 넣으면 XSS 유효성 검사를 건너 뜁니다.

function escapeHtml(string){
   return string
}

당신이 재 탈출을 방지하지 않으면 모든 솔루션은 쓸모가 없습니다. 예를 들어, 대부분의 솔루션은 이스케이프 & &amp; .

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};


반응형
반응형

출처: http://gangzzang.tistory.com/entry/스프링Spring-MVC-프레임워크Model-View-Controller-Framework-1 [갱짱.study]


스프링의 흐름을 가장 잘 설명한 글인것같아서 퍼왔다 참고할것


1. 스프링(Spring) MVC 프레임워크(Model View Controller Framework)

- 스프링이 제공하는 트랜잭션 처리, DI, AOP를 손쉽게 사용

- 스트럿츠2와 같은 프레임워크와 연동이 쉬움




2. 스프링 MVC 주요 구성 요소 및 처리 흐름

- 다른 MVC 프레임워크와 마찬가지로 컨트롤러를 사용하여 요청을 처리

- 스프링에서는 DispatcherServlet이 MVC에서의 컨트롤러(Controller) 부분을 처리



 구성 요소

 설명 

 DispatcherServlet

 클라이언트의 요청을 전달받아 요청에 맞는 컨트롤러가 리턴한 결과값을 View에 전달하여 알맞은 응답을 생성 

 HandlerMapping

 클라이언트의 요청 URL을 어떤 컨트롤러가 처리할지 결정 

 Controller

 클라이언트의 요청을 처리한 뒤, 결과를 DispatcherServlet에게 리턴 

 ModelAndView

 컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담음 

 ViewResolver

 컨트롤러의 처리 결과를 생성할 뷰를 결정 

 View

 컨트롤러의 처리 결과 화면을 생성, JSP 또는 Velocity 템플릿 파일 등을 뷰로 사용 




3. 스프링 MVC 개발

- 클라이언트에 요청을 받을 DispatcherServlet을 web.xml 파일에 설정

- 클라이언트의 요청을 처리할 컨트롤러 작성

- ViewResolver 설정 (컨트롤러가 전달한 값을 이용해서 응답 화면을 생성할 뷰를 결정)

- JSP나 Velocity 등을 이용하여 뷰영역의 코드를 작성




3.1. DispatcherServlet 설정 및 스프링 컨텍스트 설정

- web.xml(자바 웹 어플리케이션 설정 파일)에 DipathcerServlet 설정 및 공통으로 사용할 어플리케이션 컨텍스트 설정

- <servlet> 태그를 이용하여 DispatcherServlet 설정

- <servlet-mapping> 태그를 이용하여 요청 URL 패턴 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- web.xml -->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" 
         xsi:schemalocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
         id="WebApp_ID" version="3.0">
  <display-name>SpringBlog2</display-name>
   
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>
 
cs


3.2. 컨트롤러 구현 및 설정 추가

- @Controller 애노테이션을 클래스에 적용

- @RequestMapping 애노테이션을 이용해서 클라이언트의 요청을 처리할 메서드를 지정

- ModelAndView는 컨트롤러의 처리 결과를 보여줄 뷰와 뷰에서 출력할 모델을 지정

- DispatcherServlet은 스프링 컨테이너에서 컨트롤러 객체를 검색하기 때문에 스프링 설정 파일에 컨트롤러를 빈으로 등록해야 함


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// HelloController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
 
@Controller
public class HelloController {
 
    @RequestMapping("/hello.do")
    public ModelAndView hello() {
      ModelAndView mv = new ModelAndView();
      mv.setViewName("hello");
      mv.addObject("message""Hello Spring MVC");
      return mv;
    }
// HelloController
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- dispatcher-servlet.xml -->
<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:context="http://www.springframework.org/schema/context" 
       xsi:schemalocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   
  <bean id="helloController" class="com.tistory.gangzzang.controller.HelloController"></bean>
   
</beans>
cs


3.3. 설정 파일 View Resolver 설정 추가

- 컨트롤러에서 ModelAndView.setViewName() 메서드로 뷰이름을 지정

- 이 뷰이름과 매칭되는 뷰 구현체를 찾기 위해 ViewResolver를 사용

- prefix 프로퍼티와 suffix 프로퍼티를 지정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- dispatcher-servlet.xml -->
<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:context="http://www.springframework.org/schema/context" 
       xsi:schemalocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   
  <bean id="helloController" class="com.tistory.gangzzang.controller.HelloController"></bean>
   
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/"></property>
    <property name="suffix" value=".jsp"></property>
  </bean>
</beans>
cs


3.4. 뷰 코드 구현

ModelAndView.addObject() 메서드로 모델을 추가할 때 사용한 이름을 이용해서 모델의 값을 사용

1
2
3
4
5
6
7
8
9
10
11
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${ message }</title>
</head>
<body>
${ message }
</body>
</html>
cs


3.5. 실행

- 컨트롤러의 지정된 URL 요청을 주소창에 입력




4. DispatcherServlet 설정과 ApplicationContext의 관계

- web.xml 파일에 한 개 이상의 DispatcherServlet 설정할 수 있으며, 각각 한 개의 WebApplicationContext를 갖음




4.1. DispatcherServlet 설정

- DipatcherServlet는 기본적으로 /WEB-INF/ 디렉터리에 위치한 [서블릿이름]-servlet.xml 파일로부터 스프링 설정 정보를 읽어 옴

- 한개 이상의 설정 파일, 또는 설정 다른 이름의 설정 파일을 사용할 경우 contextConfigLocation 초기화 파라미터에 설정 파일 목록을 지정

- 설정 파일 구분은 콤마(","), 공백 문자(" "), 탭(\t), 줄 바꿈(\n), 세미콜론(";")을 이용


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
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- web.xml -->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" 
         xsi:schemalocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
         id="WebApp_ID" version="3.0">
  <display-name>SpringBlog2</display-name>
   
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
        /WEB-INF/beans.xml
        /WEB-INF/main.xml
      </param-value>
    </init-param>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>
cs

4.2. ApplicationContext 설정

- 한 개 이상의 DispatcheerServlet을 사용할 때 별도의 WebApplicationContext를 생성

- 이 경우 공통 빈을 필요로 할 때 ContextLoaderListener를 사용하여 사용될 빈을 설정

- ServletListener로 등록, contextConfigLocation 컨텍스트 파라미터를 이용, 공통으로 사용될 빈 정보를 담고 있는 설정 파일 목록을 지정

- ContextLoaderListener가 생성하는 WebApplicationContext는 웹 어플리케이션의 루트 컨텍스트

- DispatcherServlet이 생성하는 WebApplicationContext는 루트 컨텍스트를 부모로 사용하는 자식 컨텍스트

- ContextLoaderListener는 contextConfigLocation 컨텍스트 파라미터를 명시하지 않으면 /WEB-INF/applicationContext.xml을 설정 파일로 사용


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
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- web.xml -->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" 
         xsi:schemalocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
         id="WebApp_ID" version="3.0">
  <display-name>SpringBlog2</display-name>
   
  <!--
  <servlet>
    <servlet-name>front_dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/front.xml</param-value>
    </init-param>
  </servlet>
   
  <servlet>
    <servlet-name>rest_dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/rest.xml</param-value>
    </init-param>
  </servlet>
  -->
   
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      /WEB-INF/front.xml
      /WEB-INF/service.xml
    </param-value>
  </context-param>
 
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
   
  <servlet>
    <servlet-name>front</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
   
  <servlet>
    <servlet-name>rest</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
   
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>
cs





5. 캐릭터 인코딩 처리 필터 설정

- 모든 컨트롤러에서 response.setCharacterEncoding() 코드를 실행하는 번거로움을 해소하기 위해 서블릿 필터를 이용 처리

- 서블릿 필터에서 캐틱터 인코딩을 설정할 수 있는 CharacterEncodingFilter 클래스를 제공

- web.xml 파일에 설정


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
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- web.xml -->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://java.sun.com/xml/ns/javaee" 
         xsi:schemalocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
         id="WebApp_ID" version="3.0">
  <display-name>SpringBlog2</display-name>
   
  <servlet>
    <servlet-name>dispathcer</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
   
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
   
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
   
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>
cs




6. 컨트롤러 구현

- 스프링 3.0 버전 부터는 @Controller 애노테이션을 이용해서 컨트롤러 클래스를 구현하도록 권장




6.1. @Controller 애노테이션, @RequestMapping 애노테이션

- 컨트롤러 클래스에 @Controller 애노테이션 적용

- 클라이언트의 요청을 처리할 메서드에 @RequestMapping 애노테이션 적용

- 설정 파일에 컨트롤러 클래스를 빈으로 등록

- @RequestMapping 애노테이션은 해당 메서드에서 처리할 URI를 값으로 갖음

- @RequestMapping 애노테이션의 메서드의 리턴 타입은 상황에 따라 알맞은 타입을 선택


6.2. 컨트롤러 메서드 HTTP 전송 방식(method) 한정

- 하나의 요청 URL에 대해 HTTP GET 요청과 POST 요청을 한 개의 컨트롤러에서 처리할 경우

- @RequestMapping 애노테이션의 method 속성을 이용해서 메서드가 처리할 HTTP 메서드를 제한


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// HelloController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class HelloController {
 
    @RequestMapping(value="/write.do", method=RequestMethod.GET)
    public String writeForm() {
      return "writeForm";
    }
     
    @RequestMapping(value="/write.do", method=RequestMethod.POST)
    public String writeSub() {
      return "writeSub";
    }
// HelloController
cs


- 두 메서드가 동일한 URI를 처리하는 경우 @RequestMapping 애노테이션을 클래스에 적용해서 해당 클래스가 처리할 기본 URI를 지정가능

- @RequestMapping 애노테이션에 method 속성을 설정하지 않을 경우 모든 HTTP 전송방식(GET, POST, DELETE 등)을 처리


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// HelloController2.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
@RequestMapping("/write.do")
public class HelloController2 {
 
    @RequestMapping(method=RequestMethod.GET)
    public String writeForm() {
      return "writeForm";
    }
     
    @RequestMapping(method=RequestMethod.POST)
    public String writeSub() {
      return "writeSub";
    }
// HelloController2
cs


6.3. HTML 폼, 커맨드 객체

- HTML 폼에 입력한 데이터를 자바빈 객체를 이용해서 전달 받음

- HTML 폼의 항목 이름과 자바빈 클래스의 프로퍼티 이름이 일치할 경우 폼에 입력한 값을 프로퍼티 값으로 설정

- @RequestMapping 애노테이션이 적용된 메서드의 파라미터로 자바빈 타입을 추가

- 폼에 입력한 값은 모두 문자열이지만 스프링은 자바빈의 타입 변환 처리 기능으로 프로퍼티의 타입으로 알맞게 변환


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- writeForm.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WriteForm</title>
</head>
<body>
    <form action="write.do" method="post">
        <input type="text" name="name" placeholder="폰 이름" required="required" size="50"><br>
        <input type="text" name="manufacturer" placeholder="폰 제조사" required="required" size="50"><br>
        <input type="text" name="price" placeholder="폰 가격" required="required" size="50"><br>
        <input type="submit" value="작성"><input type="reset" value="취소">
    </form>
</body>
</html>
cs



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
// PhoneDTO.java
 
package com.tistory.gangzzang.model;
 
public class PhoneDTO {
  private String name;
  private String manufacturer;
  private int price;
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public String getManufacturer() {
    return manufacturer;
  }
 
  public void setManufacturer(String manufacturer) {
    this.manufacturer = manufacturer;
  }
 
  public int getPrice() {
    return price;
  }
 
  public void setPrice(int price) {
    this.price = price;
  }
// PhoneDTO
cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// PhoneController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.tistory.gangzzang.model.PhoneDTO;
 
@Controller
public class PhoneController {
 
  @RequestMapping(value = "/write.do", method = RequestMethod.GET)
  public String writeForm() {
    return "writeForm";
  }
 
  @RequestMapping(value = "/write.do", method = RequestMethod.POST)
  public String wirteSubmit(PhoneDTO phoneDTO) {
    return "writeSubmit";
  }
// PhoneController
cs


6.3.1. 뷰에서 커맨드 객체 접근

- 뷰에서 @RequestMapping 애노테이션 메서드에서 전달받은 커맨드 객체(자바빈 객체)의 클래스명을 이용해서 접근 가능(단 첫글자는 소문자)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- writeSubmit.jsp -->
 
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WriteSubmit</title>
</head>
<body>
    <input type="text" name="name" placeholder="폰 이름" required="required" 
           readonly="readonly" size="50" value="${ phoneDTO.name }"><br>
    <input type="text" name="manufacturer" placeholder="폰 제조사" 
           required="required" readonly="readonly" size="50" value="${ phoneDTO.manufacturer }"><br>
    <input type="text" name="price" placeholder="폰 가격" 
           required="required" readonly="readonly" size="50" value="${ phoneDTO.price }"><br>
</body>
</html>
cs


- 뷰에서 사용할 모델의 이름을 변경할 때는 @ModelAttribute 애노테이션을 이용, 커맨드 객체의 모델 이름을 지정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// PhoneController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.tistory.gangzzang.model.PhoneDTO;
 
@Controller
public class PhoneController {
 
  @RequestMapping(value = "write.do", method = RequestMethod.GET)
  public String writeForm() {
    return "writeForm";
  }
 
  @RequestMapping(value = "write.do", method = RequestMethod.POST)
  public String wirteSubmit(@ModelAttribute("p") PhoneDTO phoneDTO) {
    return "writeSubmit";
  }
// PhoneController
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- writeSubmit.jsp -->
 
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WriteSubmit</title>
</head>
<body>
    <input type="text" placeholder="폰 이름" required="required" 
        readonly="readonly" size="50" value="${ p.name }"><br>
    <input type="text" placeholder="폰 제조사" required="required" 
        readonly="readonly" size="50" value="${ p.manufacturer }"><br>
    <input type="text" placeholder="폰 가격" required="required" 
        readonly="readonly" size="50" value="${ p.price }"><br>
</body>
</html>
cs


6.3.2. 커맨드 객체로 List 받기

- 폼에서 "프로퍼티명[인덱스].프로퍼티" 같이 입력 폼의 이름을 구성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// PhoneVO.java
 
package com.tistory.gangzzang.model;
 
import java.util.List;
 
public class PhoneVO {
  private List<PhoneDTO> phoneItems;
 
  public List<PhoneDTO> getPhoneItems() {
    return phoneItems;
  }
 
  public void setPhoneItems(List<PhoneDTO> phoneItems) {
    this.phoneItems = phoneItems;
  }
// PhoneVO
cs

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
<!-- writeListForm.jsp -->
 
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WriteListForm</title>
</head>
<body>
    <form action="writeList.do" method="post">
        <input type="text" name="phoneItems[0].name" placeholder="폰 이름1" 
                required="required" size="50"><br>
        <input type="text" name="phoneItems[0].manufacturer" placeholder="폰 제조사1" 
                required="required" size="50"><br>
        <input type="text" name="phoneItems[0].price" placeholder="폰 가격1" 
                required="required" size="50"><br>
        <hr>
        <input type="text" name="phoneItems[1].name" placeholder="폰 이름2" 
                required="required" size="50"><br>
        <input type="text" name="phoneItems[1].manufacturer" placeholder="폰 제조사2" 
                required="required" size="50"><br>
        <input type="text" name="phoneItems[1].price" placeholder="폰 가격2" 
                required="required" size="50"><br>
        <hr>
        <input type="submit" value="작성"><input type="reset" value="취소">
    </form>
</body>
</html>
cs

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
// PhoneController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.tistory.gangzzang.model.PhoneDTO;
import com.tistory.gangzzang.model.PhoneVO;
 
@Controller
public class PhoneController {
 
  @RequestMapping(value = "write.do", method = RequestMethod.GET)
  public String writeForm() {
    return "writeForm";
  }
 
  @RequestMapping(value = "write.do", method = RequestMethod.POST)
  public String wirteSubmit(@ModelAttribute("p") PhoneDTO phoneDTO) {
    return "writeSubmit";
  }
   
  @RequestMapping(value = "writeList.do", method = RequestMethod.GET)
  public String writeListForm() {
    return "writeListForm";
  }
 
  @RequestMapping(value = "writeList.do", method = RequestMethod.POST)
  public String wirteListSubmit(@ModelAttribute("phone") PhoneVO phoneVO) {
    return "writeListSubmit";
  }
// PhoneController
cs


6.4. 컨트롤러 메서드 파라미터 타입

- 컨트롤러의 @RequestMapping 애노테이션이 적용된 메서드는 커맨드 클래스외에도 다양한 타입의 파라미터를 가질 수 있음


 파라미터 타입

 설명 

 HttpServletRequest, HttpServletResponse, HttpSession 

 서블릿 API 

 java.util.Locale

 현재 요청에 대한 Locale 

 InputStream, Reader

 요청 컨텐츠에 직접 접근할 때 사용 

 OutputStream, Writer 

 응답 컨텐츠를 생성할 때 사용 

 @PathVariable 애노테이션 적용 파라미터 

 URI 템플릿 변수에 접근할 때 사용 

 @RequestParam 애노테이션 적용 파라미터 

 HTTP 요청 파라미터를 매핑 

 @RequestHeader 애노테이션 적용 파라미터 

 HTTP 요청 헤더를 매핑 

 @CookieValue 애노테이션 적용 파라미터 

 HTTP 쿠키 매핑 

 @RequestBody 애노테이션 적용 파라미터 

 HTTP 요청의 몸체 내용에 접근할 때 사용(HttpMessageConverter를 이용, HTTP 요청 데이터를 해당 타입으로 변환) 

 Map, Model, modelMap

 뷰에 전달할 모델 데이터를 설정할 때 사용 

 커맨드 객체 

 HTTP 요청 파라미터를 저장한 객체, 클래스이름을 모델명으로 사용(@ModelAttribute 애노테이션으로 모델명 설정)

 Errors, BindingResult

 HTTP 요청 파라미터를 커맨드 객체에 저장한 결과(커맨드 객체를 위한 파라미터 바로 다음에 위치) 

 SessionStatus 

 폼 처리 완료 처리하기 위해 사용(@SessionAttributes 애노테이션을 명시한 session 속성을 제거 이벤트 발생) 


6.4.1. @RequestParam 애노테이션 이용 파라미터 매핑

- HTTP 요청 파라미터를 메서드의 파라미터로 전달받을 때 사용

- 애노테이션이 적용된 파라미터가 String이 아닐 경우 실제 타입에 따라 알맞게 타입 변환 수행

- 필수가 아닌 파라미터인 경우 required 속성 값을 false로 지정 (기본 값은 true), 값은 null로 저장

- 필수가 아닌 파라미터인 경우 defaultValue 속성 값으로 기본값을 지정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ParamController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
 
@Controller
public class ParamController {
 
    @RequestMapping(value = "param.do", method = RequestMethod.GET)
    public String param(
        @RequestParam(value="name", required=falseString name,
        @RequestParam(value="age", defaultValue="1"int age) {
      return "param";
    }
// ParamController
cs


6.4.2. @CookieValue 애노테이션 이용 쿠키 매핑

- 쿠키 값을 파라미터로 전달 받을 때 사용

- 해당 쿠키가 존재하지 않으면 500 응답 에러 코드 전송

- 쿠키가 필수가 아닌 경우 파라미터와 같이 required 속성의 값을 false로 지정 (기본값은 true), 값은 null로 저장

- 필수가 아닌 쿠키인 경우 defaultValue 속성 값으로 기본값을 지정



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// CookieController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class CookieController {
   
  @RequestMapping(value = "cookie.do", method = RequestMethod.GET)
  public String cookie(
      @CookieValue(value="name", required=falseString name,
      @CookieValue(value="age", defaultValue="1"int age) {
    return "cookie";
  }
// CookieController
cs

6.4.3. @RequestHeader 애노테이션 이용 헤더 매핑

- HTTP 요청 헤더의 값을 메서드의 파라미터로 전달 받을 때 사용

- 해당 헤더가 존재하지 않으면 500 응답 에러 코드 전송

- required 속성과 defaultValue 속성을 위와 같이 사용 가능


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// HeaderController.java
 
package com.tistory.gangzzang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class HeaderController {
   
  @RequestMapping(value = "header.do", method = RequestMethod.GET)
  public String header(
      @RequestHeader(value="Accept-Language", required=falseString languageHeader,
      @RequestHeader(value="user-agent", defaultValue="모름"String agentHeader) {
    return "header";
  }
// HeaderController
cs


6.4.4. 서블릿 API 직접 사용

- javax.servlet.http.HttpServletRequest / javax.servlet.ServletRequest

- javax.servelt.http.HttpServletResponse / javax.servlet.ServletResponse

- javax.servlet.http.HttpSession

- 스프링 MVC 제공 애노테이션을 이용 정보(파라미터, 헤더, 쿠키, 세션 등)에 접근 할 수 있기 때문에 직접적으로 서블릿 API를 사용해야 하는 경우는 드뭄

- 세가지 경우에 사용(HttpSession의 생성을 직접 제어, 컨트롤러에서 쿠키를 생성, 서블릿 API 사용을 선호)


6.5. 컨트롤러 메서드 리턴 타입

- ModelAndView : 뷰 정보 및 모델 정보를 담고 있는 ModelAndView 객체

- Model : 뷰에 전달할 객체 정보를 담고 있는 Model을 리턴, 뷰 이름은 요청 URL로 부터 결정(RequestTOViewNameTranslator를 통해 뷰 결정)

- Map : 뷰에 전달할 객체 정보를 담고 있는 Map을 리턴, 뷰 이름은 요청 URL로 부터 결정(RequestTOViewNameTranslator를 통해 뷰 결정)

- String : 뷰 이름을 리턴

- View 객체 : View 객체를 직접 리턴, 해당 View 객체를 이용해서 뷰를 생성

- void : 메서드가 ServletResponse나 HttpServletResponse 타입의 파라미터를 갖는 경우 메서드가 직접 응답을 처리한다고 가정, 그렇지 않을 경우 요청 뷰 이름은 요청 URL로부터 결정

- @ResponseBody : 메서드에서 @ResponseBody 애노테이션이 적용된 경우 리턴 객체를 HTTP 응답으로 전송, HttpMessageConverter를 이용해서 객체를 HTTP 응답 스트림으로 변환


6.6. 컨트롤러 클래스 자동 스캔

- @Controller 애노테이션은 @Component 애노테이션과 마찬가지로 컴포넌트 스캔 대상

- <context:component-scan> 태그를 이용 컨트롤러 클래스를 자동으로 로딩

- base-package 속성에 자동 스캔할 패키지 경로를 입력

- 복수의 패키지를 사용하고 싶은 경우 <context:component-scan> 태그를 복수개 작성


1
2
3
4
5
6
7
8
9
10
11
12
<!--?xml version="1.0" encoding="UTF-8"?-->
<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemalocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">
 
 
  <context:component-scan base-package="com.tistory.gangzzang.controller"></context:component-scan>
</beans>
cs


반응형
반응형

mysql의 최대 성능 향상 방법

10.1 버퍼 크기 조정
mysqld 서버가 사용하는 기본 버퍼 크기는 다음의 명령으로 알 수 있다.

shell> mysqld --help

이 명령은 모든 mysqld 옵션의 목록과 설정 변수를 보여준다. 출력되는 내용은 기본값을 
포함하고 있으며 다음과 비슷하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Possible variables for option --set-variable (-O) are:
back_log current value: 5
connect_timeout current value: 5
join_buffer current value: 131072
key_buffer current value: 1048540
long_query_time current value: 10
max_allowed_packet current value: 1048576
max_connections current value: 90
max_connect_errors current value: 10
max_join_size current value: 4294967295
max_sort_length current value: 1024
net_buffer_length current value: 16384
record_buffer current value: 131072
sort_buffer current value: 2097116
table_cache current value: 64
tmp_table_size current value: 1048576
thread_stack current value: 131072
wait_timeout current value: 28800
cs


mysqld 서버가 현재 가동중이면 다음의 명령을 통해 실제 변수값을 볼 수 있다.

shell> mysqladmin variables

각 옵션은 밑에서 설명한다. 버퍼 크기, 길이, 스택 크기는 바이트이다. 'K'(킬로바이트) 
나 'M'(메가바이트)를 앞에 붙여 값을 지정할 수 있다. 예를 들면 16M는 16 메가바이트를 
가리킨다. 대소문자는 구별하지 않는다. 16M 와 16m은 같다.

-back_log 
mysql이 가질 수 있는 최대 연결 요청의 수. 이것은 main mysql 스레드가 매우 짧은 시간
동안 매우 많은 연결 요청을 받을 때 기능을 한다. 이때 메인 스레드가 연결을 체크하고 새
로운 스레드를 시작하는데는 약간의 시간이 걸린다.(그러나 아주 짧은 시간임) back_log 값
은 mysql이 순간적으로 새로운 요청에 답하는 것을 멈추기전에 이 짧은 시간동안 얼마나 
많은 요청을 쌓아두고 있는지를 지정한다. 매우 짧은 시간동안 매우 많은 연결이 예상될때
만 이 값을 증가시켜야 한다.

다른 말로 이 값은 tcp/ip 연결을 받는 listen queue의 크기이다. 각 운영체제마다 이러한 큐
의 크기에 한계가 있다. Unix system call listen(2) 매뉴얼페이지에 자세한 정보가 있다. ba
ck_log값의 한계는 운영체제 문서를 확인해봐라. back_log를 최대값보다 더 높여도 효과가 
없다. 

-connect_timeout 
Bad handshake에 반응하기 전에 연결 패킷을 mysql 서버에서 기다리는 시간.(초)

-join_buffer 
(인덱스를 사용하지 않는 조인의) full-join에서 사용하는 버퍼의 크기. 버퍼는 두 테이블 사
이에서 각 full-join마다 한번 할당이 된다. 인덱싱을 추가하지 못할 때 조인 버퍼를 증가시
키면 full join의 속도를 향상시킬 수 있다. (일반적으로 빠르게 조인을 하는 가장 좋은 방법
은인덱스를 추가하는 것이다)

-key_buffer 
인덱스 블락은 버퍼링되고 모든 스레드에서 공유한다. 키 버퍼는 인덱스 블락에서 사용하는 
버퍼의 크기이다. 인덱스가 많은 테이블에서 delete나 insert 작업을 많이 하면 키 버퍼값을 
증가시키는 것이 좋다. 더 빠른 속도를 내려면 LOCK TABLES를 사용하자. [Lock Tables] 
참고.

-max_allowed_packet 
한 패킷의 최대 크기. 메시지 버퍼는 net_buffer_length 바이트로 초기화되지만 필요하면 최
대 허용 패킷 바이트를 증가시킬 수 있다.기본값은 큰 패킷을 잡기에는 작다. 거대 BLOB 
컬럼을 사용한다면 값을 증가시켜야 한다. 사용자가 원하는 최대 blob만큼 크게 해야 한다. 

-max_connections 
동시 클라이언트 숫자. mysqld가 필요로하는 파일 지시자(descriptor)의 숫자만큼 값을 늘려
야 한다. 밑에서 파일 디스크립터 제한에 대한 내용을 참고하자.

-max_connect_errors 
호스트에서 최대 연결 에러이상의 interrupted 연결이 있으면 더 많은 연결을 위해 호스트는 
block화된다. FLUSH HOSTS 명령으로 호스트의 block을 해제할 수 있다.

-max_join_size 
최대 조인 크기이상으로 레크도를 읽는 조인을 하면 에러가 난다. 만약 사용자가 where 문
을 사용하지 않고 시간이 많이 걸리면서 몇백만개의 레코드를 읽는 조인을 수행하려 하면 
이 값을 설정한다.

-max_sort_length 
BLOB나 TEXT 값으로 정열할때 사용하는 바이트의 숫자. (각 값중 오직 첫번째 max_sort
_length 바이트만 사용된다. 나머지는 무시된다)

-net_buffer_length 
질의에서 통신 버퍼가 초기화되는 크기. 일반적으로 바뀌지 않지만 매우 적은 메모리를 가
지고 있을 때 예상되는 질의에 맞게 세팅할 수 있다. (이것은 클라이언트에 가는 예상된 sql 
문의 길이이다. 질의문이 이 크기를 넘으면 버퍼는 자동으로 max_allowed_packet 바이트까
지 증가한다) 

-record_buffer 
순차적인 검색을 하는 각 스레드에서 각 검색 테이블에 할당하는 버퍼 크기. 순차적인 검색
을 많이 하면 이 값을 증가시켜야 한다.

-sort_buffer 
정렬이 필요한 각 스레드에서 할당하는 버퍼 크기. order by 나 group by 오퍼레이션을 빠
르게 하려면 이 값을 증가시킨다. 16.4 [임시 파일] 참고.

-table_cache 
모든 스레드에서 열 수 있는 테이블의 숫자. mysqld가 필요로 하는 파일 디스크립터의 숫
자만큼 이 값을 증가시켜라. mysql은 각 유일한 오픈 테이블에서 두개의 파일 디스크립터가 
필요하다. 파일 디스크립터 제한을 참고한다. 테이블 캐쉬가 어떻게 작동하는지는 10.6 [테
이블 캐쉬]를 참고한다.

-tmp_table_size 
임시 테이블이 이 값을 넘으면 mysql은 "The Table tbl_name is full"이라는 에러 메시지를 
낸다. 매우 많은 group by 질의를 사용하면 이 값을 증가시켜야 한다.

-thread_stack 
각 스레드의 스택 사이즈. creash-me test(**역자주 : 데이터베이스의 벤치마킹을 하는 테스
트입니다. 말그대로 데이터베이스를 죽여주지요) 에서 잡히는 많은 제한은 이 값에 달려있
다. 기본값은 일반적으로 충분히 크다. 11장의 [벤치마크] 참조

-wait_timeout 
연결을 끊기전에 연결 활동(activity)을 서버에서 기다리는 시간(초).

table_cache 와 max_connections는 서버가 열 수 있는 최대 파일 갯수에 영향을 미친다. 이 
값을 증가시키면 운영시스템에서 오픈 파일 디스크립터의 per-process 숫자의 한계까지 올
릴 수 있다. (** ... imposed by your operating system on the per-process number of
open file descriptors. 번역이 이상하므로 영문 참고)
그러나 많은 시스템에서 이 한계를 증가시킬수 있다. 이렇게 하려면 각 시스템에서 이 한계
를 변화시키는 방법이 매우 다양하므로 운영체제 문서를 참고해야 한다.

table_cache 는 max_connections 와 관계가 있다. 예를 들면 200개의 연결이 있으면 최소 2
00 * n 의 테이블 캐쉬를 가져야 한다. 여기서 n은 조인에서 테이블의 최대 숫자이다.

mysql은 매우 유용한 알고리즘을 사용하기 때문에 일반적으로는 매우 적은 메모리로 사용
할 수 있으며 메모리가 많을 수록 성능이 더 많이 향상된다.

많은 메모리와 많은 테이블을 가졌고 중간정도 숫자의클라이언트에서 최대의 성능을 원한다
면 다음과 같이 사용한다.

1
2
3
 
shell> safe_mysqld -O key_buffer=16M -O table_cache=128 
-O sort_buffer=4M -O record_buffer=1M &
cs


메모리가 적고 연결이 많으면 다음과 같이 사용한다.

1
2
shell> safe_mysqld -O key_buffer=512k -O sort_buffer=100k 
-O record_buffer=100k &
cs


또는: 

1
2
shell> safe_mysqld -O key_buffer=512k -O sort_buffer=16k 
-O table_cache=32 -O record_buffer=8k -O net_buffer=1K &
cs


매우 많은 연결이 있을 때 mysqld가 각 연결마다 최소한의 메모리를 사용하도록 설정하지 
않았다면 "swapping problems" 문제가 생길 것이다.

mysqld에서 옵션을 바꾸었으면 그것은 서버의 해당하는 인스턴스에만 영향을 미친다는 것
을 기억하자.

옵션을 바꾸었을때의 효과를 보기 위해 다음과 같이 해보자.

shell> mysqld -O key_buffer=32m --help

마지막에 --help 옵션이 들어간 것을 기억하자. 그렇지 않으면 커맨드 라인에서 사용한 옵
션의 효력은 출력에는 반영되지 않을 것이다. 


10.2 메모리 사용 방법 <메모리 최적화>

아래에서 설명하는 목록은 mysqld 서버가 메모리를 사용하는 방법에 대해서 나타내고 있
다. 메모리 사용과 관련된 서버의 변수 이름이 주어진다.


- 키 버퍼(변수 key_buffer)는 모든 스레드에서 공유한다. 서버에서 사용하는 다른 버퍼는 
필요한대로 할당이 된다.

- 각 연결은 각 스레드마다의 특정한 공간을 사용한다. 스택(64k, 변수 thread_stack) , 연결 
버퍼(변수 net_buffer_length), result 버퍼 (변수 net_buffer_length) 등. 연결 버퍼와 result 
버퍼는 필요할때 max_allowed_packet 까지 동적으로 증가된다. 질의가 수행될 때 현재의 
질의문의 복사문이 또한 할당이 된다. 
(** When a query is running a copy of the current query string is also alloced.) 

- 모든 스레드는 같은 기본 메모리를 공유한다.
- 메모리 맵은 아직 지원이 안된다. (압축 테이블을 제외하고. 그러나 이것은 다른 이야기이
다) 왜냐하면 4GB의 32비트 메모리 공간은 대부분의 대형 테이블에서 충분히 크기가 않기 
때문이다. 우리가 64비트 주소 공간을 가진 시스템을 가지게 될 때 우리는 메모리 맵핑을 
위한 일반적인 지원을 추가할 것이다.

- 테이블에서 순차적인 검색을 하는 각 요청은 read 버퍼에 할당이 된다. (변수 record_buff
er)

- 모든 조인은 한번에 수행이 되며 대부분의 조인은 임시 테이블을 생성하지 않고 수행이 
된다. 대부분의 테이블은 메모리 기반(HEAP) 테이블이다. 거대 길이의 레코드를 가졌거나 
BLOB 컬럼을 포함한 임시 테이블은 디스크에 저장이 된다. 현재의 문제는 메모리 기반 테
이블이 tmp_table_size를 초과했을때 "The table tbl_name is full"이라는 에러가 생기는 것
이다. 가까운 시일안에 필요할때 자동적으로 메모리 기반(HEAP) 테이블을 디스크 기반(NI
SAM) 테이블로 바꾸도록 고칠 것이다. 
이 문제를 해결하기 위해서 mysqld의 tmp_table_size 옵션을 설정하여 임시 테이블 크기를 
늘이거나 클라이언트 프로그램에서 SQL_BIG_TABLES라는 sql 옵션을 설정하여야 한다. 7.
24 SET OPTION 을 참고하자. 
mysql 3.20에서 임시 테이블의 최대 크기는 record_buffer*16이다. 3.20 버전을 사용하고 있
다면 record_buffer의 값을 증가시켜야 한다. 또한 mysqld를 시작할 때 --big-tables 옵션을 
사용하여 항상 임시 테이블을 디스크에 저장할 수 있지만 질의 속도에 영향을 미친다.

- 정열을 하는 대부분의 요청은 정렬 버퍼와 하나나 두개의 임시 파일을 할당한다. 16.4의 
[임시 파일]을 참고한다.

- 대부분의 파징(parsing)과 계산은 지역 메모리에서 이루어진다. 작은 아이템에는 메모리 o
verhead가 필요없고 일반적인 느린 메모리 할당(slow memory allocation)과 freeing(메모리 
해제)는 무시된다. 메모리는 오직 예상지 못한 거대 문자열에서 할당이 된다.( mallloc() 과 
free() 사용)

- 각 인덱스 파일은 한번에 열리며 각 병행수행되는 스레드에서 데이터 파일은 한번에 열
린다. 각 병행수행 스레드마다 테이블 구조, 각 컬럼의 컬럼 구조, 3 * n 의 버퍼 크기가 할
당된다. ( n은 최대 레코드 길이이며 BLOB 컬럼은 해당하지 않는다) BLOB는 BLOB 데이
터의 길이에 5에서 8 바이트를 더한 값을 사용한다.

- BLOB 컬럼을 가진 각 테이블에서 버퍼는 거대 BLOB 값을 읽을 수 있도록 동적으로 커
진다. 테이블을 검색하면 버퍼는 최대 BLOB의 값만큼 버퍼가 할당이 된다.

- 모든 사용중인 테이블의 테이블 핸들러는 캐쉬에 저장되며 FIFO로 관리가 된다. 일반적
으로 캐쉬는 64 엔트리를 갖는다. 동시에 두개의 실행 스레드에서 테이블을 사용하면 캐쉬
는 테이블의 두 엔트리를 포함한다. 10.6 [테이블 캐쉬]를 참고한다.

- mysqladmin flush-tables 명령은 사용하지 않는 모든 테이블을 닫고 현재 실행되는 스레
드가 끝날 때 모든 사용중인 테이블을 닫는다고 표시한다. 이것은 효과적으로 사용중인 메
모리를 해제한다. 


ps 와 다른 시스템 상황 프로그램은 mysqld가 많은 메모리를 사용하고 있다고 보고할 것이
다. 이것은 다른 메모리 주소의 스레드-스택때문에 생긴다. 예를 들면 솔라리스의 ps 는 스
택사이의 사용하지 않는 메모리를 사용하는 메모리로 간주한다. 이것은 swap -s를 이용 사
용가능한 스왑을 체크하여 확인할수 있다. 우리는 mysqld를 상용 메모리 유출 측정 프로그
램으로 테스팅해서 mysqld에는 메모리 유출이 없다.


10.3 속도 향상에 영향을 미치는 컴파일/링크 방법 <컴파일시 최적화하기>

다음 테스트의 대부분은 리눅스와 mysql 벤치마크를 가지고 수행되었지만 다른 운영 시스
템에도 암시해주는 것이 있다. 

static으로 링크를 할때 가장 빠른 실행 속도를 얻을 수 있다. 데이터베이스에 연결하기 위
해 TCP/IP보다는 유닉스 소켓을 사용하면 더 좋은 성능을 낼 수 있다. 

리눅스에서 pgcc와 -O6을 사용하면 가장 빠르다. 'sql_yacc.cc'를 이 옵션으로 컴파일하려면 
gcc/pgcc는 모든 성능을 내기 위해 많은 메모리가 필요하기 때문에 180M의 메모리가 필요
하다. 또한 mysql을 설정할때 libstdc++ 라이브러리를 포함하지 않기 위해 CXX=gcc라고 설
정해야 한다.

- pgcc를 사용하고 모두다 -O6 옵션으로 컴파일하면 mysqld 서버는 gcc로 컴파일한 것보
다 11% 빨라진다.

- 동적으로 링크하면 (-static을 사용하지 않고) 13% 느려진다.
If you connect using TCP/IP rather than Unix sockets, the result is 7.5% slower. 
- 유닉스 소켓을 사용하는 것보다 tcp/ip로 연결하는 것이 7.5% 느려진다.

- On a Sun sparcstation 10, gcc 2.7.3 is 13% faster than Sun Pro C++ 4.2. 
- On Solaris 2.5.1, MIT-pthreads is 8-12% slower than Solaris native threads. 
(** 번역을 안한 이후. 리눅스랑 상관없으니깐... **)

TcX에서 제공한 mysql 리눅스 배포판은 pgcc로 컴파일되었고 정적으로 링크되었다.


10.4 How MySQL uses indexes

prefix- and end-space compressed. See section 7.26 CREATE INDEX syntax (Compatibil
ity function). 

모든 인덱스(PRIMARY, UNIQUE and INDEX()) 는 B-trees 에 저장된다. 문자열은 자동적
으로 앞 뒤의 공간(?)이 압축된다. 7.26 [인덱스 생성] 참고. 

인덱스의 사용 : 
- WHERE 문에서 해당하는 레코드 빨리 찾기
- 조인을 수행할때 다른 테이블에서 레코드 가져오기
- 특정 키에서 MAX() 나 MIN() 값 찾기
- 소팅이나 그룹화할때 인덱스 키를 사용하면 테이블을 정열하거나 그룹화한다. 키에 DES
C가 붙으면 역순으로 인덱스를 읽는다.
- 어떤 경우에는 데이터 파일에 묻지 않고 값을 가져온다. 어떤 테이블에서 사용하는 모든 
컬럼이 숫자이고 특정 키로 형성되어있으면 빠른 속도로 인덱스 트리에서 값을 가져올 수 
있다.

다음 예제를 보자.

1
mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
cs



다중 컬럼 인덱스가 col1 과 col2에 있으면 해당하는 레코드를 직접 가져올 수 있다. 분리
된 단일 컬럼 인덱스가 col1 과 col2 에 있으면 최적화기는 어떤 인덱스가 더 적은 레코드
를 가졌는지 확인하고 레코드를 가져오기 위해 그 인덱스를 사용하도록 결정한다.

테이블이 다중 컬럼 인덱스를 가졌다면 최적화기가 레코드를 찾는데 어떤 인덱스키를 사용
할 수 있다. 예를 들면 세가지 컬럼 인덱스(col1, col2, col3)를 가졌다면 (col1), (col1,col2) 
(col1,col2,col3) 인덱스를 사용하여 검색을 할 수 있다. 

MySQL can't use a partial index if the columns don't form a leftmost prefix of the inde
x. 
Suppose you have the SELECT statements shown below: 
(** 해석이 잘 안되는데 예제를 보시면 무슨 말인지 알 수 있을 것임**)

1
2
3
mysql> SELECT * FROM tbl_name WHERE col1=val1;
mysql> SELECT * FROM tbl_name WHERE col2=val2;
mysql> SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
cs


If an index exists on (col1,col2,col3), only the first query shown above uses the index. 
The second and third queries do involve indexed columns, but (col2) and (col2,col3) are 
not leftmost prefixes of (col1,col2,col3). 

인덱스가 (col1,col2,col3)로 있다면 위의 질의중 오직 첫번째 질의만 인덱스를 사용한다. 두
번째 및 세번째 질의은 인덱스된 컬럼이 포함되어 있지만 (col2) 와 (col2,col3)는 (col1,col2,c
ol3) 인덱스에 해당하지 않는다.

MySQL also uses indexes for LIKE comparisons if the argument to LIKE is a constant 
string that doesn't start with a wildcard character. For example, the following SELECT 
stat ements use indexes: 

mysql은 또한 LIKE의 인수가 와일드카드 문자로 시작하지 않는 상수 문자열일이라면 LIK
E 비교문에서 인덱스를 사용한다. 예를 들어 다음의 SELECT 문은 인덱스를 사용한다.

1
2
mysql> select * from tbl_name where key_col LIKE "Patrick%";
mysql> select * from tbl_name where key_col LIKE "Pat%_ck%";
cs


첫번째 문장에서는 "Patrick" <= key_col < "Patricl" 을 가진 레코드만 고려된다. 두번째 문
장에서는 "Pat" <= key_col < "Pau" 을 가진 레코드만 고려된다. 


다음의 SELECT 문은 인덱스를 사용하지 않는다:

1
2
mysql> select * from tbl_name where key_col LIKE "%Patrick%";
mysql> select * from tbl_name where key_col LIKE other_col;
cs


첫번째 문장에서 LIKE 값은 와일드카드 문자로 시작하고 있다. 두번째 문장에서는 LIKE 
값이 상수가 아니다.



10.5 WHERE 문에서 최적화하기
(이번 절은 완전한 내용을 포함하고 있지는 않다. mysql은 많은 최적화방법이 있다.)

In general, when you want to make a slow SELECT ... WHERE faster, the first thing t
o check is whether or not you can add an index. All references between different tables 
should usually be done with indexes. You can use the EXPLAIN command to determine 
which indexes are used for a SELECT. See section 7.21 EXPLAIN syntax (Get informat
ion about a SELECT). 
일반적으로 느린 SELECT ... WHERE 문을 빠르게 하려면 가장 먼저 확인해야 할 것이 인
덱스 추가 문제이다. 다른 테이블사이에서 모든 레퍼런스(references 참조)는 일반적으로 인
덱스에 의해 수행된다. SELECT 문에서 어떤 인덱스를 사용하는지 결정하기 위해 EXPLAI
N 명령을 사용할 수 있다. 7.21 [Explain]을 참고.

mysql에서 수행하는 최적화는 다음과 같다.


- 불필요한 삽입어 제거

((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b ANDc) OR (a AND b AND c AND d)

-상수 폴딩(folding)

(a b>5 AND b=c AND a=5

- 상수 조건 제거(상수 폴딩때문에 필요)

(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6

- 인덱스에서 사용되는 상수 표현은 한번에 계산된다.
(Constant expressions used by indexes are evaluated only once.) 

- WHERE 절이 없는 단일 테이블의 COUNT(*)는 테이블 정보에서 직접 값을 가져온다. 
단일 테이블에서 사용된 NOT NULL 표현도 이와 같이 수행된다. 

- 유효하지 않은 상수 표현은 미리 제거된다. mysql은 불가능하고 해당하는 레코드가 없는 
SELECT 문을 빠르게 감지한다.

- GROUP BY 나 그룹 펑션(COUNT(), MIN() ...)을 사용하지 않으면 HAVING은 WHERE 
에 합쳐진다.
(** HAVING 절에서는 인덱스를 사용하지 못함. 그러므로 가능한 HAVING절을 사용하지 
않는게 속도면에서 좋다 **) 

- 각 서브 조인에서 빠르게 WHERE 문을 계산하고 가능한한 레코드를 제외하도록 간소하
게 WHERE 문이 만들어진다.

- mysql은 일반적으로 최소한의 레코드를 찾기 위해 인덱스를 사용한다. =, >, >=, <, <=, 
BETWEEN 그리고 'something%' 처럼 앞이 와일드카드로 시작하지 않는 LIKE 문등을 
사용하여 비교를 할 때 인덱스를 사용한다. (** 10.4 절에서 설명하였듯이 like 를 사용할때 
와일드카드로 시작하는 like 문을 사용하면 인덱스를 사용하지 않는다. 일정한 단어로만 시
작하는 컬럼에서 자료를 찾을 때 유용할 것이다. **)

- Any index that doesn't span all AND levels in the WHERE clause is not used to opti
mize the query. 

다음의 WHERE 문은 인덱스를 사용한다.: 

1
2
3
4
... WHERE index_part1=1 AND index_part2=2
... WHERE index=1 OR A=10 AND index=2 /* index = 1 OR index = 2 */
... WHERE index_part1='hello' AND index_part_3=5
/* optimized like "index_part1='hello'" */
cs


다음의 WHERE 문은 인덱스를 사용하지 않는다.: 

1
2
3
... WHERE index_part2=1 AND index_part3=2 /* index_part_1 is not used */
... WHERE index=1 OR A=10 /* No index */
... WHERE index_part1=1 OR index_part2=10 /* No index spans all rows */
cs


- 질의에서 다른 테이블보다 모든 상수 테이블을 먼저 읽는다. 상수 테이블은 다음과 같다.
ㅇ빈 테이블이나 1개의 레코드만 있는 테이블
ㅇWHERE 문에서 UNIQUE 인덱스나 PRIMARY KEY 를 사용하고 모든 인덱스
는 상수 표현으로된 테이블 

다음의 테이블은 상수 테이블로 사용된다.

1
2
3
mysql> SELECT * FROM t WHERE primary_key=1;
mysql> SELECT * FROM t1,t2
WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
cs


- 모든 가능성을 시도하여 테이블을 조인하는데 가장 좋은 조인 조합을 찾는다. (ORDER B
Y나 GROUP BY의 모든 컬럼이 동일한 테이블에서 나오면 조인을 할때 이 테이블이 먼저 
선택된다)

- ORDER BY 문과 다른 GROUP BY 문이 있을 때, 또는 ORDER BY 나 GROUP BY가 
조인 큐의 첫번째 테이블이 아닌 다른 테이블의 컬럼을 포함하고 있으면 임사 테이블을 만
든다.

- 각 테이블 인덱스를 찾고 레코드의 30%미만을 사용하는 (best) 인덱스가 사용된다. 그런 
인덱스가 없으면 빠른 테이블 검색이 사용된다.

- 어떤 경우에는 mysql은 데이터 파일을 조회하지 않고 인덱스에서 레코드를 읽을 수 있
다. 인덱스에서 사용한 모든 컬럼이 숫자라면 질의를 처리하는데 단지 인덱스 트리만을 사
용한다.

- 각 레코드가 출력되기 전에 HAVING 절에 맞지 않는 레코드는 건너뛴다.

다음은 매우 빠른 질의의 예이다:

1
2
3
4
5
6
7
8
mysql> SELECT COUNT(*FROM tbl_name;
mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
mysql> SELECT MAX(key_part2) FROM tbl_name
WHERE key_part_1=constant;
mysql> SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... LIMIT 10;
mysql> SELECT ... FROM tbl_name
ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;
cs


다음의 커리는 인덱스 트리만을 사용하여 값을 구한다.(인덱스 컬럼은 숫자라고 가정):

1
2
3
4
mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
mysql> SELECT COUNT(*FROM tbl_name
WHERE key_part1=val1 and key_part2=val2;
mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;
cs


다음의 질의는 개별적인 정열을 하지 않고 정열된 순서대로 열을 가져오는 데 인덱스를 사
용한다:

1
2
mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,...
mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2 DESC,...
cs



10.6 테이블 열고 닫는 방법

open 테이블의 캐쉬는 table_cache의 최대값까지 커질 수 있다. (기본값 64 ; 이 값은 mysql
d에서 -0 table_cache=# 으로 바꿀 수 있다) 캐쉬가 꽉 찼을때, 그리고 다른 스레드가 테이
블을 열려고 할 때, 또는 mysqladmin refresh 나 mysqladmin flush-tables를 사용할때를 제
외하고는 테이블은 결코 닫히지 않는다.

테이블 캐쉬가 꽉 차면 서버는 캐쉬 엔트리를 사용하도록 조절하기 위해 다음의 절차를 사
용한다.

- 가장 먼저 사용했던 순서대로 현재 사용하지 않는 테이블을 닫는다.
- 캐쉬가 꽉 찼고 어떤 테이블도 닫히지 않지만 새로운 테이블을 열어야 한다면 캐쉬가 필
요한 만큼 임시적으로 확장된다.
- 캐쉬가 임시적으로 확장된 상태이고 테이블을 사용할 수 없는 상황으로 가면 테이블을 
닫고 캐쉬를 해제한다.

테이블은 각 동시병행적인 접근때마다 열린다. 동일한 테이블에 접근하는 두개의 스레드가 
있거나 같은 질의에서 테이블에 두번 접근하면(with AS) 테이블을 두번 열여야 한다는 의
미이다. 테이블의 첫번째 개방은 두개의 파일 디스크립터를 가진다. ; 추가적인 테이블의 개
방은 하나의 파일 디스크립터를 가질 뿐이다. 처음에 개방에 사용하는 추가적은 파일 디스
크립터는 인덱스 파일에 사용된다. ; 이 디스크립터는 모든 스레드에서 공유된다.


10.6.1 데이터베이스에서 많은 수의 테이블을 만들때의 단점

디렉토리에 많은 파일이 있다면 open, close 그리고 create 오퍼레이션은 느려질 것이다. 서
로 다른 많은 테이블에서 SELECT 문을 수행하면 테이블 캐쉬가 꽉 찰 때 약간의 overhea
d가 있을 것이다. 왜냐면 개방된 테이블이 있다면 다른 테이블은 닫혀야 하기 때문이다. 테
이블 캐쉬를 크게 해서 이러한 오우버헤드를 줄일 수 있다.


10.7 많은 테이블을 여는 이유

mysqladmin status 를 실행할 때 다음과 같이 나올 것이다:

1
Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables12
cs


단지 6테이블을 사용했는데 이러한 결과는 당황스러울 것이다.

mysql은 멀티스레드를 사용한다. 그래서 동시에 같은 테이블에서 많은 질의를 할 수 있다. 
같은 파일에 대하여 다른 상황을 가지는 두개의 스레드에 대한 문제를 줄이기 위해 테이블
은 각 동시병행적인 스레드마다 독립적으로 개방된다. 이것은 테이타 파일에서 약간의 메모
리와 하나의 추가적인 파일 디스크립터를 사용한다. 모든 스레드에서 인덱스 파일은 공유된
다.


10.8 데이터베이스와 테이블에서 심볼릭 링크 사용

데이터베이스 디렉토리에서 테이블과 데이터베이스를 다른 위치로 옮기고 새로운 위치로 심
볼릭 링크를 사용할 수 있다. 이렇게 하는 것을 원할 경우가 있다. 예를 들면 데이터베이스
를 더 여유공간이 많은 파일시스템으로 옮기는 경우 등.

mysql에서 테이블이 심볼링 링크되었다는 것을 감지하면 심볼링 링크가 가리키는 테이블을 
대신 사용할 수 있다. realpath() call 을 지원하는 모든 시스템에서 작동한다. (최소한 리눅
스와 솔라리스는 realpath()를 지원한다) realpath()를 지원하지 않는 시스템에서 동시에 실
제 경로와 심볼릭 링크된 경로에 접근하면 안된다. 이런 경우에는 업데이트 된후에 테이블
이 모순될 수 있다.

mysql은 기본값으로 데이터베이스 링크를 지원하지 않는다. 데이터베이스간에 심볼릭 링크
를 사용하지 않는 작동을 잘 할 것이다. mysql 데이터 디렉토리에 db1 데이터베이스가 있
고 db1을 가리키는 db2 심볼릭 링크를 만들었다고 해보자:

shell> cd /path/to/datadir
shell> ln -s db1 db2

이제 db1에 tbl_a라는 테이블이 있다면 db2에도 tbl_a가 나타날 것이다. 한 스레드가 db1.tbl
_a를 업데이트하고 다른 스레드가 db2.tbl_a를 업데이트하면 문제가 생길 것이다.

정말로 이 기능이 필요하면 , `mysys/mf_format.c'에서 다음의 코드를 수정해야 한다.: 

if (!lstat(to,&stat_buff)) /* Check if it's a symbolic link */
if (S_ISLNK(stat_buff.st_mode) && realpath(to,buff))

위 코드를 다음과 같이 수정한다 : 

if (realpath(to,buff))


10.9 테이블에 락 거는 방법

mysql의 모든 락은 deadlock-free 이다. 언제나 질의를 시작할때 한번에 모든 필요한 락을 
요청하고 언제나 같은 순서대로 테이블에 락을 걸어 관리한다.

WRITE 락을 사용하는 방법은 다음과 같다:

- 테이블에 락이 없으면 그 테이블에 write 락을 건다. 
- 이런 경우가 아니라면 write 락 큐에 락을 요청한다.

READ 락을 사용하는 방법은 다음과 같다:

- 테이블에 write 락이 없으면 그 테이블에 read 락을 건다.
- 이런 경우가 아니라면 read 락 큐에 락을 요청한다.

락이 해제되었을 때 락은 write 락 큐의 스레드에서 사용할 수 있으며 그러고 나서 read 락 
큐의 스레드에서 사용한다.

테이블에서 업데이트를 많이 하면 SELECT 문은 더 이상 업데이트가 없을 때까지 기다린
다는 것을 의미한다.

이러한 문제를 해결하기 위해 테이블에서 INSERT 와 SELECT 오퍼레이션을 많이 사용하
는 경우에 다음과 같이 하면 된다. 임시 테이블에 레코드를 입력하고 한번에 임시 테이블에
서 실제 테이블로 레코드를 업데이트한다.

다음의 예를 보자:

1
2
3
4
5
mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> insert into real_table select * from insert_table;
mysql> delete from insert_table;
mysql> UNLOCK TABLES;
 
cs

만약 어떤 경우에 SELECT문에 우선권을 주고 싶다면 INSERT 옵션에서 LOW_PRIORITY 
or HIGH_PRIORITY 옵션을 사용할 수 있다. 7.13 [Insert] 참고. (** LOW_PRIORITY를 지
정하면 클라이언트에서 테이블을 읽지 않을 때까지 INSERT 문 수행이 미루어진다. **)

단일 큐를 사용하기 위해 `mysys/thr_lock.c' 의 락킹 코드를 바꿀 수 있다. 이런 경우 writ
e 락과 read 락은 같은 우선권을 가지며 어떤 애플리케이션에서는 유용할 수 있다.

10.10 테이블을 빠르고 작게 배열하는 방법 <** 테이블 최적화 **>

다음은 테이블에서 최대의성능을 내는 방법과 저장 공간을 절약할 수 있는 테크닉이다:

- 가능한한 NOT NULL로 컬럼을 선언한다. 속도가 빨라지며 각 컬럼마다 1 비트를 절약할 
수 있다.
- default 값을 가질 때 유리하다. 입력되는 값이 기본값과 다를 때만 확실하게 값이 입력된
다. INSERT 문에서 첫번째 TIMESTAMP 컬럼이나 AUTO-INCREAMENT 컬럼의 값을 
입력할 필요가 없다. 18.4.49 [mysql_insert_id()] 참고.
- 가능한한 테이블을 작게 만드려면 더 작은 integer 타입을 사용하자. 예를 들면 MEDIUM
INT 가 보통 INT 보다 좋다.
- 가변 길이 컬럼이 없다면(VARCHAR, TEXT or BLOB columns), 고정 길이 레코드 포
맷이 사용된다. 이 경우 속도는 더 빠르지만 불행히도(흑흑~) 낭비되는 공간이 더 많다. 10.1
4 [Row format] 참고.
- mysql이 질의를 효과적으로 최적화하기 위해 많은 양의 데이터를 입력한후 isamchk --a
nalyze를 실행하자. 이렇게 하면 동일한 값을 가진 줄의 평균 숫자를 가리키는 각 인덱스의 
값을 업데이트한다. (물론 unique 인덱스에서는 항상 1이다) 
- 인덱스와 인덱스에 따른 데이타를 정열하려면 
isamchk --sort-index --sort-records=1 을 사용하자.(if you want to sort on index 1). 
인덱스에 따라 정렬된 모든 레코드를 읽기 위해 unique 인덱스를 가졌다면 이렇게 하는 것
이 속도를 빠르게 하는 가장 좋은 방법이다.
- INSERT 문에서 가능한 다중 값 목록을 사용하자. 개별적인 SELECT 문보다 훨씬 빠르
다. 데이타를 테이블에 입력할 때 LOAD DATA INFILE을 사용하자. 많은 INSERT 문을 
사용하는 것보다 보통 20배 빠르다. 7.15 [Load] 참고.

많은 인덱스를 가진 테이블에 데이타를 입력할때 다음의 과정을 사용하면 속도를 향상시킬 
수 있다.
1. mysql이나 Perl 에서 CREATE TABLE로 테이블을 만든다.
2. mysqladmin flush-tables 실행. (** 열린 테이블을 모두 닫음 **)
3. isamchk --keys-used=0 /path/to/db/tbl_name 사용. 테이블에서 모든 인덱스 사용을 제
거한다. 
4. LOAD DATA INFILE 를 이용 테이블에 데이타를 입력.
5. pack_isam을 가지고 있고 테이블을 압축하기 원하면 pack_isam을 실행.
6. isamchk -r -q /path/to/db/tbl_name 를 이용 인덱스를 다시 생성.
7. mysqladmin flush-tables 실행.

- LODA DATA INFILE 과 INSERT 문에서 더 빠른 속도를 내려면 키 버퍼를 증가시킨
다. mysqld나 safe_mysqld에서 -O key_buffer=# 옵션을 사용하면 된다. 예를 들어 16M는 
풍부한 램을 가졌다면 훌륭한 값이다.
- 다른 프로그램을 사용하여 데이타를 텍스트 파일로 덤프할때 SELECT ... INTO OUTFIL
E 을 사용하자. 7.15 [LOAD DATA INFILE] 참고.
- 연속으로 다량의 insert와 update를 할 때 LOCK TABLE을 사용하여 테이블에 락을 걸
면 속도를 향상시킬 수 있다. LOAD DATA INFILE 그리고 SELECT ...INTO OUTFILE 
는 원자적이기 때문에 LOCK TABLE을 사용하면 안된다. 7.23 [LOCK TABLES/UNLOCK 
TABLES] 참고. 

테이블이 얼마나 단편화되었는지 점검하려면 '.ISM' 파일에서 isamchk -evi 를 실행한다. 1
3장 [Maintenance] 참고.



10.11 INSERT 문에서 속도에 영향을 미치는 부분 <** insert 최적화 **>

insert 하는 시간은 다음와 같이 구성된다:

Connect: (3) 
Sending query to server: (2) 
Parsing query: (2) 
Inserting record: (1 x size of record) 
Inserting indexes: (1 x indexes) 
Close: (1) 

(숫자)는 비례적인 시간이다. 이것은 테이블을 개방할때 초기의 overhead를 고려하고 있지
는 않다. (매 동시병행적으로 수행되는 질의마다 발생)

The size of the table slows down the insertion of indexes by N log N (B-trees).


테이블의 크기는 N log N(B-trees)에 따라 인덱스의 입력이 느려진다. (**말이 좀 이상. 테
이블이 커짐에 따라 인덱스 생성도 느려진다는 뜻이겠죵 **)

테이블에 락을 걸거나 insert 문에서 다중 값 목록을 사용하여 입력 속도를 빠르게 할 수 
있다. 다중 값 목록을 사용하면 단일 insert 보다 5배 정도 속도가 빨라진다.

1
2
3
4
5
mysql> LOCK TABLES a WRITE;
mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33);
mysql> INSERT INTO a VALUES (8,26),(6,29);
mysql> UNLOCK TABLES;
 
cs

주요한 속도 차이는 모든 INSERT 문이 완료되고 난 후에 한번에 인덱스 버퍼가 쓰여기지 
때문에 생긴다. 보통 서로 다른 여러 INSERT 문이 있으면 많은 인덱스 버퍼 플러쉬가 있
을 것이다. 모든 줄을 단일 문으로 입력하면 락은 필요없다.

락킹은 또한 다중 연결 테스트의 총 시간을 줄일 수는 있다. 그러나 어떤 스레드에서는 총 
대기시간은 증가할 수 있다.(왜냐면 락을 기다리기 때문이다)
예를 들어보자:

thread 1 does 1000 inserts
thread 2, 3, and 4 does 1 insert
thread 5 does 1000 inserts

락을 사용하지 않으면 2, ,3 4는 1과 5 전에 끝마칠 것이다. 락을 사용하면 2,3,4는 아마도 1
이나 5 전에 끝나지 않을 것이다. 그러나 총 시간은 40% 빨라진다.

INSERT, UPDATE, DELETE 오퍼레이션은 mysql에서 매우 빠르다. 그렇기 때문에 줄에서 
5개 이상의 insert나 update를 할 때 락을 추가하면 더 좋은 성능을 얻을 수 있다. 줄에 매
우 많은 자료를 입력한다면 다른 스레드에서 테이블에 접근하도록 하기 위해 때때로(각 100
0줄마다) UNLOCK TABLES를 사용하는 LOCK TABLES 실행하면 된다. 이렇게 하면 좋
은 성능을 낼 수 있다. (** 열심히 입력을 하고 중간에 락을 풀었다가 다시 락을 거는 것 
반복함**)

물론 LOAD DATA INFILE 이 더 빠르다.



10.12 DELETE 문에서 속도에 영향을 미치는 부분 <** DELETE 문 최적화 **>

레코드를 삭제하는 시간은 정확히 인덱스 숫자에 비례한다. 레코드를 빠르게 지우기 위해 
인덱스 캐쉬의 크기를 증가시킬 수 있다. 기본 인덱스 캐쉬는 1M 이다; 빠르게 삭제하기 위
해 증가되어야 한다.(충분한 메모리를 가지고 있다면 16M로 하자)


10.13 mysql에서 최대 속도를 얻는 방법

벤치마킹을 시작하자! mysql 벤치마크 스위트에서 어떤 프로그램을 사용할 수 있다. (일반
적으로 'sql-bench' 디렉토리에 있음) 그리고 입맞에 맞게 수정하자. 이렇게 하면 당신의 문
제를 해결할 수 있는 다른 해결책을 찾을 수 있으며 당신에게 가장 빠른 해결책을 테스트할 
수 있다.

- mysqld를 적절한 옵션으로 시작하자. 메모리가 많을수록 속도가 빠르다.
10.1 [MySQL parameters] 참고.
- SELECT 문의 속도를 빠르게 하기 위해 인덱스를 만들자. 
10.4 [MySQL indexes] 참고.
- 가능한 효율적으로 컬럼 타입을 최적화하자. 예를 들면 가능한 NOT NULL로 컬럼을 정
의하자. 10.10 [Table efficiency] 참고.
- --skip-locking 옵션은SQL 요청에서 파일 락킹을 없앤다. 속도가 빨라지지만 다음의 과
정을 따라야 한다:
ㅇ isamchk로 테이블을 체크하거나 수리하기 전에 mysqladmin flush-tables 로 모
든 테이블을 플러시해야 한다. (isamchk -d tbl_name은 언제나 허용된다. 왜냐하면 이건 단
순히 테이블의 정보를 보여주기 때문이다)
ㅇ 동시에 뜬 두개의 mysql 서버가 동일한 테이블을 업데이트하려 한다면 동일한 
데이터 파일에 두개의 mysql 서버를 띄우면 안된다.

--skip-locking 옵션은 MIT-pthreads로 컴파일할때 기본값이다. 왜냐면 모든 플랫
폼의 MIT-pthreads에서 flock()가 완전하게 지원이 되지 않기 때문이다.

- 업데이트에 문제가 있다면 업데이트를 미루고 나중에 하자. 많은 업데이트를 하는 것이 
한번에 하나를 업데이트하는 것보다 더 빠르다.
- FreeBSD 시스템에서 MIT-pthreads에 문제가 있으면 FreeBSD 3.0 이후 버전으로 업데
이트 하는것이 좋다. 이렇게 하면 유닉스 소켓을 사용하는 것이 가능하며(FreBSD에서 유닉
스 소켓이 MIT-pthreads에서 TCP/IP 연결을 사용하는 것보다 빠르다) 그리고 스레드 패키
지가 조정(intergrated?)되어야 한다.
- 테이블이나 컬럼 단계를 체크하는 GRANT는 성능을 떨어뜨린다.


10.14 로우 포맷과 다른 점은 무엇인가? 언제 VARCHAR/CHAR을 사용해야 하는가?

mysql은 실제의 SQL VARCHAR 타입이 없다. 그대신 mysql은 레코드를 저장하고 이것을 
VARCHAR로 에뮬레이트하는데 세가지 방법이 있다.

테이블에 VARCHAR, BLOB, TEXT 컬럼이 없으면 고정 row size를 사용한다. 그외에는 
동적 row size를 사용한다. CHAR 과 VARCHAR 컬럼은 애플리케이션의 관점에서 동일하
게 취급된다; 둘다 trailing space는 컬럼을 가져올때 제거된다.

isamchk -d 를 이용 테이블에서 사용하는 포맷을 체크할 수 있다.
(-d 는 "테이블 묘사"를 의미)

mysql은 세가지 다른 테이블 포맷을 가지고 있다; 고정길이, 다이나믹, 압축.


고정 길이 테이블
- 기본 포맷. 테이블에 VARCHAR, BLOB, TEXT 컬럼이 없을 때 사용.
- 모든 CHAR, NUMERIC, DECIMAL 컬럼은 컬럼 길이에 space-padded 이다. (** space-
padded를 무엇이라고 번역해야 할지 애매모호해서 **)
- 매우 빠름
- 캐쉬하기 쉽다
- 손상 후 복구가 쉽다. 왜냐면 고정된 위이에 레코드가 위치하기 때문이다.
- 많은 양의 레코드가 지워졌거나 운영 시스템에서 자유 공간을 늘리길 원치 않는다면 (isa
mchk를 이용) 재조직화할 필요없다.
- 보통 다이나믹 테이블보다 많은 디스크 공간을 필요로 한다. 


다이나믹 테이블
- 테이블이 VARCHAR, BLOB, TEXT 컬럼을 포함하고 있을 때 사용.
- 모든 문자열 컬럼은 다이나믹하다.(4보다 작은 길이를 가진 문자열 제외)
- 컬럼이 문자열 컬럼에서 비었거나 ('') 숫자형 컬럼에서 0(NULL 값을 가진 컬럼과 동일
한 것이 아니다) 을 나타내는 비트맵이 모든 레코드 앞에 선행된다. 문자열 컬럼에서 trailin
g space를 제거한 후 zero의 길이를 가지거나 숫자형 컬럼이 zero의 값을 가지면 비트 맵으
로 표시되고 디스크에 저장되지 않는다. 비지 않은 문자는 문자내용에 길이 바이트만큼 추
가되어 저장된다.
- 보통 고정 길이 테이블보다 디스크 공간 절약.
- 줄의 길이를 확장하는 정보를 가지고 줄을 업데이트하면 줄은 단편화될 것이다. 이런 경
우 더 좋은 성능을 위해 때때로 isamchk -r 을 실행해야 한다. 통계적으로(?) isamchk -ei 
tbl_name을 사용하자.
- 손상후 복구가 어렵다. 왜냐면 레코드가 많은 조각드로 단편화되고 링크(단편)가 없어지
기 때문이다.
- 다이나믹 사이즈 테이블의 예상되는 열 길이 :
3

1
2
3
4
5
+ (number of columns + 7/ 8
+ (number of char columns)
+ packed size of numeric columns
+ length of strings
+ (number of NULL columns + 7/ 8
cs


각 링크마다 6 바이트가 더 있다. 다이나믹 레코드는 업데이트로 레코드가 늘어날때마다 링
크된다. 각 새로운 링크는 최소 20바이트일 것이며, 그래서 다음의 확장은 아마도 동일한 링
크로 될 것이다. 그게 아니라면 다른 링크가 있을 것이다. isamchk -ed 로 얼마나 많은 링
크가 있는지 체크할 수 있다. 모든 링크는 isamchk -r 로 제거할 수 있다.(** ?? **)

There is a penalty of 6 bytes for each link. A dynamic record is linked whenever an up
date causes an enlargement of the record. Each new link will be at least 20 bytes, so th
e next enlargement will probably go in the same link. If not, there will be another link. 
You may check how many links there are with isamchk -ed. All links may be removed 
with isamchk -r. 


압축 테이블

- 읽기 전용 테이블은 pack_isam 유틸리티로 만들 수 있다. 확장 mysql 이메일 지원을 구
입한 모든 고객은 내부적인 용도로 pack_isam을 사용할 권리가 주어진다.
- 압축해제 코드는 모든 mysql 배포판에 있으므로 pack_isam이 없는 고객도 pack_isam으
로 압축된 테이블을 읽을 수 있다. (테이블이 같은 플랫폼에서 압축되어 있는한)
- 매우 적은 디스크 용량을 사용. 
- 각 레코드는 개별적으로 압축이 된다.( 매우 적은 액세스 overhead) 레코드의 헤더는 테
이블의 가장 큰 레코드에 따라 (1-3 바이트) 고정된다. 각 컬럼은 다르게 압축이 된다. 압축 
타입은 다음과 같다:

ㅇ 일반적으로 각 컬럼마다 다른 Huffman 테이블이다.
ㅇ Suffic 공간 압축
ㅇ Prefix 공간 압축
ㅇ 0 값을 가진 숫자는 1비트로 저장.
ㅇ integer 컬럼의 값이 작은 범위를 가졌다면, 컬럼은 최대한 작은 타입으로 저장
된다. 예를 들면 BIGINT 컬럼은 모든 값이 0부터 255라면 TINIINT 컬럼(1바이트)로 저장
된다.
ㅇ 컬럼이 몇가지 가능한 값으로만 구성되어 있다면, 컬럼 타입은 ENUM으로 변환
된다.
ㅇ 컬럼은 위 압축 방법을 조합하여 사용한다.
- 고정 길이나 다이나믹 길이의 테이블을 다룰 수 있다. 그러나 BLOB나 TEXT 컬럼은 다
룰 수 없다.
- isamchk로 압축을 해재할 수 있다.

mysql은 다른 인덱스 타입을 지원한다. 그러나 일반적인 타입은 NISAM이다. 이것은 B-tre
e 인덱스이며 모든 키의 갑을 합하여 (키 길이+4)*0.67로 인덱스 파일의 크기를 대강 계산
할 수 있다. (이것은 모든 키가 정렬된 순서로 입력된 가장 나쁜 경우이다)


String indexes are space compressed. If the first index part is a string, it will also be p
refix compressed. Space compression makes the index file smaller if the string column h
as a lot of trailing space or is a VARCHAR column that is not always used to the full 
length. Prefix compression helps if there are many strings with an identical prefix. 

문자열 인덱스는 공간이 압축된다. 첫번째 인덱스 부분이 문자열이라면, prefix가 압축된다. 
문자열 컬럼이 다량의 trailing space를 가졌거나 언제나 완전한 길이를 사용하지 않는 VA
RCHAR 컬럼일 때 space 압축은 인덱스 파일을 더 작게 만든다. prefix 압축은 많은 문자
열에 동일한 prefix가 있을 때 유용하다.
[출처] mysql의 최대 성능 향상 방법|작성자 Philip



기본적으로 중복되지 말아야 하는데.. 중복이 된 경우 그 행을 삭제하는 방법입니다.

DELETE FROM duplicate
WHERE id not in ( SELECT id from ( SELECT id from 
duplicate group by phone) as id )


전화번호가 중복 된 것이 있을 경우, 위와 같이 WHERE NOT IN을 사용해서 제거해 줄 수 있습니다.


출처:http://gyuha.tistory.com/309

반응형

'IT > Mysql' 카테고리의 다른 글

Mysql Procedure(프로시저) 개념과 예제  (0) 2018.01.17
반응형



Out Of Memory 오류로 추정했을시에 발생 시점


참고:http://www.nextree.co.kr/p3878/


개발이 완료되어 사용자 테스트 혹은 인수인계 단계에 많이 발생

(부하를 주는 작업 때문?)


Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space (실제 해당 로그에 남아있던 에러)


Class나 Method 객체를 PermGen space에 할당하지 못하는 경우 발생하며 애플리케이션에서 너무 많은 class를 로드할 때 발생한다. 


주로 잘못된 설계/구현에 의해 발생한다. -XX:PermSize, -XX:MaxPermSize Option을 이용하여 오류를 수정하기도 한다.


(-XX:PermSize, -XX:MaxPermSize Option 을 주어 하루정도 톰캣이 뻗지않은건 확인)



Perm Gen space에서 발생한 오류에 대해 대응하기 전에 Perm Generation 영역에 대해서 알아보면 


Permanent Generation은 young과 old를 구분하는 Generational Collector 방식인 HotSpot JVM 중 한 영역으로


객체의 생명 주가기 길다고 판단되는 객체들을 이 영역에 할당하여 GC대상에서 제외를 하기 위해서 만들어진 영역이다. 


주로 자바의 Class 객체들이나 문자열에 속한 String 객체들이 위치한다.


일반적으로 Class의 로딩은 시스템의 Class path에 의해서 로드된 Class 객체들과 에플리케이션 내 구현으로 다이나믹하게 로드되는 class들이 있는데 


주로 문제는 애플리케이션 내 로직으로 다이나믹 하게 생성되는 Class들에 의해서 발생된다. 


최근에 많이 사용되는 Spring, MyBatis등과 같은 프레임워크 등이 이와 같은 방식을 취하고 있다. 


때문에 위 프레임워크들을 사용할 경우 OOME(Out Of Memory Error)발생에 주의를 해야 한다.


- 기본적인 메모리 설정 방식

JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m 

-XX:MaxNewSize=512m -XX:PermSize=512m -XX:MaxPermSize=512m -XX:+DisableExplicitGC"


* 참고 : JVM 메모리 옵션


-Xms<size> : Java Heap의 최초 크기(Start Size)를 지정한다. Java Heap은 -Xms 옵션으로 지정한 크기로 시작하며 

최대 -Xmx옵션으로 지정한 크기만큼 커진다. 


Sun HotSpt JVM 계열에서는 최초 크기와 최대 크기를 동일하게 부여할 것을 권장한다. 크기의 동적인 변경에 의한 오버 헤들를 최소화하기 위해서이다.


-Xmx<size> : Java Heap의 최eo 크기(Maximum Size)를 지정한다. -Xms 옵션으로 지정한 크기로 시작하며 최대 -Xmx옵션으로 지정한 크기만큼 커진다. 

Sun HotSpt JVM 계열에서는 최초 크기와 최대 크기를 동일하게 부여할 것을 권장한다. 크기의 동적인 변경에 의한 오버 헤들를 최소화하기 위해서이다.


-XX:PermSize=<size> : Permanent Generation의 최초 크기를 지정한다. Permanent Generation의 최대 크기는 MaxPermSize옵션에 의해 지정된다. 

많은 수의 Class를 로딩하는 Application은 크기의 Permanent Generation을 필요로 하며, 

Permanent Generation의 크기가 작아서 Class를 로딩하지 못하면 Out of Memory Error가 발생한다.


-XX:MaxPermSize=<size> : Permanent Generation의 최대 크기를 지정한다. Permanent Generation의 시작 크기는 PermSize옵션에 의해 지정된다. 

많은 수의 Class를 로딩하는 Application은 PermSize와 MaxPermSize옵션을 이용해 Permanent Generation의 크기를 크게 해주는 것이 좋다. 

Permanent Generation의 크기가 작을 경우에는 Out of Memory Error가 발생한다.


-XX:NewSize<size> : 객체가 생성되어 저장되는 초기공간의 Size로 Eden+Survivor 영역


출처: http://javafactory.tistory.com/328 [FreeLife의 저장소]


MaxPermSize는 -Xmx 로 지정한 메모리 용량과 별도로 할당된다. 

즉, -Xmx가 256m 이고, -XX:MaxPermSize가 256m 이라면, 최대 512m이 할당될 수 있다는 것이다.


출처: http://linuxism.tistory.com/286 [linuxism]


Jconsole 도구를 이용한 메모리 설정법 

http://joont.tistory.com/42


메모리 옵션


앞에서도 설명하였듯이 JVM 튜닝의 대부분의 메모리 튜닝이고 그중에서도 JVM 메모리 튜닝은 매우 중요하다. 


결국 Full GC 시간을 줄이는 것이 관건인데, 큰 요구 사항만 없다면, 전체 Heap Size는 1G 정도가 적당하다. 


그리고 New대 Old의 비율은 서버 애플리케이션의 경우 1:2 비율이 가장 적절하다. 그리고 PermSize는 class가 로딩되는 공간인데, 


배포하고자 하는 애플리케이션이 아주 크지 않다면 128m 정도면 적당하다. 

(보통 256m를 넘지 않는다. 256m가 넘는다면 몬가 애플린케이션 배포나 패키징에 문제가 있다고 봐야 한다.)


그리고 heap size는 JVM에서 자동으로 늘리거나 줄일 수 가 있다. 


그래서 -Xms와 -Xmx로 최소,최대 heap size를 정할 수 있는데, Server 시스템의 경우 항상 최대 사용 메모리로 잡아 놓는 것이 좋다. 


메모리가 늘어난다는 것은 부하가 늘어난다는 것이고, 부하가 늘어날때 메모리를 늘리는 작업 자체가 새로운 부하가 될 수 있기 때문에, 같은 값을 사용하는 것이 좋다.


이렇게 JVM 메모리를 튜닝하면 다음과 같은 옵션이 된다.


-Xmx1024m –Xms1024m -XX:MaxNewSize=384m -XX:MaxPermSize=128m


이렇게 하면 전체 메모리 사용량은 heap 1024m (이중에서 new가 384m) 그리고 perm이 128m 가 되고, 


JVM 자체가 사용하는 메모리가 보통 300~500m 내외가 되서 java process가 사용하는 메모리 량은 대략 1024+128+300~500 = 대략 1.5G 정도가 된다.


출처: http://bcho.tistory.com/788 [조대협의 블로그]


PermGen 메모리를 설정하지 않았을경우 디폴트 값은 80메가 정도


현재 서버 컴퓨터의 MAX Heap Memory 는 7.4기가 ( Xms,Xmx를 4096 정도까지 사용가능 )


프로젝트 4개를 호스트만 변경해서 사용한다고 했을때


디폴트 메모리가 적게 잡혀있어서 문제가 일어났던것으로 파악되어서,


적정설정을 할수있다기보다는 컴튜터 사양에 맞는 최상의 옵션을 설정해두고 


부하가 늘어날때 메모리를 늘리는 작업 자체가 새로운 부하가 될 수 있기 때문에, 같은 값을 사용하는 것이 좋다는 내용을 참고하여


적정 옵션을 설정후에


OOME가 추후에 발생하는지 확인하는 방법이 제일 최선일것같다.


찾아본 허용된 옵션중 최상 옵션


JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms3072m -Xmx3072m -XX:NewSize=384m 

-XX:MaxNewSize=384m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"


Xms, Xmx를 동일하게 세팅하는 이유


- Xms로 init 메모리를 잡고, committed 도달할 때까지 Used용량이 점차 증가하는데, 

committed에 도달시 메모리 추가할당시 시스템 부하발생 (WAS가 몇 ms가량 멈출 가능성 있음)


- 메모리 용량은 init < used < committed < max 


- 보통 운영시스템에서 Xms와 Xmx를 동일하게 지정하는 이유는 init와 max사이에서 used 메모리가 committed까지 사용하게 되면, 

  신규 메모리 공간을 요구하는데 이 때 약 1초가량 jvm이 메모리 할당 중 멈춰버리는 경우가 있다. 

  그래서 Xms와 Xmx를 동일하게 주고 메모리를 확보한 상태에서 jvm을 기동시키곤 한다. 


출처 : http://javaslave.tistory.com/23




JVM 이란?

Java Virtual Machine 의 줄임말 이며 Java Byte Code를 OS에 맞게 해석 해주는 역할을 합니다. Java compiler는 .java 파일을 .class 라는 Java byte code로 변환 시켜 줍니다. Byte Code 는 기계어가 아니기 때문에OS에서 바로 실행되지 않습니다. 이때 JVM은 OS가 ByteCode를 이해할 수 있도록 해석 해줍니다. 하지만 JVM의 해석을 거치기 때문에 c언어 같은 네이티브 언어에비해 속도가 느렸지만 JIT(Just In Time)컴파일러를 구현해 이점을 극복했습니다. Byte Code는 JVM 위에서 OS상관없이 실행된다. 이런 점이 Java의 가장 큰 장점이라고 할수 있습니다. OS에 종속적이지 않고 Java 파일 하나만 만들면 어느 디바이스든 JVM 위에서 실행 할 수 있습니다. JVM은 크게 Class Loader, Runtime Data Areas, Excution Engine 3가지로 구성되어 있고 자세한 설명은 아래에 이이서 하겠습니다.

JVM 구조

Class Loader

RunTime 시점에 클래스를 로딩하게 해주며 클래스의 인스턴스를 생성하면 클래스 로더를 통해 메모리에 로드하게 됩니다.

Runtime Data Areas

JVM이 프로그램을 수행하기 위해 OS로 부터 별도로 할당 받은 메모리 공간을 말하며, Runtime Data Areas는 크게 5가지 영역으로 나눌 수 있습니다.

Execution Engine

Load된 Class의 ByteCode를 실행하는 Runtime Module이 바로 Execution Engine입니다. Class Loader를 통해 JVM 내의 Runtime Data Areas 에 배치된 바이트 코드는 Executin Engine에 의해 실행되며, 실행 엔진은 자바 바이트 코드를 명령어 단위로 읽어서 실행합니다.

최초 JVM 이 나왔을 당시에는 Interperter방식(한 줄씩 해석하고 실행)이였기 때문에 속도가 느리다는 단점이 있었지만 JIT complier 방식을 통해 이 점을 보완했습니다. JIT는 ByteCode를 어셈블러 같은 NativeCode로 바꿔서 실행이 빠르지만 역시 변환하는데 비용이 발생합니다. 이 같은 이유 때문에 JVM은 모든 코드를 JIT Compiler 방식으로 실행하지 않고 Interpreter 방식을 사용하다 일정한 기준이 넘어가면 JIT Compiler 방식으로 실행합니다.


출처:https://medium.com/@lazysoul/jvm-%EC%9D%B4%EB%9E%80-c142b01571f2

반응형
반응형

옛날에 자격증 딸때 받아놨던 자료이다 

혹시 학점관리때문에 따는사람들은 도움이 될거같아서 공유


TTL(time-to-live)

[티티엘]IP 패킷 내에 있는 값으로서, 그 패킷이 네트웍 내에 너무 오래 있어서 버려져야하는지의 여부를 라우터에게 알려준다. 일정한 시간이 지나면 그 패킷을 버리고, 재전송할 것인지를 결정하도록 그 사실을 발신인에게 알리기 릴 수 있게 하기 위한 해결책으로 TTL이 사용된다.

값이 0이 되었을 때, 라우터는 그것을 감지하여 그 패킷을 버리고 ICMP 메시지를 발신지 호스트로 보낸다.

 

SNMP(Simple Network Management Protocol) ; 간이 망 관리 프로토콜

[에스엔엠피]는 네트웍 관리 및 네트웍 장치와 그들의 동작을 감시, 통할하는 프로토콜이다. 이것은 반드시 TCP/IP 네트웍에만 한정되지는 않는다.

 

SMTP(Simple Mail Transfer Protocol) ; 단순 우편전송 규약

[에셈티피]는 전자우편을 보내고 받는데 사용되는 TCP/IP 프로토콜이다.

 

MIME (Multi-Purpose Internet Mail Extensions)

MIME[마임]은 아스키 데이터만을 처리할 수 있는 원래의 인터넷 전자우편 프로토콜, SMTP를 확장하여 오디오, 비디오, 이미지, 응용프로그램, 기타 여러가지 종류의 데이터 파일들을 주고받을 수 있도록 기능이 확장된 프로토콜이다. 아스키 형식으로 변환할 필요 없이 송신한다.

TFTP(Trivial File Transfer Protocol)

FTP보다 간단하지만 기능이 조금 덜한 네트웍 애플리케이션이다. 이것은 사용자 인증이 불필요하고, 디렉토리를 보여주지 않아도 되는 곳에 사용된다. TFTPTCP 대신에 UDP를 사용한다.

FTP 상에서 파일을 전송 받고자 할 때 사용하는 명령어 : get . Binary

 

PPTP (Point-to-Point Tunneling Protocol)

PPTP는 기업들이 인터넷상의 사설 "터널"을 통해 자신들의 기업용 사설 네트웍을 확장할 수 있도록 해주는 프로토콜이다. 실제로, 기업들은 하나의 거대한 근거리통신망으로서 광역통신망을 사용한다. 그러나, 기업들은 이제 광역통신망을 위해 더 이상 자신들만의 독립 회선을 빌릴 필요가 없으며, 공공 네트웍을 안전하게 이용할 수 있다.

이러한 종류의 접속을 가상사설망, VPN이라고 부른다. 인터넷을 경유하여 로컬 네트워크에 접근할 때, 보안을 강화하기 위해 사용하는 프로토콜이다.

 

ICMP(Internet Control Message Protocol)

는 호스트 서버와 인터넷 게이트웨이 사이에서 메시지를 제어하고 에러를 알려주는 프로토콜 프로토콜 아이디는 1이다.

0-Echo Request = 질의 메시지에 응답하는데 사용된다.

8-Echo Request = 네트워크 상의 두 개 이상의 장비의 기본 연결을 검사하기 위해 사용된다.

13-Timestamp Request = 네트워크를 통해 전송하는 과정에서 발생한 지연 시간을 측정하기 위해 사용됨

17-Address Mask Request = 장비의 서브넷 마스크를 요구하는데 사용된다.

이 프로토콜의 중요한 임무는 시작지 호스트의 라우팅 실패를 보고하는 것이다.

오류-보고의 형식을 가지고 있으며 TCP/IP 프로토콜 집합으로 가는 메시지를 제어하는 역할을 한다.

두 호스트간의 연결의 신뢰성을 테스트하기 위한 반향과 회답 메시지를 지원한다.

ICMPIP의 상실된 IP 데이터그램의 검출 및 재전송 요청, 적합한 순서대로 IP 데이터그램의 배치, 중복된 IP 데이터그램의 검출 및 폐기를 책임진다. 네트워크 계층이다.

 

IGMP (Internet Group Management Protocol) ; 인터넷 그룹 관리 프로토콜

IGMP는 인터넷 컴퓨터가 멀티캐스트 그룹을 인근의 라우터들에게 알리는 수단을 제공하는 인터넷 프로토콜이다.

IGMPOSI 참조 모델에서 네트웍 계층의 일부이다.

 

IGRP (Internet Gateway Routing Protocol)

IGRP는 시스코 시스템즈 고유의 IGP 프로토콜로서, 다른 게이트웨이들과 정보를 교환함으로써 게이트웨이들이 자신들의 라우팅 테이블을 만들 수 있게 해준다. 게이트웨이는 인접 게이트웨이들과 수정된 라우팅 정보를 교환함으로써 다른 네트웍들에 관한 정보를 얻는다.

거리백터 라우팅 프로토콜이다. 메트릭을 결정할 때 고려요소 중 하나는 링크의 대역폭이 있음. 네트워크 사이의 라우팅 최적하에 효율적이다. IGRP는 라우터를 위한 네트워크끼리의 IGP 프로토콜이다.

 

RIP (Routing Information Protocol)

RIP[알아이피]는 기업의 근거리통신망, 또는 그러한 랜들이 서로 연결된 그룹과 같은 독립적인 네트웍 내에서 라우팅 정보 관리를 위해 광범위하게 사용된 프로토콜이다. RIPIETF에 의해 여러 IGP 중의 하나로 분류되었다. 전체 라우팅 테이블을 가장 가까운 인근 호스트에 매 30초 마다 보낸다. 네트워크 거리를 결정하는 방법으로 홉의 총계를 사용한다.

RIP는 비효율적이라는 평가를 받아 이를 보완한 OSPF 가 나옴 동적 라우팅에서 라우팅 테이블을 담당한다.

MTU(Maximum Transmission Unit) ; 최대 전송 단위

[엠티유]TCP/IP 네트웍 등과 같이 패킷 또는 프레임 기반의 네트웍에서 전송될 수 있는 최대크기의 패킷 또는 프레임을 가리키며, 대개 옥텟을 단위로 사용한다. TCP는 어떠한 전송에서라도 각 패킷의 크기를 결정하는데 있어 MTU를 사용한다. MTU가 너무 크면 커다란 크기의 패킷을 처리할 수 없는 라우터를 만났을 때 재전송 해야하는 경우가 생길 수 있다. 이와는 반대로 MTU가 너무 작으면, 상대적으로 헤더 및 송수신 확인에 따르는 오버헤드가 커지게 된다.

 

Gratuitous ARP : 자신의 존재만을 알리는 프로토콜

 

ARP (Address Resolution Protocol) ; 주소결정 프로토콜

ARPIP 네트웍 상에서 IP 주소를 물리적 네트웍 주소로 대응시키기 위해 사용되는 프로토콜이다.

여기서 물리적 네트웍 주소라 함은 이더넷 또는 토큰링의 48 bits 네트웍 카드 주소를 의미한다. 두 호스트가 같은 물리적 네트워크 상에 있을때, 근원지 호스트가 목적지 호스트로 직접 데이터를 전달할 수 있도록 도와준다. 네트워크 계층의 프로토콜이다. IP에 의해 보조적으로 사용된다.

 

RARP (Reverse Address Resolution Protocol)

RARP는 근거리통신망 내에 물리적으로 존재하는 장치가 게이트웨이의 ARP 목록이나 캐시로부터 자신의 IP 주소를 알아내기 위한 확인 요청을 하는데 사용되는 프로토콜이다. 네트웍 관리자는 근거리통신망의 게이트웨이 라우터 내에 물리적인 장치가 그에 상응하는 IP주소를 지칭하도록 목록표를 작성한다. 새로운 장치가 설정되었을 때, RARP 클라이언트 프로그램은 라우터 상의 RARP 서버에게 그 장치를 위한 IP 주소를 보내주도록 요청한다. RARP 서버는 라우터 목록 내에 새로운 엔트리가 설정되었다고 가정하여, 그 장치에게 IP 주소를 답신해 주게 된다. RARP는 이더넷, FDDI, 토큰링 등의 근거리통신망에서 사용할 수 있는 프로토콜이다. 아직 자신의 인터넷 주소를 갖지 못한 호스트가 이를 얻도록 해준다. 네트워크 계층이다. 로컬 디스크가 없는 네트워크상에 연결된 시스템에 사용된다.

 

TCP/IP (Transmission Control Protocol/Internet Protocol)

인터넷의 기본적인 통신 프로토콜로서 상위계층인 TCP는 메시지나 파일들을 좀더 작은 패킷으로 나누어 인터넷을 통해 전송하는 일과, 수신된 패킷들을 원래의 메시지로 재조립하는 일을 담당한다. 하위계층, IP는 각 패킷의 주소 부분을 처리함으로써, 패킷들이 목적지에 정확하게 도달할 수 있게 한다. TCP는 전송계층이고 데이터의 에러 검출을 담당 , IP는 네트워크계층이고 경로 설정을 담당한다.

 

TCP : 연결지향 UDP : 전송계층,비연결지향 TCP/UDP 계층은 호스트 간의 데이터 교환을 함

 

TCP 헤더의 플래그 비트 : URG, ACK, PSH, RST, SYN, FIN, 등이 있다.

 

UDP (User Datagram Protocol)

UDP[유디피]IP를 사용하는 네트웍 내에서 컴퓨터들 간에 메시지들이 교환될 때 제한된 서비스만을 제공하는 통신 프로토콜이다. UDP 헤더의 크기는 8옥텟이다.

UDPTCP와는 달리, 메시지를 패킷(데이터그램)으로 나누고, 반대편에서 재조립하는 등의 서비스는 제공하지 않으며, 특히 도착하는 데이터 패킷들의 순서를 제공하지 않는다.

불특정 다수에게 간단한 메시지를 일방적으로 보낼 경우 사용한다.

프로토콜의 부하가 적어 분산처리에서 많이 사용된다.

 

Netstat : 시스템 인터페이스 정보를 출력하면서 송수신 패킷수 및 오류수, 충돌 횟수, 현재 출력큐에 대기중인 패킷 등에 관한 정보를 제공. TCP Connection의 상태를 파악하는데 사용되는 유틸리티. 인터페이스 정보제공.

 

NBTSTAT : 유틸리티 중에서 TCP/IP 통계를 통한 NetBIOS를 연결시킨다.

IP 주소를 가지고 컴퓨터의 현재 NetBIOS 상태를 알 수 있음.

 

ipconfig : 물리적 네트워크에의 인터페이스를 시험하고, 로컬 호스트의 nic의 올바른 동작여부를 검사한다.

 

traceroute : 경로를 추적하는 명령어

 

nslookup : 도메인을 IP로 변경해 주는 명령어

 

ping (Packet Internet Groper) : TCP/IP 프로토콜을 사용하는 응용 프로그램으로 다른 호스트에 IP 데이터그램이 도착할 수 있는지를 검사하는 것을 의미

 

IP address ; IP 주소

인터넷상에서 라우팅을 효율적으로 하기 위하여 물리적인 네트웍 주소와 일치하는 개념으로 부여된 32 비트의 주소가 IP 주소이다. IP 주소를 이용하면 네트웍상의 유일한 호스트를 식별하는 것뿐만 아니라, 호스트가 있는 네트웍를 식별할 수 있다. IP 주소는 클래스로 나뉘어 있으며 하나의 네트웍에서 모든 호스트는 동일한 prefix를 공유한다. IP 프로토콜은 여러 개의 독립적인 네트워크들 사이에서 데이터그램을 교환할 수 있도록 해주는 프로토콜 (데이터그램은 비연결 지향) IP주소는 32bit 이다.

네트워크ID와 호스트ID 비트가 모두 1이면 브로드캐스트로만 사용된다.

네트워크ID와 호스트ID 비트가 모두 0이면 네트워크 전용이다.

 

IP 클래스 : A Class = 1~126 , B Class = 126~191 , C Class = 191~223

 

Telnet ; 텔넷

텔넷은 자신이 사용권한을 가지고 있다는 전제하에 다른 사람의 호스트 컴퓨터를 원격지에서 액세스할 수 있도록 해주는 방법이다. 좀더 기술적으로 말한다면, 텔넷이란 원격지 컴퓨터를 액세스하기 위한 사용자 명령들과 TCP/IP 기반의 프로토콜을 말한다

 

Finger : 로그인하고 있는 사용자의 정보 확인.

 

DNS(domain name system)

[디에네스]는 인터넷 도메인 이름들의 위치를 알아내기 위한 IP 주소로 바꾸어주는 시스템이다 디에네스는 호스트 이름에 대한 분산 데이터베이스 이다.

 

DNS 리소스 레코드 : SOA(Start of Authority) = 도메인의 주 네임 서버와 몇 가지 관리 아이템을 나타냄. DNS서버를 처음 설치하면서 가장 먼저 만들어야 하는 데이터베이스 레코드 NS(Name Server) = 도메인의 네임 서버를 정의함.

PTR(Ppinter) = 호스트 이름 IP 주소와 연결하고 역방향 이름 조회를 실행함.

CNAME(Alias) = 호스트 이름의 별칭을 제공하여 하나 이상의 호스트 이름을 하나의 IP 주소에 연결 할 수 있음

MX(Mail Exchange) = 도메인의 메일 시스템을 정의함.

A(Host) = DNS 이름과 호스트의 IP 주소를 연결할 때 사용함

SRV(Service), HINFO(Host Information) 등이 있음.

 

DNS서버 종류 : primary server, cache server, master name server .

 

동적저장장치 지원볼륨 : 단순볼륨, 스팬볼륨, 스트라이프볼륨(RAID-0), RAID-5

스팬볼륨 = 작은 빈 공간들을 모아 하나의 큰 논리 드라이브를 구성하는 것을 말한다.

동적 디스크에서만 스팬 볼륨을 생성할 수 있다.

최대 32개의 동적 디스크 상에 확장할 수 있다.

적어도 두 개 이상의 동적 디스크가 필요하다.

미러볼륨(RAID-1) = 단순 볼륨으로써 두 개의 동일한 복사 영역으로 서로 다른 디스크를 사용하여야 함.

이 볼륨은 하나의 디스크에서 문제가 발생했을 때 복구 가능하므로 결합 허용을 지원함.

 

RAID (redundant array of independent [또는 inexpensive] disks)

RAID[레이드]는 중요한 데이터를 가지고 있는 서버에 주로 사용되며, 여러 대의 하드디스크가 있을 때 동일한 데이터를 다른 위치에 중복해서 저장하는 방법이다. 데이터를 여러 대의 디스크에 저장함에 따라 입출력 작업이 균형을 이루며 겹치게 되어 전체적인 성능이 개선된다. 여러 대의 디스크는 MTBF를 증가시키기 때문에 데이터를 중복해서 저장하면 고장에 대비하는 능력도 향상된다.

RAID 0 - 고용량과 데이터 분실로 인한 문제가 발생되지 않는 곳에 적합.

RAID 1 - 통상적으로 가장 많이 사용하는 RAID 레벨.

같은 데이터를 동시에 두 개의 물리적 드라이브에 쓰도록 하는 방식

RAID 5 - 가장 뛰어난 RAID 레벨.

 

터미널 서비스 설치순서 : 1.Windows 구성요소 마법사에서 터미널 서비스와 터미널 서비스 라이센싱을 선택

2.터미널 서비스 설치 모드에서 원격관리 모드를 선택한다.

3.라이센스 서버를 사용할 수 있는 범위를 지정한다.

4.라이센스 서버 데이터베이스의 위치를 지정한다.

 

Active Directory : 액티브 디렉토리는 윈도우2000, 즉 윈도우NT 5.0의 일부로서 마이크로소프트가 제공하는 새롭게 진보된 계층적 디렉토리 서비스이다. 소규모 대규모 활용가능,

설치 마법사 파일은 DCPROMO.EXE 이다. 사용자, 사용자 그룹, 네트워크 데이터 등을 하나로 통합 관리하는 새로운 인터페이스.

Active Directory 설치시 추가내용 : DNS 이름, NetBIOS 이름, 데이터베이스와 로그 파일위치, SYSVOL폴더 위치, 등 필요 NTFS 파일시스템 필요.

Active Directory 포리스트에 있는 5가지 작업 마스터 : 스키마 마스터, 도메인 명명 마스터, 관계식별(RID)마스터, 주 도메인 컨트롤러 에뮬레이터(PDCE), 구조 마스터로 구성,

 

IIS(Internet Information Server)

[아이아이 에스]는 마이크로소프트의 윈도우NT용 인터넷 서버군()의 이름으로서,

여기에는 Web, HTTP, FTP, Gopher 등이 모두 포함되어 있다.

IIS인증방법 : 기본인증, 윈도 도메인 서버의 다이제스트 인증, 통합 윈도 인증, 방법 등을 지원한다. Windows 2000 server 에서 사용하는 웹서버이다.

 

WINS(Windows Internet Naming Service)

마이크로소프트 윈도우NT 서버의 일부인 WINS, 각 구성 변경에 수반되는 사용자 또는 관리자가 없는 IP 주소들과, 컴퓨터 이름 및 위치들과의 결합을 관리한다. WINS는 컴퓨터 이름과 IP 주소를 서로 사상(寫像)시킬 수 있는 데이터를 테이블 내에 자동으로 만든다. WINS를 사용하면, 새로운 서브넷 정보가 WINS 테이블 내에서 자동으로 갱신된다.

NetBIOS 이름을 IP 주소로 사상하기 위해 사용된다.

백업의 종류와 설명 : 1.보통백업 = 선택된 모든 파일을 백업하고 백업되었다는 표시를 함

2.매일백업 = 오늘 변경된 파일만을 백업하며 백업된 것을 표시하지 않을때 사용

3.차등(differential)백업 = 증분백업과 같은 백업 작업을 하지만 복사 백업처럼 백업된 내용을 파일에 표시하지 않음

4.복사백업 = 보통 백업과는 다르게 백업되었다는 표시는 하지 않음

5.증분(incremental)백업 = 변경된 파일이나 새로운 파일만을 백업 표시함.

 

MMC(Microsoft Management Console)

MMC2000에 추가된 관리툴로서 관리도구에 구성되어 있지 않은 2000의 기능들의 사용과 관리자가 원하는 관리도구의 모음을 따로 구성할 수 있게 되어 있습니다. 이는 하나의 통일된 인터페이스를 제공하여 관리의 효율성을 극대화 시킵니다. 원격관리 기능을 제공

 

복구 콘솔 기능 : 모든 시작 부트 옵션이 실패했을 경우 Windows2000 서버를 시작할 수 있는 최소한의 버전이며 관리자 계정으로 로그온 하여 시스템 복구 작업을 수행할 수 있는 명령 세트를 제공하는 복원방법.

 

flooding ; 플러딩

네트웍 분야에서 플러딩이란, 어떤 노드에서 온 하나의 패킷을 라우터에 접속되어 있는 다른 모든 노드로 전달하는 것을 말한다.

 

(TRANS PORT) 전송계층 -4계층

이 계층은 패킷이 오류나 중복없이 올바르게 전달되도록 하며 큰 데이터는 잘라서 작은 패킷으로 작은 자료는 모아서 일정 크기의 패킷으로 묶는 역활을 합니다. 어디서 많이 보던 역활이죠? 예 바로 TCP가 여기에 속합니다. 호스트간 흐름제어와 에러제어 ,에러복구 기능.

서로 다른 네트워크의 차이를 극복한다.

 

IMT-2000(International Mobile Telecommunications - 2000)

ITU-T 스터디그룹 11에서 제안한 표준 기술이 채택된 차세대 이동통신 단말기로서,

위성을 이용한 통신서비스이다. IMT-2000의 특징은 세계 어느 지역에서나 음성전화, 텔렉스, 무선호출, 전자우편 등의 서비스를 제공받을 수 있다는 점이다. 현재 음성서비스 위주로 된 셀룰러폰과 PCS 등의 이동통신서비스는 점차 고속의 데이터, 패킷, 영상 등 멀티미디어 개인통신을 지원하는 IMT-2000 서비스로 발전하는 추세이다.

IMT-2000이라는 이름에서, 2000IMT에 할당된 주파수 대역이 2 GHz(, 2000 MHz)라는 것을 의미하는데, 1992년도에 세계 무선관리회의에서 붙여진 이름이다.

 

가상회선은 호출 요청으로 가상회선을 요구하고, 가상회선이 설립되면 메시지를 전송하고 전송이 완료되면,설정된 경로를 해제한다.

 

CSMA/CD (Carrier Sense Multiple Access/Collision Detect)

CSMA/CD[씨에스 엠에이 씨디]는 이더넷의 전송 프로토콜로서 IEEE 802.3 표준에 규격화되어 있다. 이더넷에 접속되어 있는 장치들은 어느 때라도 데이터를 전송할 수 있는데, 전송하기 전에 회선이 사용 중인지 감시하고 있다가 회선이 비어 있을 때 데이터를 전송한다. 만약 데이터를 전송하는 시점에 다른 장치가 동시에 전송을 개시하면 충돌이 발생하게 되며, 충돌한 데이터들은 버려지고 데이터를 전송한 장치들에게 재전송을 요구하게 된다. 각 장치들은 일정시간을 대기한 후 성공할 때까지 어느 횟수만큼 데이터를 재전송한다.

 

IEEE 표준안 : 근거리 통신망(LAN)의 국제 표준 모델을 제공하고 있는 표준 규격이다.

IEEE 802.3 : CSMA/CD

IEEE 802.4 : Token Bus

IEEE 802.5 : Token Ring

IEEE 802.6 : Metropolitan Area Network

 

PDU (protocol data unit) ; 프로토콜 데이터 단위

PDU는 특정 계층의 프로토콜 안에서 두 개의 실체간에 교환되는 세분화된 데이터 블록의 단위를 기술적인 이름으로 구분해 부르는 것을 말한다. 그러나, 많은 수의 사람들이 PDU나 프레임 등으로 엄격하게 구분해 사용하지 않고, 네트웍을 통해 이동하는 모든 데이터 단위를 그저 "패킷"이라고 부르는 경우가 많다.

 

에러제어 : 전송을 보낸 개체가 보낸 PDU에 대한 역널리지먼트(응답)를 특정 시간 동안 받지 못하면 재전송을 요구하는데 이 기능을 에러제어라 함

 

POLLING : 폴링은 주 스테이션이 부 스테이션에 전송할 데이터가 있는지 묻고, 부 스테이션에서 주 스테이션으로 데이터를 전송하는 중앙집중 매체접근 제어 방식

 

Apple Talk

애플사에서 발표한 Apple Talk는 여러 대의 매킨토시 컴퓨터와 레이저라이터(LaserWriter) 프린터, 기타 다른 컴퓨터 장비를 연결할 수 있도록 해 주는 근거리 통신망

 

IPX (Internetwork Packet Exchange)

IPX[아이 피 엑스]는 네트웨어 클라이언트와 서버를 사용하는 네트웍을 상호 연결하는 노벨의 네트워킹 프로토콜이다. IPX는 데이터그램 또는 패킷 프로토콜이다. IPX는 통신프로토콜의 네트웍 계층에서 동작하며, 패킷 교환 중에 커넥션이 계속 유지될 필요가 없는 커넥션리스 프로토콜이다.

패킷 수신통보는 노벨의 또다른 프로토콜인 SPX에 의해 관리된다. 관련된 노벨 네트웨어의

다른 프로토콜로는 RIP, SAP (Service Advertising Protocol) NLSP (NetWare Link Services Protocol) 등이 있다. 서로 다른 2개의 통신망 사이에서 데이터 패킷을 교환하기 위해 사용되는 통신 규약

 

VLAN (virtual LAN) ; 가상 랜

VLAN은 물리 세그먼트에서 다수의 논리적 네트워크 세그먼트를 운용할 수 있는 방법을 제공

 

packet-switched ; 패킷교환 방식

패킷교환 방식은, 패킷이라고 불리는 비교적 적은 데이터 단위가 각 패킷에 담긴 목적지 주소를 기반으로 하여 네트웍을 통해 발송되는 네트웍의 한 형태이다. 통신 메시지를 패킷으로 나눔으로써 네트웍 내의 동일한 데이터 경로를 여러 명의 사용자들이 공유할 수 있게 된다. 송신자와 수신자간의 이러한 형태의 통신을 비연결형이라고 부른다. 인터넷상의 대부분의 트래픽은 패킷교환 방식을 사용하며, 인터넷은 기본적으로 비연결형 네트웍이다. 단점은 축적교환방식 이다.

 

gateway ; 게이트웨이

게이트웨이는 다른 네트웍으로 들어가는 입구 역할을 하는 네트웍 포인트이다. 라우팅의 관점에서 보면, 인터넷은 많은 게이트웨이 노드들과 호스트 노드들로 구성된 네트웍이라 할 수 있는데, 네트웍 사용자들의 컴퓨터들과 웹페이지와 같은 콘텐츠를 제공하는 컴퓨터들이 바로 호스트 노드들이며, 일반 회사의 네트웍내에서 트래픽을 통제하는 컴퓨터들이나, 인터넷 서비스제공자들의 컴퓨터가 바로 게이트웨이 노드들이다.

한 회사의 네트웍에서는 게이트웨이 노드 역할을 하는 컴퓨터가 프럭시 서버나 방화벽 서버의 역할을 함께 수행하는 경우도 종종 있다. 게이트웨이는 라우터나 스위치 등의 사용을 필요로 한다. 서로 다른 LAN을 연결하는 장비. LANWAN에서 함께쓰이는 인터네트워킹 장비이다. 게이트웨이는 세션, 프레젠테이션, 응용계층 간의 연결에 사용됨.

게이트웨이는 이종의 프로토콜을 연결하기 위해 사용된다.

 

router ; 라우터

라우터는 동일한 전송 프로토콜을 사용하는 분리된 네트웍을 연결하는 장치로 네트웍 계층간을 서로 연결한다. 라우터는 브리지가 가지는 기능에 추가하여 경로 배정표에 따라 다른 네트웍 또는 자신의 네트웍 내의 노드를 결정한다. 그리고 여러 경로 중 가장 효율적인 경로를 선택하여 패킷을 보낸다.

라우터는 흐름제어를 하며, 인터네트웍 내부에서 여러 서브네트웍을 구성하고, 다양한 네트웍 관리 기능을 수행한다. 브리지와 라우터의 차이점을 간단히 살펴보면, 라우터는 네트웍 계층까지의 기능을 담당하고 있으면서 경로 설정을 해주는 반면, 브리지는 데이터링크 계층까지의 기능만으로 목적지 주소에 따른 선별 및 간단한 경로 결정을 한다. 이더넷 브로드캐스팅 트래픽을 완벽하게 차단한다.

Console 포트 : 라우터 인터페이스 포트 중 노트북의 COM 포트와 연결하여 라우터를 세팅하여 사용할 수 있음.

 

라우팅을 지원하는 프로토콜 : RIP, OSPF, BGP, TCP/IP, IPX/SPX

 

서브넷 : 단일 네트워크 ID가 할당된 네트워크를 여러개의 세그먼트로 분할하는 것,

IP주소 중 호스트 주소 부분이 Subnet number Host number로 분리된다.

몇개의 비트가 네트워크를 식별하는데 사용되고, 몇 개의 호스트를 식별하는데 사용되는지를 나타내기 위해 지정하는 것, NET-ID HOST-ID 를 사용.

Kerveros V5 인증 프로토콜은 윈도 2000 서버에서 지원되며 IETF RFC1510에서 정의되었음. 현재 모든 윈도2000 시스템을 위한 고유의 인증 방법, 윈도 2000 실행 및 클라이언트 소프트웨어가 설치된 컴퓨터의 기본적인 트러스트 프로토콜이다.

 

인터넷을 이용하여 인터넷 상의 특정 프린터 서버에 접근하기 위해서는 'http://URL' 이나 'IP 주소 /Printers' 라고 웹 주소를 입력한다. >> http://servername/printers

 

시스템 상태 데이터 중에서 액티브 디렉토리 서비스 데이터베이스, 인증서 서비스 데이터베이스, COM+ 클래스 등록 데이터베이스는 복원시 '대체 위치' 를 지정하여 복원할 때 복원되지 않는다.

 

IP 보안 정책 설정 옵션 : 1.클라이언트(응답만) = 일반적으로(비보안으로)통신합니다. 보안이 필요한 서버와는 기본 응답 정책을 사용하여 협상한다. 요청된 프로토콜 및 포트 소통량을 가진 서버만 보안된다.

2.서버(보안필요) = 모든 IP 소통량에 대해 항상 Kerberos 트러스트를 사용한 보안이 필요

하다. 요청에 응답하지 않는 클라이언트와의 비보안 통신을 허용한다.

3.보안서버(보안필요) = 모든 IP 소통량에 대해 항상 Kerberos 트러스트를 사용한 보안이

필요하다. 신뢰되지 않은 클라이언트와의 비보안 통신을 금지한다.

 

IPP(Internet Printing Protocol) : 인터넷을 통한 인쇄 방법

인터넷에서 인쇄를 하기 위해서는 프린터 서버상에 IIS 서버가 설치되어 실행되고 있어야 함. URL이나 IP주소로 접근하며 프린터 관리는 웹 브라우저만 있으면 됨.

 

chown : 소유자(owner)를 바꾸는 명령, root만 사용 가능한 리눅스 명령어.

 

바이트 스터핑(Byte Stuffing) : 문자열의 프레임 전송을 비정상적으로 중단하는 문제점(끝을 나타내는 문자가 데이터 중간에 오기 때문에 일어나는)을 해결하기 위하여 전송제어 문자 DLE를 추가하여 사용하는 방법

 

1-Persistent : 회선의 상태를 조사하여 사용 중이 아니면 데이터 프레임을 전송하고, 사용 중이면 전송이 끝날때까지 기다린 후 프레임을 송신한다. 이더넷과 802.3에서 충돌과 채널경쟁을 관리하기 위해 사용하는 기법.

 

셀렉션(selection) : 주 스테이션이 부 스테이션에게 미리 보낼 데이터를 준비하고 부 스테이션에게 데이터가 전송될 것임을 알려줌. 멀티 포인트 방식에서 중앙 컴퓨터가 주변의 터미널로 데이터를 전송하고자 하는 경우 수신측 터미널의 상태를 확인하는 절차.

 

회선 교환방식은 회선 설정, 데이터 전송, 회선 해제의 3단계를 거침.

 

ISDN (Integrated Services Digital Network) ; 종합정보통신망

ISDN[아이에스 디엔]은 다른 매체는 물론, 평범한 구리전화선 위에서도 디지털 전송을 할 수 있게 하기 위한 일련의 CCITT/ITU 표준들이다. 모뎀 대신에 ISDN 어댑터를 설치한 가정이나 회사의 사용자들은 최고 128 Kbps 까지의 빠른 속도로 제공되는 웹 페이지를 볼 수 있다. ISDN은 전송 양단에 어댑터가 필요하므로, 서비스제공자 역시 ISDN 어댑터가 필요하다. ISDN은 일반적으로 미국이나 유럽의 대부분 도시지역의 전화회사가 서비스를 공급하며, 우리나라에서도 한국통신에서 1993년부터 ISDN 서비스를 시작하였다.

아날로그 데이터와 디지털 데이터를 하나의 회선을 통하여 전송할 수 있음.

 

BISDN (Broadband Integrated Services Digital Network) ; 광대역 종합정보통신망

BISDN[비 아이에스디엔]은 광섬유나 무선매체 등의 광대역 네트웍에서 디지털 전송서비스를 통합하기 위한 개념, 일련의 서비스 및 표준의 개발 등을 모두 포괄하는 용어이다. BISDN은 고속 데이터를 위한 프레임 릴레이 서비스와, FDDI, 그리고 SONET 등을 모두 포함하게 될 것이다. BISDN2 Mbps의 속도에서부터 그 이상을 빠른 속도를 지원하게 될 것이지만, 구체적인 속도는 아직 결정되지 않았다.

BISDN은 협대역 가입자회선 상의 구리 전화회선을 이용해 디지털 데이터 전송을 제공하는 ISDN의 광대역 판이다.

 

비대칭 전이중 방식은 방송 분배 서비스를 하지 않음.

 

NAT(Network Address Translation); 네트웍 주소 변환

공개 IP와 사설 IP 사이의 주소를 변환해주는 메커니즘을 말하며, 사설IP 주소를 공개 IP 주소로 변환해줌으로써 인터넷에 접속할 수 있는 수단을 제공한다. 서버를 제외한 클라이언트가 외부에서의 접속이 필요 없을경우 사용.

 

STDM (statistical time division multiplexing) ; 통계적 시분할 다중화

STDM은 비록 전송할 내용이 없어도 시분할이 여전히 채널에 할당되는 표준 시분할 다중화의 일부 비효율성을 극복하기 위해 개발된 시스템이다.

STDM은 어떤 자유 시간대의 여유를 차지하기 위해 채널들이 경쟁하도록 하는 가변 시간대길이를 사용한다.

STDM은 트래픽이 절정에 이르는 기간 중, 데이터를 임시로 저장하는 버퍼 메모리를 채용한다. 이러한 방식은 STDM이 비활성 채널로 인해 고속 회선 시간이 낭비되지 않도록 한다. STDM은 채널 식별자 등과 같은 신분 정보의 전송을 필요로 한다. 이 오버헤드를 줄이기 위해, 각 채널을 위한 다수의 문자들이 전송을 위해 함께 집단으로 묶여진다.

데이터가 존재하는 채널에 대해서만 타임 슬롯을 동적으로 할당하여 데이터를 전송함

 

bridge ; 브리지

통신 네트웍에서, 브리지는 하나의 랜을 이더넷이나 토큰링과 같이 서로 같은 프로토콜을 쓰고 있는 다른 랜과 연결시켜주는 제품, 브리지는 물리 계층 및 데이터링크 계층의 기능이 있다. 상위 계층 프로토콜과 무관하다. 네트워크 관리가 용이하다. 환경설정이 필요없다.

 

repeater ; 리피터

통신 네트웍에서, 리피터는 전자기 또는 광학 전송매체 상에서 신호를 수신하고, 증폭하며, 매체의 다음 구간으로 재전송 시키는 장치이다. 리피터들은 전자기장 확산이나 케이블 손실로 인한 신호감쇠를 극복하므로, 여러 대의 리피터들을 써서 신호를 먼 거리까지 연장하는 것이 가능하다. 리피터들은 근거리통신망 내에서 세그먼트들을 서로 연결하는데 사용되며, 또한 유무선 광역통신망 전송을 증폭하고 연장하는 데에도 사용된다.

리피터는 물리 계층 수준의 기능이 있다. 전송 매체간에 리피터를 이용하여 신호의 약화 현상을 막을 수 있다.

 

hub ; 허브

데이터 통신에서 말하는 허브는, 데이터가 하나 또는 그 이상의 방향으로부터 한곳으로 모이는 장소로서, 들어온 데이터들은 다시 하나 또는 그 이상의 방향으로 전달된다. 허브는 보통 어떤 종류의 스위치를 포함한다 (스위치라고 불리는 장비는 보통 허브라고도 불린다). 허브는 데이터가 모여드는 곳이고 스위치는 모여든 데이터를 어떻게 그리고 어디로 보낼 것인지를 결정하는 것이, 두 장비의 차이점이다. 스위칭 측면에서 고려한다면, 허브는 또한 라우터를 포함할 수 있다. 네트워크 관리가 용이하다. 네트워크 확장이 용이하다. 네트워크 에러검출이 용이하다. 허브에 연결된 사용자가 많을수록 전송속도는 느려짐. 속도를 향상시키기 위해서는 리피터가 필요하다. LAN을 계층적으로 구성할 때 일반적으로 사용되는 장비로서 현재 저렴한 가격으로 가장 많이 사용된다.

 

switching hub ; 스위칭 허브

스위칭 허브는 "포트 스위칭 허브"를 줄여서 부르는 말로서, 패킷주소에 기반을 두고 패킷을 적절한 포트로 전달하는 특수한 형태의 허브이다. 전통적인 허브는 그저 모든 패킷을 모든 포트로 중계하는데 지나지 않았다. 스위칭 허브는 각 패킷을 필요한 포트에만 전달하기 때문에 더 나은 성과를 제공한다. 대부분의 스위칭 허브들은 부하조절 기능을 제공하므로, 트래픽 양상에 따라 서로 다른 랜 세그먼트에 포트들이 동적으로 재할당될 수 있다.

스위칭 허브를 사용하면 LAN 속도 및 전송 속도가 저하되지 않는다. LAN이 보유한 대역폭을 PC 대수 만큼 나누어서 제공하는 것은 일반 허브 장비이다.

 

4계층 스위치 : 1.4계층의 경우 TCPUCP 헤더에는 OSI의 최상위 계층인 응용 계층의 프로토콜인 HTTP, SMTP, FTP 등을 정확히 구분하는 포트 번호가 모든 패킷에 포함된다.

2.엔드 시스템은 이러한 정보를 통해 패킷 내부에 포함된 데이터를 인식한다.

3.포트 번호는 수신 측의 컴퓨터 시스템에서 IP 패킷의 유형을 결정하고 이것을 상위 계층으로 전달한다. 포트 번호와 디바이스의 IP 어드레스를 소켓이라고 한다.

 

DLC (data link control) ; 데이터 링크 제어

DLC는 네트웍 통신을 위해 OSI 내에 정의된 기능인 데이터 링크 계층에 의해 제공되는 서비스이다.

데이터 링크 계층의 기본적인 기능들에는 프레임 정의, 프레임 상의 에러 감지 및 교정, 그리고 흐름제어 수행 등이 포함된다. LLCMAC로 나누어져 있는 계층이다.

 

LLC layer (logical link control layer) ; 논리적 연결 제어 계층

OSI 통신 모델에서 LLC 계층은 데이터링크 계층이 가지고 있는 두 개의 부계층 중 하나로서 물리적 매체 상에서 흐름 제어와 에러 제어 등의 트래픽 관리에 관여하고 있다. LLC 계층은 SDLC, NetBIOS, 또는 NetWare 등과 같은 회선 프로토콜을 식별하며, 프레임에 일련번호를 매겨서 도착 확인을 추적할 수도 있다.

 

Archie ; 아키

Archie는 초창기에 활발하게 사용되던 인터넷 서비스로서, 자신이 필요로 하는 컴퓨터 파일이나 문서가, 어느 anonymous FTP 서버에서 제공되는지를 찾아주는 프로그램이다.

 

POP3 (Post Office Protocol 3)

POP3[팝 쓰리]는 전자우편을 수신하기 위한 표준 프로토콜로서 가장 최신 버전이다. POP3는 인터넷 서버가 사용자를 위해 전자우편을 수신하고 그 내용을 보관하기 위해 사용되는 클라이언트/서버 프로토콜이다.

 

Disk Druid : GUI 방식의 파티션 설정 유틸리티

NetBIOS (Network Basic Input/Output System)

NetBIOS[넷 바이오스]는 별개의 컴퓨터 상에 있는 애플리케이션들이 근거리통신망 내에서 서로 통신 할 수 있게 해주는 프로그램이다.

NetBIOS는 세션과 데이터그램 등 두 가지 통신모드를 제공한다. 세션모드는 두 개의 컴퓨터들이 대화를 위해 연결을 맺을 수 있도록 해주며, 커다란 메시지들의 처리와, 에러 감지 및 복구를 제공한다. 데이터그램 모드는 비연결형(connectionless)으로서, 메시지의 크기가 작아야하며, 애플리케이션은 에러 감지와 복구에 관해 자체적으로 처리해야 한다. 데이터그램 모드는 또한 근거리통신망 상의 모든 컴퓨터들에게 메시지를 뿌리는 기능을 지원한다.

 

NetBEUI : WAN이 아닌 LAN에서의 각 PC들이 상호간 통신을 할 수 있게 하는 프로토콜. 하지만 NetBEUI는 단독으로 사용하지는 못하고 IPX와 같은 다른 프로토콜과 함께 사용, 전송계층이고 UDP에 해당된다.

 

DHCPDynamic Host Configuration Protocol 의 약자로서 IP 주소를 자동으로 할당 할수 있게 하는 프로토콜. 따라서 클라이언트는 DHCP 서버에게 IP 주소를 요구하고, 서버는 각 클라이언트(PC)에게 자신이 관리하고 있는 IP를 분배해 주기 때문에 클라이언트 쪽에서 DNSNetBIOS 이름을 등록하거나, 확인할 수 없는 문제가 발생 할 수 있음.

Windows NT에서 정해진 범위 내의 IP Address를 자동으로 할당해 주는 서버이다.

DHCP서버 주소 범위 설정 옵션 : 서브넷 마스크, IP 임대 기간, 라우터 및 기본 게이트웨이 주소, IP범위

DHCP 네트워크 : DHCP 클라이언트, DHCP 서버, BOOTP/DHCP 릴레이 에이전트 로 구성.

Scope의 속성으로 DHCP 서버를 사용하기 위해서는 IP 주소의 범위와 특정 IP 주소의 서브넷을 결정하는 고유한 서브넷 마스크 그리고 범위를 만들때 지정되는 범위 이름을 할당해 주어야 함

 

LMHOSTS (LAN Manager Hosts)

LMHOSTSIP 주소를 NetBIOS 컴퓨터 이름으로 사상시키기 위해 윈도우가 사용하는 파일이다. 자신이 주기적으로 액세스하는 컴퓨터들의 이름과 IP 주소 목록을 가지고 있다.

WINS 서버와 동일한 역할을 수행한다.

 

HOSTS 파일은 Remote Host NameIP 주소의 매핑을 제공한다.

 

spool (simultaneous peripheral operations online) ; 스풀

컴퓨터의 문서나 작업목록을 스풀한다는 것은. 그것을 읽어서 하드디스크나 대용량 저장매체에 저장함으로써 좀더 편리한 시간 (예를 들면, 프린터의 경우 현재의 문서를 모두 출력하고 난 다음)에 프린트되거나 처리될 수 있도록 하는것이다.만약 프린터가 이미 다른 파일을 출력하고 있다면, 출력요청한 파일은 하드디스크 상에 스풀처리 된다.

 

AD HOC 방식은 각 단말끼리 연결이 되는 방식을 의미하며 멀리 떨어져 있는 단말끼리는 중간에 있는 단말들이 중계기 역할을 해 주어서 통신이 이루어 질 수 있도록 함.

무선 랜카드를 가진 컴퓨터 간의 네트워크를 구성하여 작동하는 방식.

 

token ring network ; 토큰링 네트웍

토큰링 네트웍은 근거리통신망의 한 형태이다. 토큰링 네트웍에서, 모든 워크스테이션은 하나의 링 또는 스타 형상으로 연결되어 있고, 메시지를 동시에 보내고자 하는 두 워크스테이션간의 충돌을 방지하기 위하여 토큰을 돌리는 형식이 사용된다.

프레임 신호의 송수신, 신호의 재생 중계, 토큰 신호의 전송, 우선 레벨의 부여 및 네트워크의 감시, 등의 기능.

 

ADSL (Asymmetric Digital Subscriber Line) ; 비대칭 디지털 가입자 회선

ADSL[에이디에스엘]은 가정과 회사에 설치되어 있는 전화회선을 통해 높은 대역폭으로 디지털 정보를 전송하기 위한 기술이다. ADSL은 대부분의 채널을 사용자측으로 내려 보내는 하향쪽으로 전송하는데 사용하고, 사용자로부터 받는 정보에는 아주 적게 할당하는 비대칭형 구조이며, 같은 회선에 디지털 정보 뿐 아니라 아날로그(음성) 정보도 동시에 수용할 수 있다. ADSL은 대개 512 Kbps에서 6 Mbps정도의 하향 데이터 전송속도를 제공하는데, 유니버설 ADSL 또는 G.Lite로 알려져 있는 ADSL의 형태가 최초의 ITU 표준으로 승인되었다. 전화선이나 전화기를 그대로 사용하면서도 고속데이터 통신이 가능할 뿐만 아니라 한 전화선으로 일반 전화통신과 데이터 통신을 모두 처리할 수 있다.

 

codec (coder/decoder, or compression/decompression) ; 코덱

통신공학에서 codec (coder/decoder) [코덱]이라는 용어는 데이터 변환을 수행하는 집적회로나 칩과 관련하여 사용된다. Codec의 형태는 아날로그-디지털 변환이나 디지털-아날로그 변환기능이 하나의 칩 내에 결합되어 있다

 

T-carrier system ; T급 회선

*전송속도 : T1 = 1.544Mbps E1 = 2.048Mbps T2 = 16Mbps T3 = 45Mbps

 

ACK (acknowledge) ; 응답문자

한 컴퓨터가 일련의 데이터를 네트웍을 통해 다른 컴퓨터로 보낼 때, 만약 그 데이터 전송이 성공적이었다면 수신측 컴퓨터가 ACK 코드 값을 송신측에 되돌려준다. 그러나, 만약 그 전송에서 에러가 발생하였다면 이때에는 negative ACK를 의미하는 코드, NAK 코드 값이 되돌려진다. 일반적으로, 송신측 컴퓨터가 일정시간동안 ACK 코드 값을 받지 못했거나, 또는 NAK 코드 값을 받은 경우에는 원래의 데이터가 재송신된다.

 

BOOTP (Bootstrap Protocol) ; 초기 적재 통신 규약

BOOTP는 네트웍 사용자가 자동으로 구성되고(IP 주소를 받게), 사용자의 간여 없이도 부트되는 운영체계를 가지고 있게 해주는 프로토콜이다. X 터미널 등과 같이 하드디스크를 갖지 않은 장치의 설정 정보를 자동적으로 할당, 관리하기 위해서 개발되었다. 네트웍 관리자에 의해 관리되는 BOOTP 서버는, 일정 시간동안 IP 주소를 자동으로 할당한다. BOOTP는 좀더 진보된 네트웍 관리 프로토콜인 DHCP의 기반이 된다.

 

CMIP (Common Management Information Protocol) ; 공통 관리 정보 프로토콜

CMIP[씨밉프]OSI 통신 모델 상에 근거한 네트웍 관리 프로토콜이다. 이와 관련된

CMIS (Common Management Information Services)는 네트웍 객체나 장치들에 대한 액세스 정보와, 그들을 제어하고, 또 상태 보고서를 수신하기 위한 서비스를 정의한다.

 

loopback ; 루프백

루프백은 전화시스템에서 네트웍 목적지로 보내어지는 시험 신호로서, 그 신호는 수신된 신호처럼 원래 신호를 보낸 곳으로 되돌아온다. 돌아온 신호는 문제를 진단하는데 도움을 줄 수 있다. 각 전화 시스템의 장치들에 루프백 신호를 한 번에 하나씩 잇달아 보내는 것은, 문제를 분리시키기 위한 기법이다. 자기 자신을 의미(127.0.0.1Software Loopback 주소)

 

Linux : 동시에 하나 이상의 프로그램을 수행할 수 있으며, 멀티태스킹을 지원한다.

foreground 작업이란 화면에 보여 주면서 실행되는 상태를 말한다.

background 시스템 내의 다중 처리가 가능하도록 하는 방법

Linux 명령어 ?

mv = 파일 혹은 디렉토리를 만들거나 이름을 변경

cp = 파일을 복사

find = 특정한 파일을 찾고자 할 때 사용

pwd = 현재 디렉토리의 위치를 보여줌

cat = 화면에 파일의 내용을 한 번에 전부 다 보여주는 명령

 

계정 관리 권한만 주고자 할 경우는 Account Operators 그룹 권한에 추가해 주면 된다.

 

바인딩 : Windows 2000에서 네트워크 설정을 할 경우 하나의 네트워크 어댑터에 시스템에 설치된 프로토콜을 사용하거나 사용하지 않게 하는 기능을 포함하고 있음.

 

LILO : 리눅스 운영체제의 중심이 되는 커널을 주기억 장소로 상주시키는데 사용되는 부트 로더

MBR (Master Boot Record) : 운영체계가 어디에, 어떻게 위치해 있는지를 식별하여 컴퓨터의 주기억 장치에 적재될 수 있도록 하기 위한 정보를 의미하며 디스크의 첫 번째 섹터에 존재

fdisk /mbr : 부트 레코드 제거 명령어

 

FixMBR : Windows 2000을 사용하던 중에 시스템의 오류로 마스터 부트 레코드에 이상이 있을 경우 마스터 부트 레코드를 복구하는 명령어

 

optical fiber ; 광섬유(케이블) : 전기 신호를 광선 신호로 바꾸어 유리섬유를 통하여 전달하는 케이블로서 유선 전송매체에 비하여 대역폭이 넓어 데이터 전송률이 뛰어남.

전기신호의 문제점인 전기 모터, 번개 충격으로 인한 신호의 왜곡 현상, 간섭 현상을 해결하기 위해 빛을 이용한 광섬유를 이용한다.

 

*전송매체

트위스트페어는 2500m 이내의 거리에서 10Mbps의 전송 속도를 낼 수 있다.

동축케이블은 10~50Mbps의 속도를 낼 수 있으며, 브로드밴드와 베이스밴드 방식으로 정보를 전송

 

interNIC은 도메인과 IP를 관리하는 목적으로 만들어진 조직 , 네트워크 ID를 부여한다.

 

swap ; 스왑

스왑은 메모리 내의 데이터 페이지 또는 세그먼트를 교체하는 것이다. 스왑핑은 컴퓨터가 주기억장치보다 더 큰 프로그램이나 데이터 파일을 다룰 수 있게 하는 유용한 테크닉이다. 운영체계는 주기억장치 내에 가능한 한 많은 데이터를 복사해 넣고, 나머지는 디스크 상에 남겨둔다. 운영체계가 디스크에 있는 데이터를 필요로할 때, 주기억장치 내의 데이터 일부를 디스크 상의 데이터와 교체한다. DOS는 스왑핑을 수행하지 않지만, OS/2, 윈도우, 유닉스 등을 포함한 많은 운영체계들이 스왑핑을 수행한다. 스왑핑은 때로, 페이징이라고 불리기도 한다.

RAM의 부족한 용량을 보충하기 위해 하드 디스크의 일정 부분을 지정하여 RAM처럼 사용한다. 일반적으로 실제 메모리의 두 배 정도면 적당하다.

시스템을 모니터링 한 결과 SWAP이 많이 일어나면 메모리를 증설해야 한다.

한 번 설정한 SWAP의 크기는 사용자가 변경이 가능하다.

 

교착상태(Deadlock) : 너무 많은 패킷이 서브넷 상에 존재하여 전송 속도를 저하시키는 상태를 의미.

 

X.25

X.25[엑스닷 투어니 화이브]는 패킷 교환망에 광범위하게 사용되는 네트웍 프로토콜로서 1976년에 CCITT에 의해 표준으로 채택되었다. X.25 프로토콜은 컴퓨서브나 TCP/IP 네트웍 등 서로 다른 공공네트웍 상의 컴퓨터들이 네트웍 계층 차원에서 중간 매개를 담당하는 컴퓨터를 통해 통신할 수 있게 해준다. X.25의 프로토콜들은 OSI 통신모델에 정의되어 있는 데이터링크 및 물리계층 프로토콜들과 밀접하게 교신한다.

 

CSU/DSU (Channel Service Unit/Digital Service Unit)

CSU/DSU는 근거리통신망에 사용되는 통신기술로부터 나온 디지털 데이터 프레임들을 광역통신망에 보낼 수 있도록 적절한 프레임으로 변환하는 외장형 모뎀 크기의 하드웨어 장치이다.

 

10 Base T : WorkstationHub로 연결된 케이블을 가지고 있어야 한다.

 

ATM (asynchronous transfer mode) ; 비동기 전송 모드 , 전용접속 스위칭기술 사용

 

윈도우2000서버 설치 옵션 : Floppy Disk, CD-ROM, 네트워크 공유 또는 Sysprep를 사용하는 무인 설치 등이 있음.

 

etc : etc디렉토리는 디바이스 드라이버 장치의 목록이 저장되어 있음

 

반응형

'IT > Etc' 카테고리의 다른 글

심심풀이로 알아보는 연봉별 실수령액 표  (0) 2018.01.30
시도해볼만한 프로그래밍언어 8종  (0) 2018.01.24
구글 검색유입 추가시키기  (1) 2018.01.08
SVN Ignore 사용하기  (2) 2018.01.08
애드센스 적용해보기  (0) 2018.01.02
반응형

사실 SHA256이나 MD5 같은 단방향 암호화를 전송하는측에서 왜 해야 하는지 의문이 들기도 하지만,
모든 개발이 생각하는대로 흘러가지 않는만큼 여러가지(?) 이유로 전송하는 문자열을 암호화 해야 하는 이슈가 발생하였다.

암호화를 SHA-256으로 하기로 협업과 약속하고 자바스크립트로 SHA256 암호화 할 수 있는 방법으로 구글링 해 보니, 쉽게 찾을 수 있었다. 이미 외국의 개발자분이 자바스크립트로 구성된 함수를 제작하여 공개하셨다.

함수는 아래와 같으며, 원 출처지인 http://www.webtoolkit.info/javascript_sha256.html#.VuJRJuY4tFC 을 통해서도 확인이 가능하다.


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
<script type="text/javascript">
    /**
    *
    *  Secure Hash Algorithm (SHA256)
    *  http://www.webtoolkit.info/
    *
    *  Original code by Angel Marin, Paul Johnston.
    *
    **/
      
    function SHA256(s){
      
        var chrsz   = 8;
        var hexcase = 0;
      
        function safe_add (x, y) {
            var lsw = (x & 0xFFFF+ (y & 0xFFFF);
            var msw = (x >> 16+ (y >> 16+ (lsw >> 16);
            return (msw << 16| (lsw & 0xFFFF);
        }
      
        function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }
        function R (X, n) { return ( X >>> n ); }
        function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }
        function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }
        function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }
        function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }
        function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }
        function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }
      
        function core_sha256 (m, l) {
             
            var K = new Array(0x428A2F980x713744910xB5C0FBCF0xE9B5DBA50x3956C25B0x59F111F1,
                0x923F82A40xAB1C5ED50xD807AA980x12835B010x243185BE0x550C7DC3,
                0x72BE5D740x80DEB1FE0x9BDC06A70xC19BF1740xE49B69C10xEFBE4786,
                0xFC19DC60x240CA1CC0x2DE92C6F0x4A7484AA0x5CB0A9DC0x76F988DA,
                0x983E51520xA831C66D0xB00327C80xBF597FC70xC6E00BF30xD5A79147,
                0x6CA63510x142929670x27B70A850x2E1B21380x4D2C6DFC0x53380D13,
                0x650A73540x766A0ABB0x81C2C92E0x92722C850xA2BFE8A10xA81A664B,
                0xC24B8B700xC76C51A30xD192E8190xD69906240xF40E35850x106AA070,
                0x19A4C1160x1E376C080x2748774C0x34B0BCB50x391C0CB30x4ED8AA4A,
                0x5B9CCA4F0x682E6FF30x748F82EE0x78A5636F0x84C878140x8CC70208,
                0x90BEFFFA0xA4506CEB0xBEF9A3F70xC67178F2);
 
            var HASH = new Array(0x6A09E6670xBB67AE850x3C6EF3720xA54FF53A0x510E527F
0x9B05688C0x1F83D9AB0x5BE0CD19);
 
            var W = new Array(64);
            var a, b, c, d, e, f, g, h, i, j;
            var T1, T2;
      
            m[l >> 5|= 0x80 << (24 - l % 32);
            m[((l + 64 >> 9<< 4+ 15= l;
      
            for ( var i = 0; i<m.length; i+=16 ) {
                a = HASH[0];
                b = HASH[1];
                c = HASH[2];
                d = HASH[3];
                e = HASH[4];
                f = HASH[5];
                g = HASH[6];
                h = HASH[7];
      
                for ( var j = 0; j<64; j++) {
                    if (j < 16) W[j] = m[j + i];
                    else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
      
                    T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
                    T2 = safe_add(Sigma0256(a), Maj(a, b, c));
      
                    h = g;
                    g = f;
                    f = e;
                    e = safe_add(d, T1);
                    d = c;
                    c = b;
                    b = a;
                    a = safe_add(T1, T2);
                }
      
                HASH[0= safe_add(a, HASH[0]);
                HASH[1= safe_add(b, HASH[1]);
                HASH[2= safe_add(c, HASH[2]);
                HASH[3= safe_add(d, HASH[3]);
                HASH[4= safe_add(e, HASH[4]);
                HASH[5= safe_add(f, HASH[5]);
                HASH[6= safe_add(g, HASH[6]);
                HASH[7= safe_add(h, HASH[7]);
            }
            return HASH;
        }
      
        function str2binb (str) {
            var bin = Array();
            var mask = (1 << chrsz) - 1;
            for(var i = 0; i < str.length * chrsz; i += chrsz) {
                bin[i>>5|= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
            }
            return bin;
        }
      
        function Utf8Encode(string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
      
            for (var n = 0; n < string.length; n++) {
      
                var c = string.charCodeAt(n);
      
                if (c < 128) {
                    utftext += String.fromCharCode(c);
                }
                else if((c > 127&& (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6| 192);
                    utftext += String.fromCharCode((c & 63| 128);
                }
                else {
                    utftext += String.fromCharCode((c >> 12| 224);
                    utftext += String.fromCharCode(((c >> 6& 63| 128);
                    utftext += String.fromCharCode((c & 63| 128);
                }
      
            }
      
            return utftext;
        }
      
        function binb2hex (binarray) {
            var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
            var str = "";
            for(var i = 0; i < binarray.length * 4; i++) {
                str += hex_tab.charAt((binarray[i>>2>> ((3 - i%4)*8+4)) & 0xF+
                hex_tab.charAt((binarray[i>>2>> ((3 - i%4)*8  )) & 0xF);
            }
            return str;
        }
      
        s = Utf8Encode(s);
        return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
      
    }
     
     
     
     
 
 
    // 암호화 확인
    console.log(SHA256("Test")) ;
 
</script>
 
cs

출처: http://fruitdev.tistory.com/191 [과일가게 개발자]




레퍼런스 문서

http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf

각 block 내용 및 W[64]의 내용들이 자세하게 나와있음

http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf

위와 비슷한 정보 

http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf



sha256은 hash 함수의 일종이다

hash 함수라는게 뭐냐면 다 알고 있겠지만 간단히 설명해보겠다


y = x + 2 이런 함수는 y를 알면 x도 알 수 있다

하지만 y = hash(x) 이런 해쉬 함수는 y를 알아도 x를 알 수 없는게 특징이다

그리고 모든 x값에 대해 각기 다른 y값을 내뱉는 특징 때문에 x가 원본임을 증명하는 일종의 시그니쳐로도 사용할 수 있다

(정확하게 말하자면 hash 함수는 단사함수가 아니다. hash collision이 있어서 다른 x임에도 같은 y값이 나오는 경우도 있다.

 hash collision을 피하기 위해선 계산을 더 복잡하게 하면 된다. 적당한 기회 비용을 두고 밀당을 해야한다는 소리)


hash 결과값은 32bit 8개를 병렬로 늘어놓은 값 

32bit x 8 = 256bit 그래서 이름이 sha256이다


원본 메세지의 각 문자(ascii 8bit)를 적당히 잘라 붙이고 쉬프트하고 and, or 등등 해서 512bit 단위의 블럭으로 만들고 이를 볶고 지져 hash를 계산한다

512bit 블럭으로 만들기 위해 크면 자르고(parsing) 모자라면 붙인다(padding)


아래의 공식에 맞춰 hash 계산에 필요한 블럭을 만든다

L + 1 + k = 448mod512


L(data length)는 hash를 만들고 싶은 원본 message의 bit길이 이므로 무조건 8의 배수이다

구현할 때 447bit 이런거 머리 빠지게 고민할 필요 없다


그리고 중요한 정보 - little endian을 기준으로 동작하도록 설계되어있다

x86, arm을 보통 사용하는 우리는 짜증나는 endian 전환을 해야 한다



실제 구현 관련 정리 - 블럭 제작 방법 및 hash 계산 방법

hash 계산 및 업데이트

간단하므로 생략, fips 문서에 나온데로 4개의 절차를 수행하면 된다(복잡해 보이는 시그마 같은거 다 문서에 잘 정의 되어있다)


메세지 길이 = len

case 1. len < 56(448bit)

마지막에 1bit를 추가하고 448bit까지 0으로 채움

그리고 마지막 64bit는 총 메세지 길이(lenx8)를 기록한다

hash 계산, 업데이트


case 2. 56 <= len < 64

마지막에 1bit를 추가하고 512bit까지 0으로 채워 block을 만든다

그리고 hash를 계산, 업데이트 한다

그리고 448bit까지 모두 0으로 채우고 마지막 64bit를 총 메세지 길이(lenx8)를 기록한다

그리고 hash 계산, 업데이트


case 3. len >= 64(512bit 이상)

512bit 씩 block으로 잘라 hash 계산, 업데이트 한다

마지막 남는 메세지는 길이에 따라 case1 혹은 case2와 동일하게 진행


last

계산한 32bit 8개의 값을 나열하면 sha256 완성



기타 유용한 참고 소스 코드

kernel 에 포함된 sha....코드.......이해하기 너무 어려움

openssl 의 crypto/sha에 있는 코드들 추천, 다만 최적화 되어있는 부분은 이해하기 힘듬

https://github.com/b-con/crypto-algorithms 매우 추천 깔끔하게 정리 되어있음

반응형
반응형


-XSS 필터



웹 페이지를 만들보면 사용자의 악의적인 공격을 많이 받게되는데



이런 것들중 가장 대표적인것이 XSS 공격이다


크로스 사이트 스크립트 라는것인데 서버로 보내는 입력값에 자바스크립트를 보내서


다른 사용자에게 자신이 만든 스크립트를 실행시켜서 사용자의 정보를 빼내는것이다




지금 당장 자신의 사이트가 XSS 를 방어하고 있는지 확인하는 방법은 간단하다


입력창 아무대서나 <script> alert("script ok"); </script> 라고 입력하고


저장한 후 상세화면으로 들어갔을때 해당 코드가 실행되는지 확인하면 간단하다



이런 문제를 해결하는데에는 많은 방법이 있지만 간단하게 Filter 추가 만으로 해결할 수 있는 방법이 있다


1. CrossScriptingFilter 필터 파일

2. RequestWrapper  필터링을 실행할 파일

3. web.xml 에서 세팅


1. 기본 컨트롤 클래스

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
 
package com.greatwebguy.filter;
 
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
 
 
public class CrossScriptingFilter implements Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
 
    public void destroy() {
        this.filterConfig = null;
    }
 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
 
        chain.doFilter(new RequestWrapper((HttpServletRequest) request), response);
 
    }
 
}
cs




2. 치환 동작 메서드

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
package com.greatwebguy.filter;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
public final class RequestWrapper extends HttpServletRequestWrapper {
 
    public RequestWrapper(HttpServletRequest servletRequest) {
        super(servletRequest);
    }
 
    public String[] getParameterValues(String parameter) {
 
      String[] values = super.getParameterValues(parameter);
      if (values==null)  {
                  return null;
          }
      int count = values.length;
      String[] encodedValues = new String[count];
      for (int i = 0; i < count; i++) {
                 encodedValues[i] = cleanXSS(values[i]);
       }
      return encodedValues;
    }
 
    public String getParameter(String parameter) {
          String value = super.getParameter(parameter);
          if (value == null) {
                 return null;
                  }
          return cleanXSS(value);
    }
 
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (value == null)
            return null;
        return cleanXSS(value);
 
    }
 
    private String cleanXSS(String value) {
                //You'll need to remove the spaces from the html entities below
        value = value.replaceAll("<""& lt;").replaceAll(">""& gt;");
        value = value.replaceAll("\\(""& #40;").replaceAll("\\)""& #41;");
        value = value.replaceAll("'""& #39;");
        value = value.replaceAll("eval\\((.*)\\)""");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        value = value.replaceAll("script", "");
        return value;
    }
}
cs



3.(<filter-class> 에는 해당 클래스 파일 경로를 넣어야한다)

1
2
3
4
5
6
7
8
9
 
<filter>
    <filter-name>XSS</filter-name>
    <filter-class>com.greatwebguy.filter.CrossScriptingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>XSS</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
cs




-URIEncodin 필터


Tomcat에서 한글 encoding을 설정하는 방법은 요청 메써드 (GET or POST)에 따라 다르다.

get 방식

Tomcat의 sever.xml 을 열고 

1
2
3
4
<Connector port="9090" protocol="HTTP/1.1" 
                 connectionTimeout="20000" 
                redirectPort="8443"
                URIEncoding="utf-8" />
cs


위 URIEncoding 부분을 추가했다.. 그러니 한글이 깨지는 것을 막을 수 있었다.
기본적으로 톰캣은 ISO-8859-1 인코딩 한다.
그래서 한글이 깨졌던거 같다.

post 방식

web.xml 아래와 같이 filter class 를 등록한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <filter>
  <filter-name>Set Character Encoding</filter-name>
  <filter-class>filters.SetCharacterEncodingFilter</filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>utf-8</param-value>
  </init-param>
 </filter>
 
 <filter-mapping>
  <filter-name>Set Character Encoding</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 
 <filter-mapping>
   <filter-name>encodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
 </filter-mapping>
 
 
cs





출처 사이트:

http://18281818.tistory.com/76 [반이라도 이해하자]

http://kcmuni.tistory.com/entry/한글-깨짐-처리URIEncodingUTF-8 [내일을 항해~]


반응형
반응형

1. 비밀번호 정규식




특수문자 / 문자 / 숫자 포함 형태의 8~15자리 이내의 암호 정규식

var regex = /^.*(?=^.{8,15}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$/;

 

숫자와 문자 포함 형태의 6~12자리 이내의 암호 정규식

var regex = /^[A-Za-z0-9]{6,12}$/;


-사용예제


1
2
3
4
5
6
7
var passRule = /^[A-Za-z0-9]{6,12}$/;//숫자와 문자 포함 형태의 6~12자리 이내의 암호 정규식
 
if(!passRule.test($("input[id='PASS']").val())) {
    //경고
 
    return flase;
}
cs


2. 이메일 정규식





var regExp = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;


- / / 안에 있는 내용은 정규표현식 검증에 사용되는 패턴이 이 안에 위치함
- / /i 정규표현식에 사용된 패턴이 대소문자를 구분하지 않도록 i를 사용함
- ^ 표시는 처음시작하는 부분부터 일치한다는 표시임
- [0-9a-zA-Z] 하나의 문자가 []안에 위치한 규칙을 따른다는 것으로 숫자와 알파벳 소문지 대문자인 경우를 뜻 함
- * 이 기호는 0또는 그 이상의 문자가 연속될 수 있음을 말함


-사용 예제


1
2
3
4
5
6
var emailRule = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;//이메일 정규식
 
if(!emailRule.test($("input[id='EMAIL']").val())) {            
            //경고
            return false;
}
cs



3. 핸드폰번호 정규식

var regExp = /^\d{3}-\d{3,4}-\d{4}$/;


4. 일반 전화번호 정규식

var regExp = /^\d{2,3}-\d{3,4}-\d{4}$/;


출처 : 

http://yyman.tistory.com/entry/Javascript-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%A0%95%EA%B7%9C%EC%8B%9D

https://webisfree.com/2016-05-12/%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A3%BC%EC%86%8C-%EA%B2%80%EC%A6%9D-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D



반응형
반응형

매일 다음으로만 유입이 되어서 구글은 왜 안들어오지 했는데

검색경로를 따로 추가해줘야하더군요 잘설명된 블로그가 있어서 퍼왔습니다

출처: http://jeorijjang.tistory.com/29


<사이트 등록>

1.

구글 웹마스터 도구로 이동

 

 

 

 

2.

블로그 주소 입력 후 속성추가 클릭

 

 

 

 

 

3.

HTML 태그 클릭 후 매타태그 복사(Ctrl+C) 후 자신의 블로그로 이동

 

 

 

 

4.

 

관리 페이지에서 HTML/CSS 편집 클릭

 

 

 

 

5.

<head>와 </head>사이에 매타태그를 붙여넣기(Ctrl+V) 후 저장.

 

 

 

 

6.

구글 웹마스터 도구로 돌아와 확인을 누르고 계속을 클릭합니다.

 

 

 

  

<사이트맵>

1.

사이트맵 생성 페이지로 이동(이미 sitemap.xml파일이 첨부되어있으면 4번으로 이동)

블로그 주소를 입력하고 Frequency를 Always로 변경 후

Create Sitemap을 클릭합니다.

 

 

 

 

2.

파일생성이 완료되면 하단의 Download버튼을 눌러 파일을 저장합니다.

 

 

 

 

3.

글 작성으로 들어가 sitemap.xml파일을 첨부 후 글을 비공개로 저장합니다.

 

 

 

 

4.

다시 글을 눌러서 우측에 HTML을 체크한 후 cfile로 시작하는 xml 주소를 복사합니다.

cfile23.uf@????????????????????.xml

이런식입니다.

 

 

 

 

5.

구글 웹마스터도구에서 Sitemap 추가/테스트를 눌러

attachment/cfile23.uf@????????????????????.xml

를 입력한 후 제출을 클릭.

앞에 attachment/를 꼭 붙이셔야 합니다.

 

 

 

 

6.

마찬가지 방법으로rss/

를 입력한 후 제출을 클릭합니다.

 

 

 

 

<RSS>

위에서 rss/를 추가해서 안해도 될것같긴한데 하나 더 해놓는다고 손해볼건 없으니 저는 이것도 했습니다.

원래는 다들 아래의 방식을 사용하시더군요..

 

1.

구글 블로그 핑 접속

 

 

 

 

2.

블로그주소/rss를 입력 후 블로그 전송 클릭

 

 

 

 

3.

완료

 

 

 

 

<최적화 완료>

며칠 기다리시면 적용이 됩니다.

(RSS는 1일, 사이트맵은 3일정도 걸린듯)

반응형
반응형
1···3456789

+ Recent posts