sitelink1 | |
---|---|
sitelink2 | |
sitelink3 | |
sitelink4 | |
sitelink5 | |
sitelink6 |
처음 자바를 배우면서 만들었던 게시판 소스에 적용했던 기법이며 지금까지 줄 곧 써왔던 방법이다.
아마 모든 초보개발자들이 즐겨 사용하는 방법이 아닐까한다.
물론 소스코드까지 자세히 기억해 낼 수는 없지만 모든 프로그래밍이라는게 원리를 알고 나면 이미 머리속에는 코드가 만들어지는거니까.
원리는 다음과 같다.
기본적으로 하나의 테이블에서 레코드 목록을 가져오든 여러 테이블을 조인하여 레코드 목록을 가져오든 일단은 레코드 목록부터 시작이다.
하나의 리스트가 있고 그 리스트를 가공하여 원하는 형태로 화면에 출력하는데에는 몇가지 조건들이 따라 붙을 수 있다.
가령 검색을 하여 원하는 부분들을 추출해낸다던지, 소팅을 하여 특정 컬럼에 맞게 정렬을 한다던지, 페이징을 적용하여 리스트의 특정 부위를 잘라내는 것 등등.
그리고 이런것들은 쿼리를 생성하는데에 비슷한 유형의 규칙을 만들어낸다.
검색을 위해서는 조건절(Where)가 필요해지고, 정렬을 위해서는 소팅(Order by)가 필요해진다. 그리고 페이징을 위해서는 범위 검색문(Where ~ Between ~)이 필요하다.
웹서버에서는 이러한 쿼리들을 적당한 부분에 끼워 넣어 만들고 데이터베이스에 질의하면 원하는 형태의 리스트로 가공되어 웹서버로 전달받게 된다.
보름전쯤 NEC로부터 게시판을 출력하는데에 웹서버의 부하가 너무 심해서 리스트 화면 부분을 손봐달라는 의뢰를 받았다.
그리고 이미 해당되는 로직과 데이터베이스를 분석해봤던 나는 그게 참 당연한 결과라는 걸 알고 있었다. (하지만 이 일을 내가 할 줄이야...)
어쩔 수 없이 이번 유지보수를 담당하고 있는 나는 이 엉망진창의 소스들과 테이블 스키마들로부터 도망갈 길이 없다.
NEC에 구축되어 있는 시스템에서는 웹서버가 데이터베이스로부터 레코드 리스트 전체를 전달받아 세션에 담아두고 이를 프로그램적으로 페이징을 하고 있었다.
게다가 이 시스템은 XML과 XSLT를 이용하여 일람화면을 만들어내는 시스템이기에 리스트 페이지 하나를 출력하기 위해 드는 비용이 그리 만만치 않은 시스템이었다.
그렇다고 해서 하루에 조회수가 수만건 이상으로 I/O가 빈번히 일어나는 시스템이 아니었지만 시간이 지날수록 데이터가 쌓여감에 따라 웹서버의 부담이 가중될 수 밖에 없었다.
이러한 시스템에서 웹서버의 메모리에서 수행하던 페이징을 DB에서부터 원하는 목록을 가져오는 페이징으로 변환하는데에는 코드상의 수정보다는 쿼리의 수정이 불가피했다.
하지만 기존의 게시판 화면을 가져오는 쿼리에서는 큼직한 쿼리 2~3개를 JOIN 하고 있었고 테이블은 5~6개를 사용하며 Self조인 Outer조인 참... 다양함이 돋보이는 쿼리였다.
그리고 소스코드에서 단지 쿼리의 라인수만 무려 500라인을 육박하니 이 쿼리를 분석하여 페이징을 적용하기란 내 정력이 아까울정도였다.
다행인것은 이러한 게시판에 새로운 페이징부분을 추가하는데에는 가장 초보적인 방법만으로도 일단은 웹서버의 부담을 덜어줄 수 있을 것이라 생각하였다.
각설하고, 계속해서 이어나가자면
NEC시스템에 구축된 시스템에서 사용하는 무지막지한 쿼리는 페이징이 적용되기 이전의 순수한 리스트를 리턴해 주는 쿼리문이다. (아쉽게도 NEC 쿼리도 성능을 보장할 수 없을정도로 메차쿠차다... ㅜ_ㅜ)
데이터베이스는 오라클 기반이지만 Relationship 이라고는 찾아볼 수 없는 설계형태였기에 이 쿼리를 튜닝한다는 건 나로써는 돈을 다발로 줘도 싫다. 능력도 안되지만 ^^; (그래도 한 1억원이라면...)
어쨌든 이 쿼리로부터 리스트를 돌려받으면 다음과 같은 View 형태가 될거다.
NecListQuery = Select * From NECTAB
내가 할일은 여기에 검색으로 좀 솎아내고, 순서좀 잘 다시 섞고, 페이징으로 반듯하게 잘라내주기만 하면 된다.
그럼 검색으로 솎아내면
SearchQuery = Select * From (NecListQuery) Where 조건1 And 조건2
이런형태가 되고, 여기에 소트부분을 추가해주면
SortQuery = Select * From (SearchQuery) Order by 정렬1, 정렬2
그리고 마지막으로 페이징 추가
PagingQuery = Select * From (SortQuery) Where Rownum Between 시작 and 끝
완성이다.
페이징은 기초적인 방법으로 Rownum을 이용한다.
솔직히 위와같은 쿼리의 결과물에 대해서는 성능을 보장받을 수 없다. 쿼리 자체에 대한 비용이 ... 그냥 많다.
하지만 자바코딩은 반대로 쉬워진다. 그리고 소스코드들을 구조화 할 수 있다.
다행인것은 NEC사람들은 웹페이지의 응답에 대해 매우 관대하다. (10초만에 화면이 뜬다고 해도 좋아해 줄거라 믿는다. 지금은 10분이나 서버가 먹통이 되버리니... )
그들은 시스템의 응답이 더 빠르게 하려면 기존의 데이터를 지우는 방법이 가장 손쉬운 방법이라는 것을 알고 있으며 그것을 선택하고도 남을 사람들이다. ㅡ_ㅡㆀ
효율적인 유지보수 방법을 선택하는데에 있어서 고객의 성향이 참으로 중요해짐을 새삼 느낄 수 있다.