반응형

 



 자바스크립트를 처음 접하게 됬을 때 함수 표현식(밑에 설명)으로 선언된 함수를 보며 이건 뭐지? 하는 생각을 했었습니다. 자바스크립트는 함수를 정의하는 세 가지 방법이 있는데 이를 모르고 있다면 처음 접하셨을 때 많이 당황할 수 있습니다. 오늘은 자바스크립트에서 함수를 정의하는 방법과 함수를 호출하는 패턴 그리고 익명 함수에 대해 알아보도록 하겠습니다. 



1. 먼저 자바스크립트에서 함수란???

 자바스크립트에서 함수는 문장을 실행할 수 있는 고유한 스코프(scope)다. (scope에 대한 설명은 ver2 참고)

 자바스크립트에서 함수를 설명 할 때 "자바스크립트에서 함수는 first-class object(또는 citizen, value)다"는 정의를 알고 갈 필요가 있다. 대부분이 first-class object라는 단어에 대해 생소하실 텐데 여기서 말하는 first-class object는 다음과 같은 의미들을 포함합니다.


 1) first-class object는 변수에 저장할 수 있어야 한다.

 2) first-class object는 함수의 파라미터로 전달할 수 있어야 한다.

 3) first-class object는 함수의 반환값으로 사용할 수 있어야 한다.

 4) first-class object는 자료 구조에 저장할 수 있어야 한다.


 위와 같은 조건들을 충족시키는 객체를 first-class object라 하고 자바스크립트 함수를 의미합니다. 한 마디로 "자바스크립트에서 함수는 first-class object다"라고 생각하시면 될 것 같습니다. 이와 같이 자바스크립트에서 함수는 객체를 의미하고 함수는 변수, 배열, 객체에 저장될 수 있다는 뜻을 내포하고 있습니다. 또한 함수에 전달될 수도 함수에서 반환될 수도 있습니다. 



2. 함수를 정의하는 세 가지 방법  

  1 ) 함수 생성자 방식

 함수 생성자 방식은 함수 선언과 더불어 new 키워드를 통해 함수 객체를 생성하는 방법으로 마지막 매개변수는 함수의 로직(몸체 코드)부분을 의미하며, 그 외의 매개 변수는 인수가 됩니다.



 2 ) 함수 선언문 방식

 함수 선언문 방식은 우리가 주로 함수를 사용할 때 쓰는 방법으로 많이들 익숙하리라 생각 됩니다. 



 3 ) 함수 표현식 방식

 함수 표현식 방식은 변수를 선언하고 그 변수에 함수를 할당하고 있는 모습을 볼 수 있습니다. c나 c++, java와 같은 언어에서는 차마 볼 수 없는 광경입니다. 따라서 위의 함수를 선언하는 위의 세 가지 방법을 다 모르고 있을 경우 많이 당황하실 우려가 있습니다. 

저 코드를 실행하면 console.log를 통해 4, 4, 4가 찍히게 됩니다. 어떤 방식을 사용하든 문제는 없지만 함수 생성자 방식은 함수이 몸체 부분을 문자열로 작성해 주어야 되기 때문에 많이 불편하여 자주 사용되지 않는 편입니다. 



 3. 함수를 호출하는 네 가지 패턴

 함수는 다음과 같은 네 가지 시나리오나 패턴을 사용해 호출할 수 있습니다.

  1 ) 함수 패턴

 함수를 객체의 속성이 아닌 함수(fucntion)로서 호출할 때를 일컫는다.

 


  2 ) 메소드 패턴 

 함수를 객체의 속성(Property)에 저장하는 경우 이 함수를 메소드라고 부르고 이를 통해 함수를 호출하는 것을 메소드 패턴이라 한다. 


 3 ) 생성자 호출 패턴

 함수를 new라는 전치연산자와 함께 호출하는 것을 말한다. 생성자 호출 패턴을 사용하는 경우 호출한 함수의 prototype (자바스크립트에서 Function() 인스턴스를 만들 때 자바스크립트가 인스턴스에 부여하는, 이름이 "prototype"이고 기본값이 객체인 속성일 뿐이다. )속성의 값에 연결되는 (숨겨진)링크를 갖는 객체가 생성되고, 이 새로운 객체는 this에 바인딩된다.(자바스크립트의 prototype은 중요하므로 이에 대해서는 ver.4에서 포스팅하도록 하겠다) 


 console.log를 통해 찍히는 내용을 보자.




 4 ) apply()와 call() 패턴

 

 call()과 apply()의 차이점은 호출할 함수에 매개변수를 전달하는 방식이다. apply()는 배열방식으로 매개변수를 전달한다.



 4. 익명 함수

 익명 함수(anonymous function)란 이름이 없는 함수를 뜻한다. 익명 함수는 대부분 다른 함수에 매개변수로서 전달되는 경우가 많다.



 #다른 프로그래밍 언어와 달리 자바스크립트에서는 매개변수를 생략햐도 아무런 문제가 없다. 심지어 함수 선언 시 매개변수를 정의한 경우에도 문제가 없다. 전달하지 않은 인수에는 undefined 값이 저장된다. 물론, 인수를 전달하지 않으면 함수 내의 코드가 올바르게 동작하지 않을 수 있다.


 # 반대로 추가 매개변수(함수 선언 시 정의하지 않은 매개변수)를 함수에 전달해도 에러가 발생하지 않는다. 추가로 전달한 매개변수는 함수에 자동으로 추가되는 arguments 객체(함수로 전달된 매개변수를 저장하고 있는 배열 비슷한 객체)를 통해 접근할 수 있다.  



참조 

자바스크립트를 깨우치다 - 코디 린들리



 


반응형
반응형

 

 저번 포스팅에서 자바스크립트 언어의 특징을 시작으로 가장 기본적이면서도 중요한 내용들에 대해 알아보았다. (참고, [자바스크립트]자바스크립트 이것만은 꼭 알고가자(Part 1)) 이번 두번 째 자바스크립트 포스팅에서는 자바스크립트에서의 Scope와 Hoisting, Scope Chain, Closure에 대해 정리해보도록 하겠습니다.. 포스팅 내용중에 잘못된 부분이 있거나 개선할 점이 있다면 댓글로 의견 남겨주시면 감사하겠습니다.



