레이블이 Tips인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Tips인 게시물을 표시합니다. 모든 게시물 표시

2008년 10월 6일 월요일

DNS 캐시 디버깅하기

웹 개발이나 서버 관리를 하다 보면 도메인 및 많은 수의 virtual host들을 관리해야 하는 경우가 많은데, 이때 네임서버 설정을 변경해도 바로 반영이 안 되어서 한참 동안 접속이 되는 걸 기다리느라 시간을 허비할 때가 많다. DNS 문제는 인터넷의 발전을 가로막는 장벽이라는 이야기가 있을 정도로 그 갱신 주기와 관리에 관련된 주체들이 많이 얽혀있어 처음 이런 문제를 접하는 사람들의 경우 해결하기가 쉽지 않고, 캐시 갱신으로 인해 갑자기 해결되어도 왜 그런지 이해하지 못하는 경우가 태반이다.

그래서 이 글에서는 DNS 설정을 바꿨을 때 어떻게 하면 빨리 대처할 수 있는지 살펴보기로 한다.

1. 네임서버 자체의 TTL 설정 확인
DNS 관리할 때 사용되는 용어 중 TTL(Time-to-live)이란 것이 있는데, 이것은 네임서버가 해당 도메인에 대한 정보를 얼마나 긴 시간 동안 캐시(임시 보관)하고 있을 것인지 결정한다. 이 값이 길수록 캐시 기간이 길어지므로 새로운 정보로 변경했을 때 그 정보가 적용되기까지 시간이 오래 걸린다. 따라서 테스트용 서버와 같이 자주 변경이 이루어지는 경우 이 값을 비교적 작게 유지하는 것이 좋다.

2. ISP가 제공하는 DNS 서버
회사나 큰 기관에서는 자체 DNS 서버를 이용하기도 하고, 개인사용자들은 KT, 하나로통신, LG파워콤 등 자기가 가입한 인터넷 회선 사업자의 DNS 서버를 이용할 것이다. 네임서버 정보를 수정했다고 해도 이들 서버에 적용되기까지 또 시간이 걸린다. 이것은 TTL 정보뿐만 아니라 각 DNS 서버의 운영 정책 등과도 관련이 있기 때문에 정확히 얼마만큼의 시간이 걸린다고 예측하기는 어려우며 DNS 서버마다 갱신 주기가 달라 어떤 곳에서는 새로 바뀐 주소로 접속이 되고 어떤 곳에서는 예전 주소로 접속되고 이런 현상이 발생하기도 한다.

내가 추천하는 한 가지 방법은 OpenDNS를 이용하는 것인데, 이곳은 캐시 갱신이 비교적 빠른 편이고 갱신이 안 되어 접속에 문제가 생겼을 때 캐시 상태를 확인할 수 있는 페이지로 보내주므로 현재 어떤 상황인지 비교적 투명하게 알 수 있다는 장점이 있다. DNS 서버는 ISP가 제공하지 않는 것을 사용하더라도 보통 별다른 제약이 없기 때문에 이 방법을 가장 추천한다.

3. 자기 컴퓨터의 DNS 캐시
DNS 서버에서도 캐시가 이뤄지지만 각자 사용하는 로컬 컴퓨터의 운영체제에서도 자체적으로 캐시가 이루어진다.

 운영체제 로컬 캐시 갱신 명령 수동 mapping 파일
 MS Windows ipconfig /flushdns {SystemDir}\drivers\etc\hosts
 Linux /etc/init.d/nscd restart /etc/hosts
 MacOS X (10.4 이전) lookupd -flushdns /etc/hosts
 MacOS X (10.5 이후) dnscacheutil -flushdns  /etc/hosts

여기서 주목할 것은 etc/hosts 파일인데(심지어 윈도우도 거의 같은 디렉토리/파일명에 똑같은 포맷을 가지고 있다), 이 파일에 "IP주소 도메인" 형태로 한줄씩 수동 mapping을 추가할 수 있다. 이렇게 하면 실제 인터넷 상의 DNS 서버를 이용하지 않고 해당 IP 주소로 자기 PC 레벨에서 무조건 연결시켜주므로 DNS 서버가 갱신되지 않을 때 재빨리 테스트해보기 위한 용도로 적합하다.

거의 모든 운영체제에서 제공하고 있는 네임서버 테스트 용도의 nslookup 명령 결과에 영향을 주는 부분은 여기까지다.

※ Linux의 경우 배포판마다 캐시 갱신 명령이 다를 수 있음.

