2차 프로젝트 - 마무리 단계
프로젝트 링크 : https://github.com/LuiGee3471/BitCampProject2nd
금, 토, 일 3일 동안 계속 붙잡은 끝에 슬슬 마무리가 되어가고 있습니다. 내일 정도에는 어쩌면 세세한 디테일을 잡는 단계로 들어갈 수 있겠네요. 3일치다 보니 까먹은 것도 많고 할 말도 많은데 이것저것 정리해보겠습니다.
1. 서브쿼리의 악몽
SQL을 배울 때 SQL의 꽃이라고 배웠던 서브쿼리. 사실 그동안은 딱히 쓰지 않았는데 게시판 페이지 처리가 생기면서 서브쿼리를 써야 하는 상황이 찾아왔습니다. 바로 rownum 때문이었죠. 오라클과 달리 MySQL은 직접 제공해주는 기능은 아닙니다만 변수로 비슷한 활용을 할 수 있는데 결국 얘도 서브쿼리로 일단 표를 하나 만든 다음에 붙여주는 건 똑같았습니다. 사실 처음 배울 때는 아니 왜 이렇게 하지 싶었지만 만들어진 표에 붙는 것이다라고 이해하고 나니 알겠더라고요. 그래서 SQL문이 엄청 복잡해졌습니다.
사실 복잡하다고 해도 이 SQL문을 작성한다고 꼬이고 그랬던 건 없어서 힘들지는 않았는데 문제는 이걸 Java에 가지고 오니 그때부터 복잡해져서 좀 지쳤었습니다. 띄어쓰기가 안됐네, 쉼표가 없네 하면서 계속 에러를 내는 건 애교고요. 가져오는 컬럼도 많으니 일일이 데이터를 넣어주는 것도 일이었습니다. (스프링은 이런걸 쉽게 해준다는데 지금은 서블릿과 JSP만 활용하고 있습니다. 기대되네요!) 복잡해졌다고는 해도 사실 다시 보면 그 정도는 아닌 것 같은데 어디까지 복잡해질 수 있나 궁금하네요.
그리고 변수 설정. set @rownum:=0으로 시작했는데 지금은 필요한 곳에만 쓴 것이라 이론도 모르고 그냥 가져왔는데요. 이건 궁금하네요. 어떤 식으로 활용할 수 있을지 여유가 되면 알아보고 싶습니다.
2. Font Awesome
순수 CSS만 쓰고 있다고 했습니다만, 사실 Font Awesome은 사용하고 있습니다. 조원 한 명이 개인 프로젝트에서 쓸 때 괜찮았다고 해서 도입했는데 일단 결론부터 말하면 대만족입니다. 쓰기 쉽고, 커스터마이징도 쉽고, 사이트에도 잘 어울리니 더 좋을 수 있을까요. 가장 맘에 드는 것은 그냥 글씨처럼 다룰 수 있다는 점이었습니다. 크기도 다양하게 지원해주고 색깔도 원하는 대로 사용할 수 있으니 많이 사용은 안했지만 들어간 곳마다 깔끔한 아이콘이 있어서 만족스럽네요.
사실 처음엔 Font Awesome이란 이름 때문에 글꼴 제공 사이트인가해서 그럼 한국어 위주인 우리한테는 별로 못쓰겠다 싶었네요. 아이콘 제공이라는 것을 알았으니 이번은 물론이고 다음에도 많이 활용할 수 있을 것 같습니다.
3. JSP에서 JavaScript 사용
사실 이건 쓰면서도 아직도 신기합니다. 다른 두 언어가 결국은 HTML에서 만나서 서로 소통이 되다니요. 스크립틀릿이나 EL-JSTL로 사용한 표현이 그대로 JavaScript의 변수로 들어가는 것은 정말 엄청난 일인 것 같습니다. 다른 기술들은 방법은 좀 다르겠지만 이렇게 하나의 작업에 여러 언어가 쓰일 수 있다는 것을 느끼고 있습니다.
아무튼 중요한 것은 JavaScript 파일을 JSP 안에 넣지 않고 별도로 분리하고 싶었습니다. JSP 표현이 있는 그대로 복사해서 가져왔는데 그러고 나니까 인식을 못해서 열심히 분리 다 해놨는데 순간적으로 막막해졌었죠. 찾아보니 불러오는 순서가 있더라고요. HTML을 먼저 불러오고 분리한 JavaScript는 나중에 불러오고 등등. 아무튼 결론은 JSP 처리가 더 빠르기 때문에 나중에 오는 외부 JavaScript 파일의 JSP 표현은 인식을 못하고 이상한 표현이 되어버린 것이었습니다. 결국 이 문제는 <script> 태그를 만들고 거기다 변수만 전역으로 선언해주고 바로 아래 외부 JavaScript 태그를 추가해주는 방식으로 진행했습니다.
해결은 했지만 이러고 나니 왜 JavaScript에서 전역 변수가 위험한지 깨달았습니다. 다른 블럭에 선언해도 이렇게 쓸 수 있으니 다른 파일끼리 변수명이라도 겹쳤다가는 어떤 혼란이 일어날지.... 그동안은 약간 Java처럼 계속 쓸 변수는 미리 다 선언해놓고 했는데 조금 조심해야겠습니다.
<script>
const currentPage = <%=request.getAttribute("currentPage")%>;
const option = "<%=request.getAttribute("option")%>";
const boardType = <%=request.getAttribute("boardType")%>;
const word = "<%=request.getAttribute("word")%>";
</script>
<script src="<%=request.getContextPath()%>/js/boardlist.js"></script>
이런 식으로 구현했습니다. JavaScript에서는 전역 변수라면 다른 태그에 있는 애들과도 친구가 될 수 있습니다.
4. 완전히 실패한 DTO, DAO 설계
처음부터 나오는 이야기지만 진짜 크게 실패해서 여기는 너무 아쉽네요. 너무 단순한 함수들만 생각했습니다. 사실상 처음 만들어놓은 함수들은 사용을 하지 않고 새로운게 필요하면 계속 만들어서 쓰고 있습니다. 그러다보니 좀만 수정하면 하나의 함수로 parameter만 다르게 해서 사용할 수 있는 함수도 많아 보이고 자꾸 DTO에는 이것 저것 넣고 싶고 하네요. 계속 새로 만들다보니 작업 속도도 당연히 저하 ㅠ.... 다음에는 DB를 먼저 만들고 select를 좀 미리 테스트해보면서 가져올 만한 데이터는 미리 DTO, DAO에 포함시켜보는 건 어떨지 생각해봐야겠습니다.
5. Exception 대체 어디서 던지나
사실 이번엔 throws 를 좀 써보고 싶어서 가장 마지막에 실행하는 곳에서 예외 처리를 했는데 이러고 나니 오류가 나서 작업을 했는데 애먼 멀쩡한 함수를 고치고 있고 진짜 틀린 애가 무엇인지 모르는 상황이 만들어졌습니다.
코드가 죄다 try-catch로 도배되는 것은 싫은데 그러니 또 이런 상황이 만들어지고 어떻게 할지 모르겠네요. 어차피 자동 완성도 잘 되는데 굳이 피해갈 이유는 없을 것 같기도 하고요.
6. DB 내보내기 기능
이런게 있겠지 싶었는데 굉장히 쉽게 되어있더라고요. 그냥 필요한 것 체크하고 버튼 하나 클릭하면 나중에 이 SQL문 쓰세요. 하고 쭈욱. 다만, 참조 키 등 순서가 중요할 때가 있는데 그런 것 없이 테이블 별로 SQL만 만들어주기는 하더라고요. 그런 것은 조금 아쉽습니다. 그래도 이것 덕분에 주말에도 편하게 작업할 수 있었으니 다행입니다.
7. 페이지 처리
게시판의 꽃이라 하던가요. 페이지 처리에 꽤 오랜 시간이 잡아먹혔습니다. 그래도 어떻게 해낸 느낌이기는 한데 정말 아무 문제 없을지는 모르겠습니다. 여러 단계가 있는데 우선 페이지 수 구하기. 이건 간단한 수학이니까 쉽게 했습니다.
int page = (post % 20 == 0) ? (post / 20) : (post / 20 + 1);
글 20개가 한 페이지에 들어가는 게시판이기 때문에 이렇게 구현. post는 전체 글의 수입니다. 보기 좋게 삼항연산자를 사용하면 왠지 엄청 고급 기술을 사용한 것 같아서 뿌듯합니다.
그 다음에는 페이지 이동 버튼입니다. 총 페이지 수와 현재 페이지 수에 따라 바뀌게 해야 했죠.
int totalPages = (int) request.getAttribute("pages"); // 총 페이지 수
int currentPage = (int) request.getAttribute("currentPage"); // 현재 페이지 번호
int startPage = 1; // 페이지에서 표시될 가장 앞 페이지 번호
if (currentPage >= 4) {
if (currentPage % 3 == 1) {
startPage = currentPage;
} else if (currentPage % 3 == 2) {
startPage = currentPage - 1;
} else {
startPage = currentPage - 2;
}
}
int endPage = 0; // 페이지에서 표시될 가장 뒤 페이지 번호
if (totalPages <= 3) {
endPage = totalPages;
} else {
if (totalPages - startPage >= 3) {
endPage = startPage + 2;
} else {
endPage = totalPages;
}
}
% 연산자는 정말 많은 것을 해주는 연산자라고 생각합니다. 새삼 늘 모티베이션을 주시는 이고잉님의 말씀도 기억나네요. '쉬운 것이라고 중요하지 않은 것은 시험일뿐, 현실에서는 쉽고 자주 쓰는 것이야말로 가장 중요한 것이다'. 나머지라는 분수와 소수만 배워도 금방 안쓰는 개념이 여기서는 참으로 유용하게 쓰입니다. totalPages는 그냥 DB에서 count 함수로 가져와서 전달해줬습니다. 아무튼 이걸 활용하니 페이지 버튼이 더 필요하면 생기고 필요 없으면 생기지 않습니다. 저 두 숫자를 이용해 위에 나오는 '다음 >' 버튼이나 '< 이전' 버튼도 만들었습니다.
아무튼 거의 디버깅에 접어들 단계같습니다. 댓글이나 글에 아무 것도 작성을 안해도 작성이 된다거나 하는 문제들도 있고 아직도 많습니다. 다 끝내고 에러 페이지를 만들 단계쯤 들어가면 감개무량할 것 같네요.