1. 자바스크립트에서의 Scope는???

 스코프(Scope)란 범위를 뜻하는 단어로서 자바스크립트에서 변수의 종류에 따라 어느 범위까지 참조가 가능한지에 대한 의미쯤으로 생각하면 되겠다. 크게 전역 스코프(global scope), 지역 스코프(local scope, "함수 스코프"라고도 불림)로 구분된다. 



 1) 전역 스코프(global scope)란 말 그대로 global 영역에 선언된 전역변수가 스크립트 내의 모든 구간에서 사용될 수 있음을 의미한다. 밑의 그림을 보자.

 

 그림을 보면 먼저 글로벌 전역 변수를 선언한 것을 볼 수 있다. var global = 1로 설정한 값은 해당 스크립트의 어떤 영역에서도 사용이 가능하다. 물론 함수안에서도 전역변수를 사용할 수 있는 것을 예제를 통해 알 수 있다. console.log()로 값을 찍어 보면 선언하고 나서 찍었을 때와 함수에서 글로벌 전역변수를 리턴해주는 값 모두 처음 값을 지정해주었던 "1" 이 찍히는 것을 알 수 있다. (참고로 자바스크립트에서는 변수를 선언할 때 타입을 지정하지 않는다. 변수를 사용할 때 무슨 타입이든 var를 사용한다. 또한 변수를 선언할 때 'var'를 입력하지 않으면 전역변수로 인식하기 때문에 전역변수든 지역변수든 모두 'var'를 붙여 일관성을 부여하도록 하자. 밑의 '5)'설명 참고) 





 2) 지역 스코프(local scope, "함수스코프")란 쉽게 말해 해당 함수안에서만 접근가능한 private variable을의미한다. 즉 함수 내에서 var를 사용해 정의된 코드는 지역 스코프에서만 유효하고 해당 함수 내에서 정의된 중첩 또는 자식 함수를 비롯해 해당 함수 내부에서만 사용 가능하다. 

 

 그림을 보면 test()함수안에서 선언된 'local'이라는 지역변수는 함수 외부 {} 밖에서는 그 변수의 유효범위가 끝나버리기 때문에 접근할 수 없는 것을 볼 수 있다. 





 3) 전역변수와 지역변수를 동일한 이름으로 사용하게 되면 어떻게 될까???

 그럼 만약에 전역변수와 지역변수를 동일한 이름으로 사용했을 경우 어떤 문제가 발생할 수 있을까? 자바스크립트에서는 전역 변수 영역에 선언된 변수와 동일한 이름의 지역변수를 사용할 수 있다. 예를 보자.

 

 그림에서 보면 전역변수와 지역변수를 동일한 이름으로 사용을 했을 경우에도 전혀 문제가 되지 않는 것을 볼 수 있다. 보면 test()함수를 실행해 변수의 값을 찍어보면 지역변수의 값(3)이 찍히고 그냥 "global"변수 값을 찍어보면 전역변수의 값인 '1'이 찍히는 것을 확인할 수 있다. 다시말해 전역변수와 지역변수를 동일한 이름으로 사용하여도 각기 다른 변수객체가 만들어 진다는 것을 알 수 있다. 이 부분에 대해서는 밑의 설명들을 참고하길 바란다. (또한 혼란을 막기 위해 이렇게 중첩된 변수 네이밍 사용을 가급적 사용하지 않는 것이 좋다.)





 4) 자바스크립트에는 블록 스코프가 없다. 

 자바스크립트에서는 조건문 ( if() { } )과 반복문( for(){} )은 스코프를 만들지 않으므로 조건문과 반복문 사이에도 변수를 서로 재정의할 수 있다. 

 

 그림에서와 같이 자바스크립트에는 블록 스코프가 없기 때문에 no의 값이 for문에서 바뀌는 것을 확인하였다. 자바스크립트에는 함수, 전역, eval() 스코프만 있음을 명심하자.





 5) 함수 내에서 변수 선언 시 var를 사용해 스코프에서 발생할 수 있는 문제를 피하자.

 위에서 잠깐 설명했다 시피 자바스크립트는 변수를 선언할 때 따로 타입을 지정하지 않고 var를 사용해 선언하게 된다. var 키워드 없이도 변수를 선언할 수 있는데 이는 함수 안에서 선언한다 하더라도 전역 변수의 스코프를 갖게 된다. 

 

 그림과 같이 첫 번째는 test()함수 안에 var를 사용해 지역변수로 선언하고 함수 범위 밖에서 'boo' 지역변수에 접근했을 때는 접근할 수 없지만 두 번째에서는 var 키워드를 사용하지 않고 'boo'를 선언하였기 때문에 전역변수로 인삭하게 되고 test()함수 밖에서도 접근할 수 있게 된다. 따라서 함수 내에서 변수를 선언할 때에는 항상 var를 사용하도록 하자. 그렇지 않으면 스코프 때문에 혼란스러워지는 문제가 발생할 수 있기 때문이다. 





2. 자바스크립트 Hoisting 이란???

 'hoist = 끌어올리다' 라는 뜻으로 자바스크립트에서는 변수 선언과 함수 선언은 해당 유효범위의 가장 최상위로 끌어 올려짐을 의미합니다. 예제를 통해 좀 더 쉽게 살펴보도록 하겠습니다. 

 

 그림을 보게 되면 처음 console.log에서는 undefined를 찍어내는 것을 파악할 수 있습니다. 이와 같은 이유는 자바스크립트 엔진에 의해 아래와 같이 해석되기 때문입니다.

 

 이렇게 'name' 변수의 선언부만 호이스팅 되기 때문에 발생합니다. 자바스크립트의 호이스팅은 함수나 변수의 선언부만 최상위로 끌어올리게 되고 초기화과정은 기존의 위치에서 실행되게 됩니다. 다시 말해 변수의 선언이 초기화나 할당시에 발생하는 것이 아니고, 유효범위의 최상위로 호이스트 되는 것입니다. 유효 범위 안에서 변수에 할당한 값을 활용하고 싶을 때에는 항상 유효범위의 최상위에 선안하고 값을 초기화 해주도록 하는 것이 자바스크립트의 호이스팅기능으로 인해 발생할 수 있는 문제들을 조금이나마 줄여줄 것 입니다.





 3. 자바스크립트의 Scope chain

 자바스크립트는 변수를 찾을 때 스코프의 계층 구조에 기반한 검색 체인을 거슬러 올라가며 추적하게 됩니다. 예제를 통해 좀 더 쉽게 살펴보도록 하겠습니다.

 

 그림에서 보면 console.log를 통해 "scopeChain"을 찍어 내는 모습을 볼 수 있습니다. console.log를 func2 스코프에 쓰여있지만 실제로 자바스크립트 scope chain을 통해 전역 스코프의 scopeChain 변수에 접근에 값을 출력하게 됩니다. func2 함수 스코프 내에 포함되어 있지 않은 scopeChain 값을 찾는 과정은 먼저 func2 함수에서 scopeChain 라는 변수를 찾게 되고, 이 값이 없으면 func2 의 부모 함수인 func1에서 검색을 하게 되고 여기에도 없으면 func1 의 부모 함수가 없기 때문에 전역 스코프에서 값을 찾게 됩니다. 전역 스코프에서 scopeChain을 발견하게 되면 이 값을 func2로 전달하게 되는 것을 자바스크립트의 scopeChain의 핵심 역할 입니다. 만약 전역 스코프에도 해당 내용이 정의되어 있지 않았다면 자바스크립트는 undefinded를 반환하게 됩니다. 



명확한 이해를 위해 예제를 하나 더 살펴보도록 하겠습니다.

 

 그림에서 보듯이 console.log는 func2에서 수행되고 있으면 "number1 + number2 + number3"의 연산을 수행하게 됩니다. 각각의 변수들은 각기 다른 스코프에서 선언이 되었습니다. 자바스크립트는 scope chain을 통해 해당 변수들을 찾게 되고 number3, number2, number1의 순서로 chain을 통해 접근하여 값을 func2 함수로 전달하여 연산을 수행하게 됩니다. 이렇듯 func2 함수에서 참조한 변수는 지역 스코프에 없을 경우 스코프 체인에서 변수를 검색하게 되며 스코프 체인을 검색할 때는 가장 처음 발견한 값을 반한하게 됩니다. (예를 들어 위에 number1, number2 의 명칭을 number3으로 변경해 주게 되면 console.log에는 9가 찍히게 됩니다.)


 이렇듯 스코프 체인을 검색할 때는 가장 처음 발견한 값을 반환하게 되므로 상위 범위에 대해서는 검색을 하지 않고 연산을 수행하여 9가 찍히게 됩니다. 