4. 웹브라우저 자체의 DNS 캐시
그러나 위의 etc/hosts 파일을 고쳐도 적용되지 않는 경우가 있을 수 있는데, 이것은 웹브라우저 자체가 가지고 있는 캐시 때문이다. -_-; 보통은 웹브라우저를 재시작해도 적용되지만 Firefox처럼 세션을 저장했다가 다시 불러오는 경우 바로 갱신되지 않을 때가 있다.
이럴 땐 웹브라우저의 설정을 직접 건드려주는 방법이 있다.

  • Firefox : about:config에서 network.dnsCacheEntries (캐시 항목 개수), network.dnsCacheExpiration (캐시 기간, 단위: 초) 두 항목을 변경하거나 새로 추가한다. entry 개수가 0이 되면 캐시를 전혀 하지 않지만 복잡한 웹사이트 로딩시 속도가 떨어질 수 있다.
  • Internet Explorer : MSDN 참조

이처럼 살펴본 바와 같이, DNS Cache 문제는 여러 단계에서 영향받을 수 있기 때문에 꼼꼼히 확인해봐야 한다.

2008년 9월 17일 수요일

Gecko와 Webkit의 CSS Transform 테스트

Gecko 엔진에서도 CSS Transform 기능이 추가되었다는 소식을 듣고 테스트해보았다. 특히 나는 CSS에서 left: 50% + 20px;과 같은 다른 단위끼리의 간단한 사칙연산을 지원해주었으면 하는 생각을 가지고 있었고, left 속성과 transform 중 linear traslation을 조합하면 해당 기능을 구현할 수 있으리란 생각이 들었기 때문이다.

직접 간단한 예제를 만들어 테스트해본 결과 예상대로 제대로 동작함을 확인할 수 있었다. 오오 ㅠ_ㅠb

Gecko와 Webkit의 CSS Transform 테스트


일단 transform 속성 중 위치를 변경시키는 translate 자체는 거의 100% 호환되는 듯하나, 불행히도(?) rotate시킬 때 어느 점을 기준으로 하는지는 약간 차이가 있는 것 같다.

실제 테스트 페이지도 따로 볼 수 있도록 만들었다. 여기 클릭.

IE에서도 DXImageTransform.Microsoft.Matrix 필터를 이용해 이런 transform이 가능하기는 한데, 직접 해보니 rotation의 경우 원래 블록이 차지하던 영역 밖으로 벗어나는 부분이 그대로 짤려버려서 매우 보기 흉하고, 특히 직접 회전변환 행렬을 계산해서 넣어줘야 한다는 점이 개발자 입장에서 매우 불편하다.

사실상 두 엔진의 transform 속성이 거의 똑같은 문법으로 동작하는만큼 이 기능이 CSS3 표준에 포함되었으면 좋겠다.

2008년 8월 16일 토요일

HTTP 모델링하기

텍스트큐브닷컴에 글을 쓰는 건 꽤 오랜만인 것 같다;; 그 사이 업데이트도 좀 된 것 같고... 글을 쓰긴 써야 할 것 같아서 요즘 한창 생각하고 있는 주제 중 하나를 써본다. (그래도 '웹'에 관한 블로그라고 했으니 그쪽 관련된 것으로 골랐다-_-)

요즘 스팍스에서 KSearch (가제)라는 카이스트 내부를 대상으로 하는 검색 엔진 프로젝트가 진행 중인데, Lucene과 Python을 기반으로 만들면서 후배 녀석들이 웹브라우저와 통신하는 프론트엔드 서버를 위해 말 그대로 SimpleFramework를 만들어둔 것이 있다. 그쪽을 맡아서 하던 후배가 교환학생(...)을 가버리는 바람에, 또 마침 내가 좀 시간이 생겼기도 하고 해서 내가 그 부분을 맡아서 계속 작업해나가는 중이다. (내가 한 작업으로는 Django의 템플릿 엔진을 떼어와 얹은 것 등이 있다)

앞으로 프론트엔드 전체를 Django로 갈아엎어버릴지까진 모르겠지만 Django의 경우 DB와 반드시 연동되어 돌아가야 하고 그와 관련하여 설정을 별도로 해줘야 하는 등 순수 검색 인터페이스만을 위한 단순 UI 구성에는 귀찮은 면이 있어 초간단 WSGI 인터페이스 wrapper를 만들어 쓰고 있다.

Python에서 사용하는 웹서버 CGI 규격이라고 할 수 있는 WSGI 인터페이스가 어느 정도 기본적인 처리는 해주지만 이것을 좀더 쓰기 편하게 만들려면 역시 HTTP에 대한 이해가 필요하다. 여기서는 HTTP를 다루는 프레임웍을 만들고자 할 때 어떤 점들을 고려하면 좋을지 간단히 써보려고 한다.

Request - Response

웹이라는 건 기본적으로 웹브라우저(client)와 웹서버(server) 사이의 통신에 의해 구현된다. 그 통신 방법은 보통 HTTP라는 프로토콜을 이용한다.

