프로젝트 진행 ② : 로그인 기능 구현 + 구조 개선
목차
- 시작하며
- 페이지 만들기
- 컨트롤러 구조 변경
- 뷰 리졸버 구조 변경
- DB 연동하기 (mysql)
- 마치며
시작하며
저번 포스팅에서 프로젝트를 생성하고 MVC Model 2, Front Controller 구조를 만들어봤다. 이번에는 계획한 일정 상 가장 처음에 하려고 계획했던 로그인 페이지를 만들고 DB를 이용해서 로그인 기능을 구현한 것을 포스팅하려고 한다.
페이지 만들기
일단 현재까지 만든 페이지는
- 첫 페이지
- 로그인 페이지
- 아이디 찾기 페이지
- 비밀번호 찾기 페이지
이렇게고 메인 페이지는 ui를 완벽하게는 아니지만 로그인 후 보여줄 화면으로 간단하게 만들어두었다.
컨트롤러 구조 변경
지금부터 이야기할 내용은 저번 포스팅을 보면 쉽게 이해될거라고 생각한다.
기존에는 IController Interface -> implController Class 와 같이 단순한 형태의 상속 구조였다. 처음에 이렇게 생각한 이유는 디스패쳐 서블릿에서 컨트롤러 정보를 request uri 정보를 기준으로 controller class를 불러올 때, 어떤 컨트롤러가 불려올지 모르는 상태이기 때문에 Controller를 한 번 추상화해서 동일한 메서드를 실행하여 뷰 이름을 얻기 위함이었다.
그런데 페이지를 만들고나서 생각해보니 로그인이나 여타 다른 기능에서 요청 메서드(request Method)가 여러 개로 나뉠 수가 있었다. 메서드가 나뉘는데 기존 구조를 계속 사용하자니 Controller 내부에서 if 문이나 switch 문을 사용해 분기를 나누고 메서드별 분기처리를 해야했다.
물론 '분기처리를 해도 되긴 되겠다' 라는 하지 않은 것은 아니다. 그러나 이렇게 되면 컨트롤러를 추가할 때마다 메서드별 분기처리 구문을 반복해서 사용해야하는 문제가 있었다.
물론.. 단순히 뷰 화면만 보여주는 페이지도 존재하겠지만 내 생각엔 이 구조를 만들어두지 않고 개별로 분기처리를 하게되면 실수 가능성도 높아질 것 같고, 가독성도 떨어질 것같은.. 뭔가 경험적으로 이런 구조는 피해야겠다 라는 생각이 들었다.
그래서 바뀐 구조는 IController Interface -> ControllerTemplete Abstract Class -> implController Class 이다. 우선 이름을 ControllerTemplete으로 명명한 이유는 메서드별로 분기처리를 해야하지만, 디스패쳐 서블릿에선 execute() 메서드 한 개로 통일실행을 해야 한다고 생각했기 때문이다. 그래서 템플릿 메서드(Templete Method) 패턴을 사용하기로 했고 보통 디자인 패턴을 사용한 클래스는 클래스 네이밍 시 패턴 이름을 붙힌다. 패턴에 대해서는 나중에 따로 포스팅을 하려고 한다.
뷰 리졸버 구조 변경
기존에 뷰 리졸버는 컨트롤러(핸들러)로부터 얻어온 뷰 페이지 이름을 얻어 실제 경로로 변환하는 용도로 사용하고 있었다. 용도가 바뀐 것은 아니지만 원래 사용자로부터 요청(request)가 들어올 때마다 생성해서 사용했었다.
결론적으로는 생성하는 타이밍을 디스패쳐 서블릿(Dispatcher Servlet)의 service() 메서드가 아닌 init() 메서드 내부로 옮겼다. 이유는 두 가지 정도 있다.
- 유저가 어떠한 요청을 할 때마다 new ViewResolver()를 하는 비용을 줄이기 위함
- 전역 변수처럼 사용하기 위함.
기존에는 존재하지 않는 요청을 하면 web.xml 설정에 의해 url-pattern을 "/"으로 인식하여 첫 페이지가 반환되는 현상이 있었다. 이 것을 페이지가 존재하지 않는다는 별도의 페이지를 만들어서 pageNotFound.jsp 페이지를 반환해야 했다.
그리고 매번 요청이 올 때마다 파일을 탐색하는 것은 비효율적이기에 Map<> 맴버변수를 만들고 ViewResolver Class를 전역 변수화 하여 이미 방문했던 페이지는 존재하는 페이지이기 때문에 파일을 탐색하지 않도록 구조를 변경하였다.
DB 연동하기 (mysql)
페이지를 만들었으니 로그인 기능을 구현하기 위해 Mysql Dependency를 추가했다.
메이븐 pom.xml 작성법에 대해서는 여기서 자세하게 다룬 적이 있다.
그 후 LoginDao Class를 만들어서 로그인을 위해 DB에 접속하는 구문을 작성했다.
위 로직을 LoginController에서 사용할 수 있게 아래처럼 작성했다.
이 로직을 작성하면서 고민 중인 것이 두 가지 있다.
- Connection, Statememt, ResultSet 객체를 사용함에 있어 반복되는 코드를 줄일 수 없을까?
- 메인 페이지로 넘어가면 로그인이 완료되기 전과 후로 나누어 서비스를 제공해야 하는데, 그럼 필연적으로 브라우저에서 제공하는 뒤로가기 기능을 막아야 할 때가 있지 않을까?
위 두 가지는 조금 더 고민해보고 프로젝트가 진행되면서 해결되면 이에 대해서 포스팅하려고 한다.
마치며
솔직히 처음에는 jsp 페이지 만들고 프론트 부분은 부트스트랩 프레임워크를 익히면서 사용하느라 꽤 시간이 걸렸지만, 쓰다보니 뭔가 익숙해진 것도 있고 js나 css도 아예 모르지는 않기 때문에 뷰 페이지를 만듦에 있어 속도가 늘고있어서 괜찮았다^^
부족하거나 궁금한 점은 댓글 남겨주세요!! 감사합니다!!