###스코프 체인은 함수를 실행한 위치가 아닌 정의한 위치에 의해 결정되어 집니다. 이를 가리켜 문법적 스코핑(lexical scoping)이라고도 합니다. 스코프 체인은 함수를 호출하기 전에 이미 만들어지며, 이 덕분에 우리는 클로저(closure)를 만들 수 있게 됩니다. 





 4. 자바스크립트 Closure

 

 Closure는 scope chain과 매우 밀접하게 연관되어 있기 때문에 scope chain의 이해가 우선시 됩니다. 그림에서 보면 sequencer 내부 함수에 ++seq를 반환하고 있는 것을 볼 수 있습니다. 이는 일반적으로 다른 언어에서는 유효범위를 벗어난 쓸 수 없는 변수이지만 자바스크립트에서는 scope chain을 통해서 연결이 가능하게 됩니다. 내부 함수는 자신이 선언된 환경에 대한 연결을 갖게 됩니다. 다시 말해 foo() 함수가 클로져를 갖게 됩니다. 클로져는 두개의 것으로 이루어진 특별한 오브젝트로 첫 번째는 함수, 두 번째는 그 함수가 만들어진 환경을 가지게 됩니다. 그 함수가 만들어진 환경은 함수가 만들어질 때 사용할 수 있었던 변수들로 이루어지고 이 경우에 foo()함수는 sequencer의 내부 함수와 seq 변수를 포함하는 클로져가 됩니다. 





[글을 쓰며]  

 자바스크립트 이것만은 알고가자 (Ver 2)를 포스팅하면서 어떻게 하면 좀 더 다른 누군가가 내 글을 봤을 때 '해당 내용들에 대해 쉽게 이해할 수 있을까'라는 고민을 많이 하게 됬다. 그로 인해 깨달은 것은 내가 그 내용에 대해 완벽히 파악하고 있지 못하다면 쉽게 설명하기 힘들다는 것과 내가 이해하는 내용을 글로 쉽게 옮겨 내는 것 또한 많은 노력이 필요하다는 것이다. 앞으로 글을 쓸 때 앞의 2가지 깨달음을 잊지 않고 포스팅을 해나가도록 하겠다. 



[참조]

자바스크립트를 깨우치다 - 코디 린들리 지음










반응형
반응형

회사에 들어와 처음 웹프로그래밍을 접하면서 자바스크립트에 대한 지식이 전무한 상태에서 무작정 남들이 작성한 코드를 토대로 감으로 프로그래밍을 했었다. 그 당시는 교육이수 중이라서 프로젝트 개발 시간도 부족한 나머지 따로 자바스크립트를 공부할 시간을 갖지 못했었다. 그래서였는지 조그마한 프론트 기능을 추가했을 때 사소한 문제들에 자주 부딪혔던 기억이 있다. 아직도 자바스크립트 공부가 많이 필요하지만 그 중 사소한 실수를 줄여 소중한 시간을 아낄 수 있는 기초 문법들에 대해 알고 넘어가 보려 한다.

 자바스크립트??? 객체기반언어, 인터프린터 언어 자바스크립트는 브라우저 기반에서 실행되는 객체 기반 언어이다. 또한 인터프린터 언어로 컴파일 언어와는 반대로 컴파일 과정이 생략되고 실행 중에 바로 한줄 한줄 번역 해 가며 실행된다. 이렇듯 한줄 한줄 변환되기 때문에 컴파일 언어보다 실행 속도가 당연히 떨어지게 된다. 또한 디버깅 혹은 에러를 잡아 내기가 컴파일 언어보다 힘들다. 하지만 인터프리트 언어는 장점 또한 가지고 있는데 한줄 한줄 해석되는 언어이다보니 자신의 프로그램을 수정하거나 보완한 경우, 전체를 완선히 새로 'Recompile'할 필요가 없어 코드를 수정하고 실행해 즉각 테스트가 가능해진다. (작업중인 jsp파일의 소스코드를 수정하고 웹페이지를 통해 즉시 확인해 볼 수 있는 이유) 또한 웹 브라우저의 Script 엔진이 직접 코드를 해석하여 처리하므로 적은 시스템 부하와 환경에 독립적인 장점을 가지고 있다.

 자바스크립트의 특징은???첫번 째, 자바스크립트는 객체 기반 언어로서 상속과 클래스가 존재하지 않는다.두번 째, 자바스크립트는 인터프리터 언어로서 클라이언트 웹 브라우저에 의해 해석되고 실행된다.세번 째, JavaScript는 HTML 문서 내에 기술되고 HTML 문서와 함께 수행된다.네번 쨰, JavaScript는 HTML에 연산, 제어 등 프로그래밍적인 요소를 추가하고, 클라이언트의 자원을 활용할 수 있게 한다.


 HTML에서 자바스크립트의 위치는??? <head>??<body>??? 보통 JSP에서 스크립트의 파일을 <head>에 모아두는데 학습을 하다 보니 head에 모아두는 것이 좋지 않다는 걸 알게 되었다. 보통 브라우저는 HTML 태그를 위부터 아래로 순서대로 읽어가며 DOM Tree를 만들고 바로바로 화면에 렌더링을 한다. 그런데 도중에 <script>태그를 만나면 렌더링을 일단 중지하고 스크립트를 실행하고 나서 다시 렌더링을 시작하게 된다. 문제는 여기서 발생한다. 만약 선언되어 있는 스크립트 중에 실행하는데 오래걸리는 스크립트가 있을 경우 화면 렌더링은 그 시점에서 멈추게 되는데 이로인해 사용자는 제대로 로딩되지 않은 공백 화면을 오래 마주하게 되는 문제가 생길 수 있다. (이로인해 많은 사용자들이 뒤로가기 버튼을 누르거나 다른 페이지로 넘거가게 된다) 하지만 스크립트를 <body> 가 닫히기 전에 넣어주게 되면 이러한 문제를 해결할 수 있다.</body>바로 직전이나 </html>후에 스크립트를 넣어주게 되면 DOM이 다 로딩되고 수행되기 때문에 복잡한 로직 수행이 수반된 스크립트나 이벤트 처리들을 다수 포함하고 있는 스크립트는 <body>가 닫히기 전에 명시해 주는 것이 좋다. 하지만 <body>사이에서 <script>를 찾는 것이 번거롭거나 불편하다고 느낄경우 처음 head에 스크립트를 선언시 defer기능을 통해 문서가 다 로딩 된 후 스크립트를 읽도록 하는 기능도 지원하는 것으로 알고 있다.(추가적인 부분은 구굴에 찾아보길 바란다)


 자바스크립트에서 기본 타입은??? 자바스크립트에서는 크게 Number, String, Boolean, Object, Null, Undefined의 타입이 존재한다. Object타입안에는 Function, Array, Date, RegExp(정규식)이 존재한다. 자바스크립트에서 사용되는 대부분의 데이터 타입은 객체로 존재하며 그에 따른 사용 또한 객체 기반이 될 수 밖에 없다.


 자바스크립트에서 Nan은 무엇인가??? 자브스크립트를 짜다가 Nan이라는 단어를 접하고 이게 뭐지 했던 때가 있었다. Nan은 Not a Number의 약자로 말그대로 해당 하는 값이 숫자가 아니라는 뜻이다. 자바스크립트에서 해당 데이터가 NaN인지 검사해주는 isNaN()이라는 내장 객체가 존재하는데 isNaN()은 NaN인지 여부를 검사하는 함수임으로 NaN일 때 true를 반환한다.


 자바스크립트에서 Null과 Undefined의 차이는???자바스크립트를 작성하다 보면 Undefined를 자주 접하게 될 것이다. 처음 Undefined를 접하게 되면 Null과 같은건가 하는 생각을 하게 되는데 둘은 다르다는 것을 알고 있어야 한다. 이 둘에 대한 차이를 정확히 이해하지 않고 스크립트를 작성하게 될 경우 사소한 부분에서 에러와 함께 시간을 많이 빼앗기게 될 것이다. 자바스크립트에서 null은 값이 없음을 나타내고 Undefined는 초기화(선언) 되지 않았거나 값이 할당되지 않았음을 나타낸다. Null은 개발자가 의도적으로 비어있는 값을 부여한 것이고 Undefined는 애당초 어떠한 값도 할당 되지 않은 것이다. 자바스크립트는 변수의 선언과 초기화를 동시에 하지 않아도 되는데 선언만 하고 초기화 되지 않은 변수는 초기화되지 않았거나 값이 할당되지 않았음을 표현하는 undefined라는 값을 할당받게 된다. 정리하자면 NULL은 변수가 참조하는 객체가 없음(null)을 나타내고 Undefined는 그 변수가 참조하는 객체를 아직 지정하지 않음(not Initialized)을 뜻하고 Undefined값을 가지는 변수는 할당을 통해 값을 가지고 이 값을 해제할 때 null타입이 되는 것이다.