웹브라우저는 웹서버에게 이러이러한 정보를 달라고 요구하거나 웹서버가 어떠어떠한 동작을 해줬으면 하는 request를 보내고, 웹서버는 이를 처리한 후 결과를 response한다. Request의 종류는 몇 가지가 더 있지만 나머지는 잘 쓰이지 않고 보통 GET/POST 두 가지를 사용하며 GET은 어떤 정보 제공을 요청하는 것이고 POST는 웹브라우저가 데이터를 제공하고 그에 대한 처리 결과를 알려달라고 요청하는 것이다.

HTTP의 경우, 일반적으로 한 번의 request-response 쌍이 오가고 나면 연결이 끊어진다. 따라서 로그인과 같은 기능을 구현하려면 여러 client들로부터 날아오는 request들을 각 client 단위로 구분하고 인증할 방법이 필요한데, 이것이 세션과 쿠키이다.

쿠키는 웹서버가 웹브라우저에 뭔가 작은 크기의 정보를 저장할 수 있게 해주는데, request가 들어올 때마다 쿠키를 조회하여 자기가 기록했던 정보를 알 수 있다. 따라서 로그인 인증 과정에서 부여한 (랜덤한) 고유값을 쿠키에 넣어두고 그 고유값과 인증 여부의 mapping을 웹서버가 가지고 있으면 그 client를 로그인 상태로 유지하고 쇼핑몰 장바구니와 같이 계속 가지고 있어야 하는 정보들을 관리할 수 있다.

따라서 모델링에는 Request로 날아온 데이터를 잘 unpack해서 다루기 쉽게 해주는 부분과, session을 관리하고 현재 session이 가지고 있는 데이터를 다룰 수 있게 해주는 부분, response와 그 출력을 작성할 수 있게 해주는 부분들이 포함되어야 한다.

Response의 세분화

그러한 웹서버의 response에는 여러가지 종류가 있는데, HTTP specification을 보면 잘 처리되었음을 알리는 200번대 응답코드와 다른 페이지로 이동하라는 것을 알리는 300번대 응답코드, 요청을 수행할 수 없음을 알리는 400번대/500번대 응답코드가 있다.

가장 많이 사용되는 것은 200 OK, 302 Found, 403 Forbidden, 404 Not Found, 500 Internal Error 정도가 되겠다. 그외 세부적인 코드들도 많이 있지만 보통 이 정도만 알고 있으면 무방하다. OOP 언어를 사용한다면 클래스 상속 정도로 모델링해볼 수 있겠다.

Ajax 처리하기

뭔가 특별하고 새로운 신기술 같아 보일 수도 있는(...) Ajax도 기본적으로 request-response라는 건 똑같은데, 다만 그것이 웹브라우저에서 봤을 때 페이지 이동 없이 javascript를 이용해 문서의 일부분만 갱신하는 형태로 보여진다는 것이 다를 뿐이다. 웹서버 입장에서는 다른 것이 전혀 없다.

디버깅 요소 집어넣기

웹프로그래밍에서 가장 어려운 것은 디버깅이다. 간단한 문제라면 웹출력에 몇 가지 문자열을 더 찍어보는 것으로 해결되겠지만 복잡한 것들은 이런 방식으로는 찾아내기 힘들고, 프레임웍 구조나 사용 환경의 차이에 따라 response 출력 과정에서 중간에 '끼어들어' 문자를 찍는 것 자체가 불가능하거나 매우 까다로울 수도 있다.

Django 디버그 모드 오류 페이지 (ⓒDorkyCute)

위 그림은 Django 프레임웍의 디버그 화면이다. 500 Internal Error를 날리되 거기에 디버깅 정보를 함께 실어준다. 코드가 진행되다가 처리되지 않은 예외가 발생할 경우 이렇게 stack trace와 각 단계에서의 local variable 정보, 에러 메시지와 그 위치 등을 상세하게 표현해주는데, 프레임웍을 설계한다면 디버깅 기능은 반드시 고려해야 할 중요한 요소다.

잡다한 표준들

캐시 제어 및 시간 표현을 위한 RFC 규약들, Form 데이터를 주고받기 위한 인코딩/디코딩 방법, 올바른 MIME-Type 지정하기 정도가 기본적으로 고려되어야 할 부분들이다. 여기에 Django처럼 보다 추상화된 형태의 Form 등을 지원한다면 더 좋을 것이다.

-

뭐 대충 적어봤다. 아는 사람한텐 다 아는 내용일 테지만 나 스스로도 요구사항을 정리하는 관점에서 간단하게 적어보았다. 여기에 부가 기능을 더한다면 표현과 로직을 분리하기 위한 template 엔진이나, DB를 쉽게 다루기 위한 ORM 등이 있을 수 있겠다.