오늘은 종일 기능 구현을 혼자서 해보는 자습 시간을 가졌다.
게시판 MVC 구조에 회원 기능을 합쳐서 로그인한 사용자만 게시판을 이용하게 만들었다.
목차
1 전체 실습 개요
2 BOARD와 MEMBER 테이블
3 BoardDto와 MemberDto
4 BoardDao와 MemberDao
5 BoardService와 MemberService
6 BoardServlet
7 MemberServlet
8 로그인과 세션 처리
9 회원가입과 아이디 중복 체크
10 logininfo.jsp
11 게시판 View 페이지
12 pageContext.request.contextPath
13 오늘 실습의 핵심 정리
1 전체 실습 개요
1) 오늘 실습의 흐름
(1) 게시판과 회원 기능 통합
오늘은 기존 Servlet MVC 게시판 구조에 로그인, 로그아웃, 회원가입, 아이디 중복 체크 기능을 함께 구현했다.
게시판 기능만 따로 동작하는 것이 아니라, 로그인한 사용자만 게시판 목록, 상세 보기, 글쓰기, 수정, 삭제 화면에 접근할 수 있도록 만들었다.
(2) Servlet 기반 MVC 구조
BoardServlet은 게시판 요청을 처리하고, MemberServlet은 회원 관련 요청을 처리한다.
하나의 Servlet이 모든 기능을 담당하지 않고, 게시판 기능과 회원 기능을 나누어 관리했다.
(3) 전체 구조
DTO는 데이터를 담는 객체이다.
DAO는 SQL 실행을 담당한다.
Service는 DAO를 호출하고 Connection, commit, rollback 흐름을 관리한다.
Servlet은 사용자의 요청을 받아 어떤 기능을 실행할지 결정한다.
JSP는 사용자가 보는 화면을 출력한다.
2 BOARD와 MEMBER 테이블
1) BOARD 테이블
(1) 게시글 저장 테이블
BOARD 테이블은 게시판의 글 정보를 저장하는 테이블이다.
글 번호, 작성자, 제목, 내용, 작성일을 저장한다.
(2) NO
NO는 게시글 번호이다.
PRIMARY KEY로 설정되어 게시글 하나를 구분하는 고유한 값으로 사용된다.
(3) WRITER
WRITER는 작성자를 저장하는 컬럼이다.
글 작성 시 반드시 입력되어야 하므로 NOT NULL이 설정되어 있다.
(4) TITLE
TITLE은 게시글 제목을 저장하는 컬럼이다.
게시글 목록과 상세 화면에서 출력된다.
(5) CONTENT
CONTENT는 게시글 내용을 저장하는 컬럼이다.
상세 보기와 수정 화면에서 사용된다.
(6) REGDATE
REGDATE는 게시글 작성일을 저장하는 컬럼이다.
글 작성 시 SYSDATE를 사용해 현재 날짜를 저장한다.
2) SEQ_BOARD
(1) 게시글 번호 자동 생성
SEQ_BOARD는 게시글 번호를 자동으로 증가시키기 위한 시퀀스이다.
INSERT 할 때 SEQ_BOARD.NEXTVAL을 사용해 새로운 글 번호를 만든다.
3) MEMBER 테이블
(1) 회원 정보 저장 테이블
MEMBER 테이블은 로그인과 회원가입에 필요한 회원 정보를 저장하는 테이블이다.
회원 번호, 아이디, 비밀번호, 이름, 전화번호를 저장한다.
(2) MYNO
MYNO는 회원 번호이다.
PRIMARY KEY로 설정되어 회원 한 명을 구분하는 고유한 값이다.
(3) MYID
MYID는 로그인할 때 사용하는 아이디이다.
UNIQUE가 설정되어 있어 같은 아이디를 중복으로 사용할 수 없다.
(4) MYPW
MYPW는 로그인할 때 사용하는 비밀번호이다.
오늘 실습에서는 입력된 비밀번호와 DB에 저장된 비밀번호를 비교해 로그인 여부를 판단했다.
(5) MYNAME
MYNAME은 회원 이름이다.
로그인 후 화면에서 “OO님 환영합니다.”처럼 사용자 이름을 출력할 때 사용한다.
(6) MYPHONE
MYPHONE은 회원 전화번호이다.
UNIQUE가 설정되어 있어 같은 전화번호를 중복으로 사용할 수 없다.
3 BoardDto와 MemberDto
1) BoardDto
(1) 게시글 데이터 전달 객체
BoardDto는 BOARD 테이블의 한 행 데이터를 Java 객체로 담는 클래스이다.
게시글 번호, 작성자, 제목, 내용, 작성일을 하나의 객체로 관리한다.
(2) 사용하는 이유
DB에서 조회한 게시글 정보를 여러 변수로 따로 전달하면 복잡하다.
BoardDto 객체 하나에 게시글 정보를 담으면 DAO, Service, Servlet, JSP 사이에서 데이터를 쉽게 전달할 수 있다.
2) MemberDto
(1) 회원 데이터 전달 객체
MemberDto는 MEMBER 테이블의 한 행 데이터를 Java 객체로 담는 클래스이다.
회원 번호, 아이디, 비밀번호, 이름, 전화번호를 하나의 객체로 관리한다.
(2) 로그인 정보 저장
로그인 성공 시 MemberDto 객체를 session에 저장한다.
이렇게 하면 다른 JSP에서도 로그인한 회원의 이름이나 아이디를 사용할 수 있다.
4 BoardDao와 MemberDao
1) BoardDao
(1) 게시판 DAO 인터페이스
BoardDao는 게시판에서 필요한 DB 기능 목록을 정의한 인터페이스이다.
전체 조회, 상세 조회, 글 작성, 글 수정, 글 삭제 메소드를 선언한다.
(2) SQL 상수
selectAllSql, selectOneSql, insertSql, updateSql, deleteSql을 선언했다.
각 SQL문을 이름으로 구분해 구현 클래스에서 사용할 수 있게 했다.
2) BoardDaoImpl
(1) 게시판 DAO 구현체
BoardDaoImpl은 BoardDao 인터페이스에 정의된 메소드를 실제로 구현한 클래스이다.
PreparedStatement를 사용해 SQL을 실행하고 결과를 반환한다.
(2) selectAll
BOARD 테이블의 전체 게시글을 조회한다.
ORDER BY NO DESC를 사용해 최신 글이 위에 나오도록 정렬한다.
(3) selectOne
글 번호 NO를 기준으로 게시글 하나를 조회한다.
상세 보기나 수정 화면에서 사용된다.
(4) insert
새 게시글을 BOARD 테이블에 추가한다.
작성자, 제목, 내용을 받아 INSERT문을 실행한다.
(5) update
글 번호를 기준으로 제목과 내용을 수정한다.
작성자와 작성일은 수정하지 않는다.
(6) delete
글 번호를 기준으로 게시글을 삭제한다.
삭제 성공 여부를 boolean 값으로 반환한다.
3) MemberDao
(1) 회원 DAO 인터페이스
MemberDao는 회원 기능에 필요한 DB 기능 목록을 정의한 인터페이스이다.
로그인, 아이디 중복 체크, 회원가입 메소드를 선언한다.
(2) loginSql
loginSql은 아이디와 비밀번호가 일치하는 회원을 조회하는 SQL이다.
로그인 성공 여부를 판단할 때 사용한다.
(3) idchkSql
idchkSql은 입력한 아이디가 이미 존재하는지 확인하는 SQL이다.
회원가입 전 중복 체크에 사용한다.
(4) registSql
registSql은 새로운 회원 정보를 MEMBER 테이블에 추가하는 SQL이다.
회원가입 처리에 사용한다.
4) MemberDaoImpl
(1) 회원 DAO 구현체
MemberDaoImpl은 MemberDao 인터페이스를 구현한 클래스이다.
실제 로그인 조회, 아이디 중복 확인, 회원가입 INSERT를 처리한다.
(2) login
입력받은 id와 pw를 조건으로 MEMBER 테이블을 조회한다.
일치하는 회원이 있으면 MemberDto에 회원 정보를 담아 반환한다.
(3) idChk
입력받은 id가 DB에 존재하는지 조회한다.
이미 존재하면 해당 id를 반환하고, 존재하지 않으면 null을 반환한다.
(4) insertMember
회원가입 폼에서 입력한 아이디, 비밀번호, 이름, 전화번호를 MEMBER 테이블에 저장한다.
INSERT 성공 여부를 boolean 값으로 반환한다.
5 BoardService와 MemberService
1) Service 계층의 역할
(1) Service
Service는 Servlet과 DAO 사이에서 DB 작업 흐름을 관리하는 계층이다.
Servlet이 직접 DAO를 호출하지 않고 Service를 거쳐 기능을 실행한다.
(2) 사용하는 이유
Servlet은 요청 처리와 화면 이동에 집중하고, DAO는 SQL 실행에 집중해야 한다.
Service는 그 사이에서 Connection 생성, commit, rollback, close 같은 흐름을 관리한다.
2) BoardServiceImpl
(1) 게시판 Service 구현체
BoardServiceImpl은 게시판 기능의 Service 역할을 한다.
BoardDaoImpl을 이용해 게시글 조회, 작성, 수정, 삭제 기능을 실행한다.
(2) 조회 기능
selectAll과 selectOne은 DB 내용을 변경하지 않는다.
따라서 DAO 호출 후 Connection을 닫고 결과를 반환한다.
(3) 변경 기능
insert, update, delete는 DB 내용을 변경한다.
성공하면 commit하고 실패하면 rollback한 뒤 Connection을 닫는다.
3) MemberServiceImpl
(1) 회원 Service 구현체
MemberServiceImpl은 회원 기능의 Service 역할을 한다.
MemberDaoImpl을 이용해 로그인, 아이디 중복 체크, 회원가입 기능을 실행한다.
(2) 로그인과 아이디 체크
login과 idChk는 조회 기능이므로 commit이나 rollback이 필요하지 않다.
DAO 호출 후 Connection을 닫고 결과를 반환한다.
(3) 회원가입
insertMember는 DB에 회원 정보를 추가하는 기능이다.
성공하면 commit하고 실패하면 rollback한다.
6 BoardServlet
1) BoardServlet의 역할
(1) 게시판 Controller
BoardServlet은 게시판 관련 요청을 처리하는 Servlet Controller이다.
URL은 @WebServlet("/board")로 매핑되어 있다.
(2) command 방식
request.getParameter("command")로 요청 종류를 구분한다.
list, writeform, write, detail, updateform, update, delete 값에 따라 다른 기능을 실행한다.
2) list
(1) 게시글 목록 요청
command가 list이면 service.selectAll을 호출해 전체 게시글 목록을 조회한다.
조회 결과를 request에 list라는 이름으로 저장한다.
(2) boardlist.jsp 이동
RequestDispatcher를 사용해 view/board/boardlist.jsp로 forward한다.
forward를 사용하기 때문에 request에 저장한 list를 JSP에서 사용할 수 있다.
3) writeform
(1) 글쓰기 화면 이동
command가 writeform이면 view/board/boardwrite.jsp로 이동한다.
별도로 전달할 데이터가 없으므로 redirect를 사용한다.
4) write
(1) 글 작성 처리
command가 write이면 form에서 전달된 writer, title, content 값을 받는다.
이 값들을 BoardDto 객체에 담아 service.insert로 전달한다.
(2) 결과 처리
작성 성공 시 “글 작성 성공” 메시지와 목록 이동 URL을 result.jsp로 전달한다.
작성 실패 시 “글 작성 실패” 메시지와 글쓰기 화면 이동 URL을 전달한다.
5) detail
(1) 상세 조회
command가 detail이면 no 값을 받아 해당 게시글을 조회한다.
service.selectOne(no)를 호출해 BoardDto 객체를 가져온다.
(2) 상세 화면 이동
조회 결과를 request에 dto라는 이름으로 저장한다.
view/board/boarddetail.jsp로 forward하여 상세 내용을 출력한다.
6) updateform
(1) 수정 화면 요청
command가 updateform이면 no 값을 받아 기존 게시글을 조회한다.
수정 화면에는 기존 제목과 내용이 필요하기 때문이다.
(2) boardupdate.jsp 이동
조회한 dto를 request에 저장하고 view/board/boardupdate.jsp로 forward한다.
JSP에서는 EL을 사용해 기존 값을 화면에 출력한다.
7) update
(1) 수정 처리
command가 update이면 수정 form에서 전달된 title, content, no 값을 받는다.
이 값들로 BoardDto 객체를 만들어 service.update로 전달한다.
(2) 결과 처리
수정 성공 시 목록으로 이동하도록 처리한다.
수정 실패 시 다시 수정 화면으로 돌아갈 수 있도록 URL을 설정한다.
8) delete
(1) 삭제 처리
command가 delete이면 no 값을 받아 삭제할 게시글을 지정한다.
service.delete(no)를 호출해 DB에서 게시글을 삭제한다.
(2) 결과 처리
삭제 성공 시 목록으로 이동한다.
삭제 실패 시 다시 상세 페이지로 이동하도록 처리한다.
7 MemberServlet
1) MemberServlet의 역할
(1) 회원 Controller
MemberServlet은 회원 관련 요청을 처리하는 Servlet Controller이다.
URL은 @WebServlet("/member")로 매핑되어 있다.
(2) 담당 기능
로그인, 로그아웃, 회원가입 화면 이동, 아이디 중복 체크, 회원가입 처리를 담당한다.
2) login
(1) 로그인 요청
index.jsp에서 아이디와 비밀번호를 입력하고 로그인 버튼을 누르면 command=login 요청이 발생한다.
MemberServlet은 id와 pw 값을 받아 service.login을 호출한다.
(2) 로그인 성공
로그인 성공 시 MemberDto 객체의 myid 값이 null이 아니다.
이 경우 session에 login이라는 이름으로 회원 정보를 저장한다.
(3) 게시판 목록 이동
로그인 성공 후 response.sendRedirect("./board?command=list")를 사용해 게시판 목록으로 이동한다.
session에 로그인 정보가 저장되어 있으므로 redirect 후에도 로그인 상태가 유지된다.
(4) 로그인 실패
로그인 실패 시 result.jsp로 forward한다.
실패 메시지와 index.jsp 이동 URL을 request에 저장한다.
3) logout
(1) 로그아웃 요청
로그아웃 버튼을 누르면 command=logout 요청이 발생한다.
MemberServlet은 session.invalidate를 실행해 session 정보를 삭제한다.
(2) 로그아웃 결과
로그아웃 완료 메시지를 result.jsp로 전달한다.
확인 버튼을 누르면 index.jsp로 이동한다.
4) registform
(1) 회원가입 화면 이동
command가 registform이면 view/member/registform.jsp로 이동한다.
로그인 화면에서 regist 버튼을 누르면 이 요청이 발생한다.
5) idchk
(1) 아이디 중복 체크 요청
회원가입 화면에서 중복체크 버튼을 누르면 새 팝업 창으로 member?command=idchk&id=입력아이디 요청이 발생한다.
MemberServlet은 입력한 id를 받아 service.idChk를 호출한다.
(2) 중복 여부 판단
service.idChk 결과가 null이면 사용 가능한 아이디이다.
결과가 null이 아니면 이미 존재하는 아이디이므로 사용할 수 없다.
(3) idchk.jsp 이동
중복 여부를 idnotused라는 이름으로 request에 저장하고 idchk.jsp로 forward한다.
idchk.jsp는 사용 가능 여부를 화면에 출력한다.
6) insertmember
(1) 회원가입 처리
회원가입 form에서 입력한 myid, mypw, myname, myphone 값을 받는다.
이 값들을 MemberDto 객체에 담아 service.insertMember로 전달한다.
(2) 결과 처리
회원가입 성공 시 result.jsp에 “회원 가입 성공” 메시지를 전달하고 index.jsp로 이동하게 한다.
실패 시 회원가입 화면으로 돌아가도록 처리한다.
8 로그인과 세션 처리
1) session 저장
(1) 로그인 정보 저장
로그인 성공 시 session.setAttribute("login", dto)를 사용해 회원 정보를 session에 저장한다.
login이라는 이름으로 저장했기 때문에 JSP에서는 sessionScope.login 또는 ${login}으로 접근할 수 있다.
(2) 사용하는 이유
웹은 요청이 바뀌면 이전 요청 정보를 기본적으로 기억하지 않는다.
로그인 상태를 유지하려면 session에 사용자 정보를 저장해야 한다.
2) session 유지 시간
(1) setMaxInactiveInterval
session.setMaxInactiveInterval(60*60)은 session 유지 시간을 1시간으로 설정한다.
사용자가 일정 시간 동안 요청을 보내지 않으면 session이 만료될 수 있다.
3) session 삭제
(1) invalidate
session.invalidate는 현재 session에 저장된 값을 모두 삭제한다.
로그아웃할 때 사용한다.
(2) 로그아웃 후 변화
session의 login 값이 사라지면 로그인한 사용자로 인정되지 않는다.
게시판 페이지에 접근하려고 해도 logininfo.jsp에서 로그인 화면으로 이동시킨다.
9 회원가입과 아이디 중복 체크
1) registform.jsp
(1) 회원가입 화면
registform.jsp는 회원가입 정보를 입력받는 JSP이다.
아이디, 비밀번호, 이름, 전화번호를 입력받는다.
(2) required 속성
input 태그에 required 속성을 사용했다.
값이 비어 있으면 form 제출을 막아 필수 입력을 유도한다.
(3) 중복체크 버튼
아이디 입력 옆에 중복체크 버튼을 두었다.
버튼을 누르면 JavaScript의 idChk 함수가 실행된다.
2) idChk 함수
(1) 아이디 입력 확인
idChk 함수는 먼저 아이디 입력값이 비어 있는지 확인한다.
비어 있으면 “아이디를 입력해 주세요” alert를 출력한다.
(2) window.open
아이디가 입력되어 있으면 window.open을 사용해 작은 팝업 창을 연다.
팝업 창에서는 member?command=idchk&id=입력아이디 요청을 실행한다.
3) idchk.jsp
(1) 팝업 결과 화면
idchk.jsp는 아이디 중복 체크 결과를 보여주는 팝업 화면이다.
사용 가능한 아이디인지, 중복 아이디인지 메시지를 출력한다.
(2) opener
opener는 현재 팝업 창을 열어준 부모 창을 의미한다.
idchk.jsp에서는 opener.document를 사용해 부모 창의 회원가입 form에 접근한다.
(3) 확인 버튼
확인 버튼을 누르면 중복 여부에 따라 부모 창의 포커스를 이동시킨다.
사용 가능한 아이디라면 비밀번호 입력칸으로 이동하고, 중복 아이디라면 아이디 입력칸으로 다시 이동한다.
10 logininfo.jsp
1) logininfo.jsp의 역할
(1) 로그인 정보 공통 화면
logininfo.jsp는 게시판 JSP에서 공통으로 포함되는 로그인 정보 영역이다.
로그인한 사용자의 이름과 로그아웃 버튼을 출력한다.
(2) include 사용
boardlist.jsp, boarddetail.jsp, boardwrite.jsp, boardupdate.jsp에서 logininfo.jsp를 include했다.
공통으로 필요한 로그인 체크와 사용자 정보 출력 코드를 여러 페이지에 반복해서 작성하지 않아도 된다.
2) 로그인 체크
(1) sessionScope.login
sessionScope.login은 session에 저장된 로그인 회원 정보를 의미한다.
로그인하지 않은 상태라면 이 값은 비어 있다.
(2) c:if
c:if test="${empty sessionScope.login}" 조건으로 로그인 여부를 확인한다.
session에 login 값이 없으면 로그인하지 않은 사용자로 판단한다.
(3) c:redirect
로그인하지 않은 사용자는 c:redirect url="/"로 이동시킨다.
즉, 게시판 페이지에 직접 접근해도 로그인 화면으로 돌아가게 된다.
3) 로그인 사용자 출력
(1) 사용자 이름 출력
${login.myname}을 사용해 로그인한 사용자의 이름을 출력한다.
session에 저장된 MemberDto의 getMyname 값이 화면에 표시된다.
(2) 로그아웃 버튼
로그아웃 버튼을 누르면 member?command=logout 요청이 발생한다.
MemberServlet에서 session을 삭제하고 로그아웃 결과 페이지로 이동한다.
11 게시판 View 페이지
1) boardlist.jsp
(1) 게시글 목록 화면
boardlist.jsp는 게시글 목록을 출력하는 페이지이다.
Controller에서 request에 저장한 list를 JSTL로 반복 출력한다.
(2) c:choose
c:choose를 사용해 게시글이 없는 경우와 있는 경우를 나누었다.
목록이 비어 있으면 “작성된 글이 존재하지 않습니다”를 출력한다.
(3) c:forEach
게시글이 있으면 c:forEach로 list를 반복한다.
각 게시글의 번호, 작성자, 제목, 작성일을 출력한다.
2) boarddetail.jsp
(1) 상세 보기 화면
boarddetail.jsp는 게시글 하나의 상세 내용을 출력한다.
Controller가 request에 저장한 dto를 EL로 출력한다.
(2) 수정, 삭제, 목록 버튼
수정 버튼은 updateform 요청을 보낸다.
삭제 버튼은 delete 요청을 보낸다.
목록 버튼은 history.back으로 이전 화면으로 돌아간다.
3) boardwrite.jsp
(1) 글쓰기 화면
boardwrite.jsp는 새 게시글을 작성하는 form 화면이다.
작성자, 제목, 내용을 입력받고 board Servlet으로 POST 요청을 보낸다.
(2) hidden command
command=write 값을 hidden input으로 전달한다.
BoardServlet은 이 값을 보고 글 작성 요청임을 판단한다.
4) boardupdate.jsp
(1) 글 수정 화면
boardupdate.jsp는 기존 게시글의 제목과 내용을 수정하는 form 화면이다.
기존 값은 EL을 사용해 input과 textarea에 출력한다.
(2) hidden no
수정할 글 번호는 hidden input으로 전달한다.
화면에는 보이지 않지만 DB에서 어떤 글을 수정할지 판단하는 기준이 된다.
5) result.jsp
(1) 공통 결과 화면
result.jsp는 로그인 실패, 로그아웃, 회원가입, 글 작성, 글 수정, 글 삭제 결과를 공통으로 출력한다.
Servlet에서 전달한 msg와 url을 EL로 출력한다.
(2) 사용하는 이유
기능마다 결과 페이지를 따로 만들지 않아도 된다.
메시지와 이동할 URL만 다르게 전달하면 하나의 result.jsp로 여러 결과를 처리할 수 있다.
12 pageContext.request.contextPath
1) contextPath의 개념
(1) contextPath
contextPath는 현재 웹 애플리케이션의 기본 경로를 의미한다.
프로젝트명이 URL에 포함되는 경우, 그 프로젝트 경로까지 자동으로 가져온다.
(2) 사용 예
${pageContext.request.contextPath}/board?command=list처럼 작성하면 현재 프로젝트 경로를 기준으로 board Servlet에 요청을 보낼 수 있다.
2) 사용하는 이유
(1) 경로 오류 방지
JSP 파일이 view/board 같은 하위 폴더에 있으면 상대 경로가 헷갈릴 수 있다.
contextPath를 사용하면 현재 JSP 위치와 상관없이 안정적으로 Servlet 요청 경로를 만들 수 있다.
(2) 유지보수
프로젝트 이름이 바뀌어도 contextPath를 사용하면 경로를 직접 수정할 필요가 줄어든다.
JSP에서 Servlet으로 요청을 보낼 때 자주 사용하는 방식이다.
13 오늘 실습의 핵심 정리
1) 게시판과 회원 기능 통합
(1) 게시판 기능
게시판에서는 목록 조회, 상세 조회, 글 작성, 글 수정, 글 삭제 기능을 구현했다.
BoardServlet, BoardService, BoardDao 구조로 역할을 나누었다.
(2) 회원 기능
회원 기능에서는 로그인, 로그아웃, 회원가입, 아이디 중복 체크를 구현했다.
MemberServlet, MemberService, MemberDao 구조로 역할을 나누었다.
(3) 통합 흐름
로그인에 성공하면 게시판 목록으로 이동한다.
게시판 JSP에서는 logininfo.jsp를 include하여 로그인 여부를 확인한다.
2) Servlet 분리
(1) BoardServlet
BoardServlet은 게시판 관련 요청만 담당한다.
command 값에 따라 list, write, detail, update, delete 기능을 처리한다.
(2) MemberServlet
MemberServlet은 회원 관련 요청만 담당한다.
command 값에 따라 login, logout, registform, idchk, insertmember 기능을 처리한다.
(3) 분리의 장점
하나의 Servlet이 모든 기능을 처리하면 코드가 길어지고 복잡해진다.
기능별로 Servlet을 나누면 요청 흐름을 더 쉽게 파악할 수 있다.
3) 로그인 기반 접근 제어
(1) session 사용
로그인 성공 시 MemberDto를 session에 저장했다.
session에 login 값이 있으면 로그인한 사용자로 판단한다.
(2) logininfo.jsp
게시판 JSP에 logininfo.jsp를 include하여 로그인 여부를 공통으로 검사했다.
로그인하지 않은 사용자가 게시판 페이지에 접근하면 로그인 화면으로 이동하게 만들었다.
(3) 배운 점
단순히 로그인만 구현하는 것이 아니라, 로그인 상태에 따라 페이지 접근을 제어하는 흐름을 배웠다.
실제 웹 서비스에서 로그인하지 않은 사용자가 특정 기능을 사용할 수 없도록 막는 기본 구조이다.
4) 회원가입과 중복 체크
(1) 회원가입
회원가입 form에서 아이디, 비밀번호, 이름, 전화번호를 입력받아 MEMBER 테이블에 저장했다.
INSERT 성공 여부에 따라 result.jsp에서 결과를 출력했다.
(2) 아이디 중복 체크
회원가입 전에 입력한 아이디가 이미 존재하는지 DB에서 조회했다.
중복되지 않은 아이디면 사용 가능, 이미 존재하면 중복 아이디로 안내했다.
(3) 팝업과 opener
window.open으로 중복 체크 결과 창을 띄우고, opener를 이용해 부모 회원가입 창의 입력칸에 접근했다.
이를 통해 팝업 창과 원래 창이 서로 연결될 수 있다는 것을 배웠다.
5) EL과 JSTL 활용
(1) EL
${dto.title}, ${login.myname}, ${msg}처럼 EL을 사용해 객체 값을 출력했다.
JSP에서 Java 표현식을 직접 쓰지 않아도 데이터를 화면에 보여줄 수 있었다.
(2) JSTL
c:choose, c:when, c:otherwise, c:forEach, c:if, c:redirect를 사용했다.
조건문과 반복문, 로그인 체크, 페이지 이동을 태그 형태로 처리했다.
(3) View 정리
EL과 JSTL을 사용하면서 JSP 안의 Java 코드가 줄어들었다.
View는 화면 출력에 집중하고, 로직은 Servlet, Service, DAO에서 처리하는 구조가 더 명확해졌다.
6) 오늘 배운 점
(1) MVC 구조 확장
게시판 CRUD만 구현하던 구조에서 회원 기능까지 연결하면서 MVC 구조가 확장되는 흐름을 이해했다.
기능이 많아질수록 Controller, Service, DAO의 역할 분리가 중요하다는 것을 느꼈다.
(2) 로그인 상태 유지
session을 이용해 로그인 정보를 유지하고, 게시판 페이지에서 로그인 여부를 검사하는 방법을 배웠다.
로그인은 단순히 성공 여부만 판단하는 것이 아니라, 이후 페이지 접근과도 연결된다는 점을 알게 되었다.
(3) 공통 JSP 분리
logininfo.jsp처럼 여러 페이지에서 반복되는 코드를 별도 JSP로 분리해 include할 수 있었다.
공통 영역을 분리하면 코드 중복을 줄이고 유지보수하기 쉬워진다.
(4) 실제 웹 서비스에 가까운 흐름
로그인, 회원가입, 중복 체크, 게시판 CRUD가 함께 연결되면서 실제 웹 서비스에 더 가까운 구조를 경험했다.
사용자가 로그인하고, 게시글을 보고, 글을 작성하고, 로그아웃하는 전체 흐름을 구현했다는 점에서 의미 있는 실습이었다.'멀티캠퍼스' 카테고리의 다른 글
| [2026.06.09] - TIL 47일차 Ajax, Fetch, JSON 데이터 처리 정리 (0) | 2026.06.11 |
|---|---|
| [2026.06.08] - TIL 46일차 답변형 게시판 구현 정리 (0) | 2026.06.09 |
| [2026.06.04] - TIL 44일차 Servlet 기반 MVC 게시판 CRUD 정리 (0) | 2026.06.08 |
| [2026.06.02] - TIL 42일차 Scope, EL, JSTL 정리 (0) | 2026.06.03 |
| [2026.06.01] - TIL 41일차 Servlet Life Cycle, URL Mapping, GET/POST 요청 처리 정리 (0) | 2026.06.03 |