자바스크립트에서 ===???프로그래밍을 하면서 '=='는 많이 접해보았을 것이다. 무엇을 비교할 때 많이 사용하는데 자바스크립트에서 멋도 모르고 '=='를 다른 언어에서 쓰던것 처럼 쓰게되면 큰코 다치는 날이 올 것이다.간단히 설명하자면 ==는 값만으로 체크를 하는 것이도 ===은 변수의 타입과 값을 모두 체크하여 비교하는 것이다.ex) x=3이라고 가정x==5 (false)x==3 (true)

x==="3" (false)x===3 true)가 되게 된다. 그럼 x=="3"을 하게 되면 결과는 어떻게 될까??? 상식대로라면 false를 뱉어야 하지만 true가 되게 되는데 자바스크립트의 ==는 형변환은 시도해 비교하게 되기 때문에 이와 같은 상황이 발생한다. 따라서 무작정 ==와 ===를 사용하게 되면 나중에 큰 문제에 직면하게 될 것이다. 반드시 차이를 정확히 이해하고 사용하기 바랍니다.


⊙ 자바크립트를 공부하는 입장으로서 가장 기본적인 내용에 대해 알아보았다. 다음 포스팅 '자바스크립트 이것만은 알고가자(Ver. 2)'에서는 자바스크립트에서의 Scope, Hoisting, Scope Chain, Closure에 대해서 알아보도록 하겠습니다.





반응형
반응형

최근 작업중 unix date를 파싱해야는 경우가 있어서 아무렇지 않게


String unixDate = "1498906817.357"

String[] parseDate = unixDate.split(".");

String parsedDate = Long.parseLong(parseDate[0]);


다음과 같이 썼는데 파싱된 데이터에 값이 안들어있다는...


확인해보니 split의 인자로 들어가는  .(dot)이 정규식이기 때문이었다. 

정규식에서는 .(dot)은 무작위의 한글자를 의미하므로 모든 문자가 토큰이 되기 때문에 배열에 남는게 없게 되는 것이다.

그렇기 때문에 이를 피하기 위해서는 이스케이프(\\)를 문자앞에 써줘야 한다.



String unixDate = "1498906817.357"

String[] parseDate = unixDate.split("\\.");

String parsedDate = Long.parseLong(parseDate[0]);


뭔가 split 메서드를 사용해 parsing을 했는데 값이 정상적으로 나오지 않는다면 정규식을 의심하자.



[ 참고 ]

there are 12 characters with special meanings: the backslash \, the caret ^, the dollar sign $, the period or dot ., the vertical bar or pipe symbol |, the question mark ?, the asterisk or star *, the plus sign +, the opening parenthesis (, the closing parenthesis ), and the opening square bracket [, the opening curly brace {, These special characters are often called "metacharacters".

반응형
반응형

클라우드 네트워크 교육(0627)

사내에서 클라우드 네트워크 교육(0627)을 듣고 새롭게 알게된 내용에 대해 간략하게 정리.


공해야할 것 들이 너무 나도 많음을 느낀다.

[ 교육들으며 새로 알게 된 내용 ]

1. 실제 네트워크 확인시 패킷을 뜬다고 소위 말하는데 실제로는 OSI Layer상의 Datalink Layer의 Frame을 의미한다

2. Frame, Packet, Segment의 주요한 차이는 header가 가지는 정보의 차이에 있다고 볼 수 있다.

세그먼트(Segment, OSI 7계층의 전송 계층(Transport Layer)) : 데이터를 네트워크를 통한 실질적인 전송을 위하여 적절한 크기로 분할한 조각.

패킷(Packet, OSI 7계층의 네트워크 계층(Network Layer)) : 전송을 위해 분할된 데이터 조각(세그먼트)에 목적지까지의 전달을 위하여 Source IP 와 Destination IP가 포함된 IP Header가 붙은 형태의 메세지

프레임(Frame, OSI 7계층의 데이터링크 계층(Data Link Layer)) : 최종적으로 데이터를 전송하기 전에 패킷에 Header(Mac Address 포함)와 CRC를 위한 Trailer가 붙은 메세지

3. 리눅스에서 MAC ADDRESS확인시 ifconfig외에 ip link 및 ip -4 addr로 확인 가능 (가급적이면 ip 명령어에 익숙해지자 - 네트워크관련 모든 명령 처리가능)


4. MAC ADDRESS는 유니크한가? 로컬 LAN안에서는 유니크해야한다.


5. MAC ADRRESS는 permanent한가? permanent하지 않다. ip link set을 통한 abusing가능. 그렇기 때문에 MAC ADDRESS를 통한 인증처리는 지양하자.


6. 패킷 전송 크기를 정하는 MTU(Maximum Transmission Unit) 가 작을 경우 header에 의한 overhead를 초래할 수 있다.

ex) 
데이터 사이즈 3000byte
MTU=500 (byte) 인경우 6frame 으로 나눠 전송, 각 프레임에 헤더는 14byte * 6이된다
MTU=1500 (byte, 일반적 설정) 2frame, 헤더는 14byte * 6이 된다.

     [ MTU 더 궁금하면참고 ] http://www.packetinside.com/2013/02/mtumaximum-transmission-unit.html


7. 네트워크 연결 확인시 ping보다는 arping 명령어 이용 ping의 경우는 어떤 layer에서 막혔는지 확인이 힘들다.


8. 네트워크 대역폭 확인 시 iperf3 명령어 사용 (참고, http://sola99.tistory.com/374)


9. 토스트 클라우드 네트워크는 각 서비스별에 맞춰 tenant하게 설계되어짐 (share x) - 서로간 통신을 위해서는 floating IP 필요


10. AWS에서는 virtual private cloud를 사용해 각 계정 전용 가상 네트워크 제공


네트워크에 대한 공부도 틈틈히 시간내서 하도록 하자. 

알고개발하는 것과 모르고 개발하는 것은 천지차이


반응형
반응형


 안녕하세요. 오늘은 프로세스와 스레드에 대해서 알아보도록 하겠습니다. 많은 분들이 실제로 프로세스와 스레드를 알고 계시면서도 막상 물어보면 대답하기 막막해하시는 경우도 많이 있고 저도 실제로 프로세스&스레드에 대해서 명확히 설명하기 힘들어 했던 경험이 있어 이번 기회에 한 번 간단히 개념적인 부분에 대해서 정리하고 넘어가려고 합니다. 이제 막 2년차에 접어드는 현업 개발자지만 요즘 느끼는 것은 새로운 기술들에 관심을 가지는 것도 중요하지만 개발을 함에 필요한 '기본적인 내용들과 지식을 좀 더 단단히 쌓아야 겠다'는 생각이 많이 들곤 합니다. 포스팅 시작하도록 하겠습니다.



[ PROCESS ]

 먼저 프로세스란 간단히 설명해서 실행중인 프로그램에 대한 인스턴스를 프로세스라고 합니다. 실제로 프로세스가 생성되게 되면 해당 프로세스는 운영체제로부터 주소공간, 파일, 메모리 등을 할당받게 됩니다. 그리고 메모리 공간은 CODE, DATA, HEAP, STACK영역으로 나뉘어지게 됩니다. 실제로 프로세스가 처리해야 될 일을 각각의 메모리 영역들 위에서 처리하게 되게 됩니다.

프로세스는 다음과 같은 독립된 메모리공간을 프로세스별로 가지게됩니다. (스레드 설명할 때 설명하겠지만 스레드는 STACK 부분만 독립적으로 가지게 됩니다.) 그렇기 때문에 특정 PROCESS가 다른 PROCESS 메모리에 직접 접근하기 힘듭니다.


[ THREAD ]

 스레드란 프로세스 안에서 동작되는 여러 실행의 흐름이라고 보시면 됩니다. 간단히 말해서 프로세스 내부에서 실제로 일을 하는 녀석들을 스레드라고 합니다. 우리 몸으로 치면 몸은 프로세스 손,발은 스레드 정도가 되지 않을까요?(단순한 제 생각) 기본적으로 하나의 프로세스가 생성되면 하나의 스레드가 같이 생성이됩니다. 이를 메인 스레드라고 부르며, 스레드를 추가로 생성하지 않는 한 모든 프로그램 코드는 메인 스레드에서 실행이 된다고 생각하시면 됩니다. 또한 프로세스는 메인 스레드 외에도 여러개의 스레드를 가질 수 있는데요. 이를 멀티스레드라고 합니다.

 스레드의 경우에도 프로세스와 같이 메모리 공간을 할당 받게 되는데요. 프로세스가 각각의 독립적인 메모리 공간을 할당받는 반면에 스레드의 경우는 Stack영역만을 독립적으로 할당 받게 됩니다. 실제로 Code, Data, Heap영역은 프로세스의 공간을 공유받아 사용하게 됩니다. 이렇듯 프로세스 내에서 생겨나는 모든 스레드의 경우 Stack이외의 영역은 프로세스의 영역을 공유받아 사용하게 되고 이러한 이유로 인해 스레드간 Context Switching(아래에 간단히 설명)이 발생했을 경우 Stack 영역의 데이터들만 switching되면 되므로 프로세스 스위칭보다 훨씬 빠르게 진행이 됩니다. 스레드의 장점으로는 시스템의 Throughput(처리량)이 향상 되며, 자원 소모가 줄어들고 스레드간의 스위칭 시간이 줄어들면서 일을 처리할 때 응답 시간이 단축되는 점이 있습니다. 반면에 여러 개의 스레드를 사용할 때는 프로세스가 가지고 있는 메모리 영역의 자원 공유의 문제가 발생할 수 있고 디버깅이 힘들다는 점이 있습니다. 마지막으로 프로세스의 메모리 영역(Data, heap)을 공유함으로써 전역 변수와 동적 할당 딘 메모리 공간을 공유하게 되고 이를 통해 쓰레드간 통신이 쉽게 가능하게 됩니다.


[ THREAD가 스택을 독립적으로 할당하는 이유 ]

 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소 값 및 함수 내에서 선언하는 변수 등을 저장하기 위해 사용되는 메모리 공간입니다. 따라서 스택 메모리 공간이 독립적이라는 것은 독립적인 함수 호출이 가능하다는 것이고, 이는 독립적인 실행흐름을 가질 수 있다는 것입니다. 결과적으로 실행 흐름의 추가를 위한 최소 조건이 독립된 스택을 제공하는 것이라고 볼 수 있습니다.


[ Context  Switching 이란? ]

 프로세스를 이것저것 우선 순위에 따라 변경하기 위해서는 실제로 작업에 사용되는 프로세스 데이터를 레지스터와 메모리 사이를 왕복하며 값을 복사해야 합니다. 보통 cpu에 의해 프로세스가 일을 처리하게 되는데 스케줄링 방식에 따라 특정 프로세스가 일을 진행하고 있다가 다른 프로세스에게 cpu사용권을 넘겨주게 될 때 어디까지 작업을 했고 다음부터는 어디서부터 작업을 해야하는지에 대한 정보를 보관할 수 있는 곳이 필요하고 이러한 정보들을 프로세스에 맞게 변경해주고 처리하는 것을 말합니다. 실제로 CPU는 동시에 한 개씩만 스레드를 실행시킬 수 있는데 스레드가 여러개가 생성되게 되면 CPU는 각각의 스레드를 번갈아가며 실항하게 되는데, 이 때 이전 스레드의 문맥 정보(레지스터 값, 실행중인 스택 정보 등)을 백업받고 백업 받아놓았던 다음 스레드의 문맥정보를 로딩하는 과정을 거치게 됩니다. 이 과정을 Context Switchig이라고 합니다. 이러한 스레드가 많아질 수록 Context Switching에 많은 부하가 걸리기 때문(메모리와 레지스터 사이의 데이터 이동도I/O이다)에 잘 고려해서 사용해야 되겠습니다.  


오늘 포스팅은 여기까지 하도록 하겠습니다. 잘못된 부분이나 설명이 부족한 부분은 댓글로 남겨주시면 참고하도록 하겠습니다. 감사합니다.




반응형
반응형

 


 [ REST API 제대로 알고 사용하기 ]

 어느 날 뜬금없이 대학교 친구에게 전화가 왔습니다. 그러더니 ‘야, REST API가 정확히 뭐 어떤 거야?’ 하는 질문에 가슴에 비수가 날아와 꽂힌 듯한 느낌을 받았습니다 . 며칠 전 카톡으로 요즘 보통 웹서비스들은 ‘REST API형태로 서비스를 제공한다’고 아는 척을 조금 했던 기억이 머릿속을 빠르게 스쳐 지나갔고 그 순간 대충 얼버무리며 ‘아, 그거 REST하게 클라이언트랑 서버간에 데이터를 주고 받는 방식'을 말한다며 얼렁뚱땅 마무리 지었던 기억이 납니다.  실제로 REST API의 서비스를 직접 개발도 해보고 사용도 해봤는데도 막상 설명을 하자니 어려움을 겪었던 적이 있으셨을텐데요. 그래서 이번에 REST API에 대해 정리하게 되었습니다. 기본적인 REST API에 대한 내용 외에도 REST API를 설계하실 때 참고해야 할 몇 가지 TIP들에 대해 공유해보도록 하겠습니다. 


1. REST API의 탄생

   REST는 Representational State Transfer라는 용어의 약자로서 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍쳐로써 REST를 발표했다고 합니다.


2. REST 구성

쉽게 말해 REST API는 다음의 구성으로 이루어져있습니다. 자세한 내용은 밑에서 설명하도록 하겠습니다.

자원(RESOURCE) - URI

행위(Verb) - HTTP METHOD

표현(Representations)


3. REST 의 특징

1) Uniform (유니폼 인터페이스) 

: Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말합니다.


2) Stateless (무상태성) 

: REST는 무상태성 성격을 갖는다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다. 세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.


3) Cacheable (캐시 가능) 

: REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 따라서 HTTP가 가진 캐싱 기능이 적용가능하다. HTTP 프로토콜 표준에서 사용하는 Last-Modifyed태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.


4) Self-descriptiveness (자체 표현 구조) 

: REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것이다.


5) Client - Server 구조 

: REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로  각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 된다.


6) 계층형 구조 

: REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.



4. REST API 디자인 가이드

! REST API 설계시 가장 중요한 항목은 다음의 2가지로 요약할 수 있습니다.

첫 번째, URI는 정보의 자원을 표현해야 한다.

두 번째, 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.

다른 건 다 잊어도 위 내용은 꼭 기억하시기 바랍니다.


4-1  REST API 중심 규칙

1) URI는 정보의 자원을 표현해야한다. (리소스명은 동사보다는 명사를 사용)

GET /members/delete/1

 

위와 같은 방식은 REST를 제대로 적용하지 않은 URI입니다. URI는 자원을 표현하는데 중점을 두어야 합니다. delete와 같은 행위에 대한 표현이 들어가서는 안됩니다.


2) 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE 등)로 표현

 위의 잘못 된 URI를 HTTP Method를 통해 수정해 보면

DELETE /members/1

로 수정할 수 있겠습니다. 회원정보를 가져올 때는 GET, 회원 추가시의 행위를 표현하고자 할 때는 POST METHOD를 사용하여 표현합니다.

 

회원정보를 가져오는 URI

GET /members/show/1     (x)

GET /members/1          (o) 

 

회원을 추가할 때

GET /members/insert/2 (x)  - GET 메서드는 리소스 생성에 맞지 않는다.

POST /members/2       (o)

 

**[참고]HTTP METHOD의 알맞은 역할 **

POST, GET, PUT, DELETE 이 4가지의 Method를 가지고 CRUD를 할 수 있다. 

| POST | POST를 통해 해당 URI를 요청하면 리소스를 생성합니다. |

| GET | GET를 통해 해당 리소스를 조회 합니다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가져온다. |

| PUT | PUT를 통해 해당 리소스를 수정 합니다. |

| DELETE | DELETE를 통해 리소스를 삭제합니다. |

다음과 같은 식으로 URI는 자원을 표현하는데에 집중하고 행위에 대한 정의는 HTTP METHOD를 통해 하는 것이 REST한 API를 설게하는 중심 규칙입니다.



4-2 URI 설계시 주의할 점

1) 슬래시 구분자(/)는 계층 관계를 나타내는 데 사용

EX )  * http://restapi.example.com/houses/apartments

         * http://restapi.example.com/animals/mammals/whales


2) URI 마지막 문자로 슬래시(/)를 포함하지 않는다 

: URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라저여한다. REST API는 분명한 URI를 만들어 통신을 해야하기 때문에 혼동을 주지 않도록 URI 경로의 마지막에는 /를 사용하지 않는다.

http://restapi.example.com/houses/apartments/ (X)

http://restapi.example.com/houses/apartments  (0)


3) 하이픈(-)은 URI 가독성을 높이는데 사용 

: URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI경로를 사용하게 된다면 하이픈을 사용해 가독성을 높일 수 있다.


4) 밑줄(_)은 URI에 사용하지 않는다. 

: 글꼴에 따라 다르긴 하지만 밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 한다. 이런 문제를 피하기 위해 밑줄 대신 하이픈을 사용하자(가독성)


5) URI 경로에는 소문자가 적합하다. 

: URI 경로에 대문자 사용은 피하도록 하자. 대소문자에 따라 다른 리소스로 인식하게 된다. RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하기 때문이지요.

(*RFC 3986 is the URI (Unified Resource Identifier) Syntax document)


6) 파일 확장자는 URI에 포함시키지 않는다.

http://restapi.example.com/members/soccer/345/photo.jpg (X)

REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다. Accept header를 사용하도록 합시다.

GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg



4-3 리소스간의 관계를 표현하는 방법

: REST 리소스 간에는 연관 관계가 있을 수 있고 다음과 같은 표현방법으로 사용하자.

/리소스명/리소스 ID/관계가 있는 다른 리소스명

ex) GET : /users/{userid}/devices  (일반적으로 소유 ‘has’의 관계를 표현할 때)

만약에 관계명이 복잡하다면 이를 서브 리소스에 명시적으로 표현하는 방법이 있다. 예를 들어 사용자가 ‘좋아하는’ 디바이스 목록을 표현해야 할 경우 다음과 같은 형태로 사용될 수 있다.

GET : /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)



4-4 자원을 표현하는 Colllection과 Document

: Collection과 Document에 대해 알면 URI 설계가 한 층 더 쉬워집니다. DOCUMENT는 단순히 문서로 이해해도 되고, 한 객체라고 이해하셔도 될 것 같습니다. 컬렉션은 문서들의 집합, 객체들의 집합이라고 생각하시면 이해하시는데 좀 더 편하실 것 같습니다. 컬렉션과 도큐먼트는 모두 리소스라고 표현할 수 있으며 URI에 표현됩니다. 예를 살펴보시도록 하겠습니다.

http:// restapi.example.com/sports/soccer

위 URI를 보시면 sports라는 컬렉션과 soccer라는 도큐먼트로 표현되고 있다고 생각하시면 됩니다. 좀 더 예를 들어보자면

http:// restapi.example.com/sports/soccer/players/13

sports, players 컬렉션과 soccer, 13(13번인 선수)를 의미하는 도큐먼트로 URI가 이루어지게 됩니다. 여기서 중요한 점은 컬렉션은 복수로 사용하고 있다는 점입니다. 좀 더 직관적인 REST API를 위해서는 컬렉션과 도큐먼트를 사용하실 때 단수 복수도 지켜주신다면 좀 더 이해하기 쉬운 URI를 설계하실 수 있을 것 같습니다.
 


5. HTTP 응답 상태 코드

마지막으로 응답 상태코드를 간단히 살펴보도록 하겠습니다. 잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 내어주는 것 까지 포함되어야 합니다. 정확한 응답의 상태코드만으로도 많은 정보를 전달할 수가 있기 때문에 응답의 상태코드 값을 명확히 돌려주는 것은 생각보다 중요한 일이 될 수도 있습니다. 혹시 200이나 4XX관련 특정 코드 정도만 사용하고 계시다면 처리 상태에 대한 좀 더 명확한 상태코드 값을 사용하실 수 있기를 권장하는 바입니다.

상태코드에 대해서는 몇 가지지만 정리하도록 하겠습니다.



200 - 클라이언트의 요청을 정상적으로 수행함

201 - 클라이언트가 어떠한 리소스 생성을 요청, 해당 리소스가 성공적으로 생성됨(POST를 통한 리소스 생성 작업시)


400 - 클라이언트의 요청이 부적절 할 경우 사용하는 응답 코드

401 - 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을때 사용하는 응답 코드 (로그인 하지 않은 유저가 로그인했을 때 요청 가능한 리소스를 요청했을 때)

403 - 유저 인증상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용하는 응답 코드 (403 보다는 400이나 404를 사용할 것을 권고. 403자체가 리소스가 존재한다는 뜻이기 때문에)

405 - 클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드


301 - 클라이언트가 요청한 리소스에 대한 URI가 변경 되었을때 사용하는 응답 코드 (응답시 Location header에 변경된 URI를 적어 줘야 한다.

500 - 서버에 문제가 있을 경우 사용하는 응답 코드


[ 글을 마치며 ]

그래서 'REST API가 정확히 뭐 어떤 거야?'라고 다시 묻는 다면 'HTTP METHOD와 자원을 표현하는 URI를 이용해 서비스의 데이터에 접근하는 것' 라고 제 나름의 정의를 내려보았습니다. 물론 비전공자인 친구에게는 추가적인 설명이 필요할 것 같습니다. 


RESTFul한 API를 설계하실 때 도움이 될 만한 내용들을 제 나름의 우선순위를 가지고 정리해 보았습니다. 정리를 하면서 다시 한 번 느낀 것은 정확히 알지 못하면 '설명할 수 없다'는 것입니다. 누군가가 그런 말을 하였습니다. '당신이 어떤 것을 할머니에게 설명해 주지 못한다면, 그것은 진정으로 이해한 것이 아니다.' 저 문구를 항상 가슴 깊이 새기고 앞으로 무엇인가 새로운 지식을 학습해 실무에 적용할 때에도 '대충'이 아닌 '정확한 이해'를 바탕으로 문제를 해결해 나가도록 해야겠다'는 다짐과 함께 글을 마무리 짓도록 하겠습니다.


마지막으로 REST API는 정해진 명확한 표준이 없기 때문에 REST API를 사용함에 있어 '무엇이 옳고 그른지'가 아닌 개발하는 서비스의 특징과 개발 집단의 환경과 성향 등이 충분히 고려되어 설계되어져야 할 것입니다

 

 

긴 글 읽어주셔서 감사합니다.


[ Reference ]

- 일관성 있는 웹 서비스 인터페이스 설계를 위한 REST API 디자인 규칙(한빛미디어)

https://ko.wikipedia.org/wiki/REST

http://blog.remotty.com/blog/2014/01/28/lets-study-rest/

https://yangbongsoo.gitbooks.io/study/content/restc758_c774_d574_c640_c124_acc4.html

http://spoqa.github.io/2012/02/27/rest-introduction.html


#NHN엔터테인먼트가 만드는 IT 서비스를 소개하고, 개발 경험을 공유하는 기술 커뮤니티 이고 해당 페이지에 게시한 글입니다.

많은 구독부탁드립니다:)

https://www.facebook.com/toast.nhnent/?fref=ts 


반응형
반응형


 안녕하세요. 오늘은 저번 정리 PART.1에 이어 정리를 해보도록 하겠습니다.


[ 403 Forbidden ]

 403이 발생한 원인으로는 파일 시스템의 퍼미션이 부여되지 않은 경우와 액세스 권한에 문제(허가되지 않은 송신 IP 주소의 액세스 등) 가 있는 것을 예로 들 수 있다.

-> 실제로 현업에서 API 통신간 자주 보는 상태 코드이며 보통은 ACL문제라고 볼 수 있다.


[ 503 Service Unavailable ]

 이 리스폰스는 일시적으로 서버가 과부하 상태이거나 정검중이기 때문에 현재 리퀘스트를 처리할 수 없음을 나타낸다. 이 상태가 해소되기까지 시간이 걸리는 경우에는 Retry-After 헤더 필드에 따라 클라이언트에 전달하는 것이 바람직하다.


[ 프록시 ]

 서버와 클라이언트의 양쪽 역할을 하는 중계 프로그램으로, 클라이언트로부터의 리퀘스트를 서버에 전송하고, 서버로부터의 리스폰스를 클라이언트에 전송한다.

클라이언트 <-> 프록시 서버 <-> 오리진 서버(Origin Server, 리소스 본체를 가진 서버)

프록시 서버를 사용하는 이유는 캐시를 사용해서 네트워크 대역 등을 효율적으로 사용하는 것과 조직 내에 특정 웹 사이트에 대한 액세스 제한, 액세스 로그를 획득하는 정책을 지키려는 목적으로 사용하는 경우가 있다.


[ 프록시 사용 방법 2가지, 캐싱 프록시(Cashing Proxy)/투명 프록시(Transparent Proxy) ]

 캐싱 프록시 (Cashing Proxy) : 프록시에 다시 같은 리소스에 리퀘스트가 온 겨우, 오리진 서버로부터 리소스를 획득하는 것이 아니라 캐시를 리스폰스로서 되돌려 주는 타입의 프록시

 투명 프록시 (Transparent Proxy) : 리퀘스트와 리스폰스를 중계할 때 메시지 변경을 하지 않는 타입의 프록시, 반대로 메시지에 변경을 가하는 타입의 프록시를 비투과 프록시라고 한다.


[ 게이트웨이 ]

 게이트웨이의 동작은 프록시와 매우 유사하나 게이트웨이의 경우에는 그 다음에 있는 서버가 HTTP 서버 이외의 서비스를 제공하는 서버가 된다.

클라이언트 <-(HTTP 통신) -> 게이트웨이 <-(HTTP 프로토콜 이외의 통신) -> HTTP이외의 서버

두 컴퓨터(노드-node라고도 함)가 네트워크 상에서 서로 연결되려면 동일한 통신 프로토콜(protocol, 통신 규약)을 사용해야 한다. 따라서 프로토콜이 다른 네트워크 상의 컴퓨터와 통신하려면 두 프로토콜을 적절히 변환해 주는 변환기가 필요한데, 게이트웨이가 바로 이러한 변환기 역할을 한다. 한국인과 미국인 사이에 원활한 의사소통을 위해 통역사를 두는 것과 동일하다 

자세한 설명 참고 : http://it.donga.com/6744/


[ 캐시(Cache) ]

 캐시는 프록시 서버와 클라이언트의 로컬 디스크에 보관된 리소스의 사본을 가리킨다. 캐시를 사용하면 리소스를 가진 서버에 액세스를 줄이는 것이 가능하기 때문에 통신량과 통신 시간을 절약할 수 있다. 캐시 서버는 프록시 서버의 하나로 캐싱 프록시로 분류되며 캐시 서버의 장점은 같은 데이터를 몇 번이고 오리진 서버에 전송할 필요가 없다는 것이다. (클라이언트는 네트워크에서 가까운 서버로부터 리소스를 얻을 수 있고 서버는 같은 리퀘스트를 매번 처리하지 않아도 된다)


[ 클라이언트에 존재하는 캐시 ]

 캐시 서버만 캐시를 가지고 있는 게 아니라 클라이언트가 사용하고 있는 브라우저에서도 캐시를 가질 수 있다. IE에서 클라이언트가 보존하는 캐시를 인터넷 임시 파일이라고 부른다. 브라우저가 유효한 캐시를 가지고 있는 경우, 같은 리소스의 액세스는 서버에 액세스하지 않고 로컬 디스크로부터 불러 온다.


오늘은 여기까지 정리하도록 하겠습니다. 뭐든 배울 수록 배워야될게 더 생겨나가는 이 느낌. 정말 공부는 끝이 없을 것 같습니다.





반응형
반응형

 안녕하세요. 오늘은 전에 읽었던 '그림으로 배우는 HTTP&NETWORK BASIC'이라는 책을 간단히 제가 몰랐거나 나중에 다시 한 번 상기가 필요한 내용들로 정리해보려고 합니다. 아무래도 웹 개발을 하다보니 네트워크 지식들이 필요할 때가 많은데요. 중요한 내용을 바탕으로 쉽게 그림으로 잘 설명되어 있는 책을 골라 읽어보았는데 생각보다 괜찮네요. 기본적인 네트워크 지식이 필요하신 분들에게도 좋은 책이 될 것 같네요. 아무래도 제 주관적으로 중요하다 싶은 내용이나 나중에 한 번 더 봐야 될 부분들에 대해서 정리가 될 것 같은데 보시고 괜찮으시다면 책을 사셔서 보시는걸 추천 드리겠습니다.

[ TCP/IP 계층화 ]
-TCP/IP는 '애플리케이션 계층', '트랜스포트 계층(TCP)', '네트워크 계층(IP)', '링크 계층' 이렇게 총 4계층으로 나뉘어 있다.
> 계층화의 메리트는 인터넷이 하나의 프로토콜로 되어 있다면 어디선가 사양이 변경되었을 때 전체를 바꾸지 않으면 안되지만, 계층화되어 있으면 사양이 변경된 해당 계층만 바꾸면 됩니다.

[ 패킷 ]
-패킷이란 전송하는 데이터의 최소 단위 입니다.

[ IP, MAC ]
-IP(Internet Protocl)의 역할은 개개의 패킷을 상대방에게 전달하는 것. 상대방에게 전달하기까지 여러 요소가 필요한데 그 중에서도 IP와 MAC(Media Access Control Address)라는 요소가 중요하다.
IP주소는 각 노드에 부여된 주소를 가리키고 MAC 주소는 각 네트워크 카드에 할당된 고유의 주소이다. IP주소는 변경 가능하지만 기본적으로 MAC 주소는 변경 할 수 없다.

[TCP, Three way handshaking]
-TCP(Transfer Control Protocol)는 대용량의 데이터를 보내기 쉽게 작게 분해하여 상대에게 보내고, 정확하게 도착했는지 확인하는 역할을 담당한다. TCP는 상대에게 확실하게 데이터를 보내기 위해 "쓰리웨이 핸드셰이킹(three way handshaking)"이라는 방법을 사용하고 있는데 이 방법은 패킷을 보내고 나서 바로 끝내는 것이 아니라, 보내졌는지 여부를 상대에게 확인하러 간다. 이것은 'SYN'와 'ACK'라는 TCP 플래그를 사용한다. 송신측에서는 최초 'SYN'플래그로 상대에게 접속함과 동시에 패킷을 보내고, 수신측에서는 'SYN/ACK' 플래그로 송신측에 접속함과 동시에 패킷을 수신한 사실을 전한다. 마지막으로 송신측이 'ACK' 플래그를 보내 패킷 교환이 완료되었음을 전한다.

[ HTTP, STATLESS PROTOCOL ]
-HTTP는 상태를 계속 유지하지 않는 스테이트리스(stateless)프로토콜로 리퀘스트와 리스폰스를 교환하는 동안에 상태를 관리하지 않는다. HTTP에서는 새로운 리퀘스트가 보내질 때 마다 새로운 리스폰스가 생성된다. 프로토콜로서는 과거의 리퀘스트나 리스폰스 정보를 전혀 가지고 있지 않다. 이는 많은 데이터를 매우 빠르고 확실하게 처리하는 범위성(scalability)을 확보하기 위해서 이와 같이 간단하게 설계되어 있는 것이다.

[ 지속연결, 파이프라인화 ]
-HTTP/1.1와 일부 HTTP/1.0에서는 TCP 연결 문제를 해결하기 위해 지속연결(Persistent Connections)이라는 방법을 고안하였다.  지속 연결의 특징은 어느 한 쪽이 명시적으로 연결을 종료하지 않는 이상 TCP 연결을 계속 유지한다. 지속 연결은 여러 리퀘스트를 보낼 수 있도록 파이프라인(HTTP pipelining)화를 가능하게 한다. 파이프라인화에 의해서 이전에는 리퀘스트 송신 후에 리스폰스를 수신할 때까지 기다린 뒤에 리퀘스트를 발행하던 것을, 리스폰스를 기다리지 않고 바로 다음 리퀘스트를 보낼 수 있게 되었다. 지속 연결 < 파이프라인화(리퀘스트 수가 늘어날 수록 현저한 차이)

[ STATELESS PROTOCOL 이점 ]
-상태를 유지하지 않는다는 점에서 서버의 CPU나 메모리 같은 리소스의 소비를 억제할 수 있다. 또한, 단순한 프로토콜이기에 HTTP가 다양한 곳에서 이용되는 측면도 있다.

[ 쿠키 - STATELESS PROTOCOL 문제 해결 ]
-쿠키는 리퀘스트와 리스폰스에 쿠키 정보를 추가해서 클라이언트의 상태를 파악하기 위한 시스템이다.

[ 인코딩으로 전송 효율을 높이다 ]
-HTTP로 데이터를 전송할 경우 그대로 전송할 수도 있지만 전송할 때에 인코딩을 실시함으로써 전송 효율을 높일 수 있다. 전송할 때 인코딩을 하면 다량의 액세스를 효율 좋게 처리할 수 있다. 단지, 컴퓨터에서 인코딩 처리를 해야 하기 때문에 CPU 등의 리소스는 보다 많이 소비하게 된다.

[ 레인지 리퀘스트 (Range Request) ]
-다운로드 중 커넥션이 끊어지게 되면 처음부터 다시 다운로드를 해야하는 문제를 해결하기 위해 일반적인 리줌(resume)이라는 기능이 필요하게 되었다. 리줌을 통해 이전에 다운로드를 한 곳에서 부터 다운로드를 재개할 수 있다. 이 기능 실현을 위해서는 엔티티의 범위를 지정해서 다운로드를 할 필요가 있다. 이와 같이 범위를 지정하여 리퀘스트 하는 것을 레인지 리퀘스트라고 부른다.

[ 콘텐츠 네고시에이션 ]
- 서로 다른 언어를 주로 사용하는 브라우저가 같은 URI에 액세스할 때에 각각 영어판 웹 페이지와 한국어판 웹 페이지를 표시하는 구조를 콘텐츠 네고시에이션(Content Negotiation)이라고 부른다.
서버 구동형 네고시에이션(서버 측에서 리퀘스트 헤더 필드의 정보를 참고해서 자동적으로 처리하는 방식)과 에이전트 구동형 네고시에이션(브라우저에서 표시 된 선택지 중에서 유저가 수동으로 선택하는 방법)이 있다.

오늘 포스팅은 여기까지 하도록 하겠습니다. :)



반응형

+ Recent posts