CRUD를 활용하여 회원가입을 진행하고, 고객의 정보가 데이터베이스에 저장한 후 이를 통해 로그인을 할 수 있는 방법을 배우게 됐다. 먼저 회원가입 창은 기존 CRUD를 진행함에 있어 다른점이 없기 때문에 새롭게 배운 부분만 살펴보려고 한다.

 

	public Member getUser(String id, String pw) {
		
		Member mb = null;

		Connection conn = DBconn();
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {
			
			String sql = "select * from member where id=? and password=?";
			ps = conn.prepareStatement(sql);
			ps.setString(1, id);
			ps.setString(2, pw);
			
			rs = ps.executeQuery();
			
			if(rs.next()) {
				System.out.println("일치하는 회원 발견!");
				
				mb = new Member();
				mb.setId(rs.getString("id"));
				mb.setPassword(rs.getString("password"));
				mb.setName(rs.getString("name"));
				mb.setGender(rs.getString("gender"));
				mb.setBirth(rs.getString("birth"));
				mb.setMail(rs.getString("mail"));
				mb.setPhone(rs.getString("phone"));
				mb.setAddress(rs.getString("address"));
				mb.setRegist_day(rs.getTimestamp("regist_day"));
				
				
			} else {
				System.out.println("아이디 혹은 패스워드가 다릅니다.");
			}
			
		} catch(SQLException e) { System.out.println("회원 조회 실패"); }
		
		finally {
			try {
				
				if(rs != null) { rs.close(); }
				if(ps != null) { ps.close(); }
				if(conn != null) { conn.close(); }
				
			} catch (Exception e2) { System.out.println("SQL리소스 닫기 실패"); }
		}
        
		return mb;
	}

 

   먼저 로그인을 진행하게 되면 회원의 정보를 데이터베이스에서 가져오기 전에 아이디와 비밀번호를 조회하여 모두 맞다면 반환하고 그렇지 않다면 다르다는 경고문을 띄워야 한다. 먼저 회원의 정보를 담을 객체 Member를 생성해야 하는데, 초기에 null값을 주는 이유는 컨트롤러에 넘어가서 해당 객체의 null값으로 true/false를 판단해야 하기 때문이다. if문에서 ResultSet으로 받은 데이터가 있는지 조회하고, 없으면 아무것도 담지 못한 채 컨트롤러에 null을 반환할 수 있도록 말이다.

 

   SQL문도 조금은 달라졌는데, where명령어에 and를 추가하면 두 개 이상의 조건이 맞는 데이터만 반환해준다. 조건에 맞는 데이터가 있다면 해당 데이터를 반환할 것이고, 없다면 -1(false)을 반환하기 때문에 if문이 실행되지 않는다.

 

@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException {

		String id = req.getParameter("id");
		String password = req.getParameter("password");

		MemberRepository dao = MemberRepository.getRepository();
		Member dto = dao.getUser(id, password);
		
		if(dto != null) {
			//로그인에 성공했으므로 세션 생성
			HttpSession session = req.getSession(true);
			session.setAttribute("member", dto);
			RequestDispatcher rd = req.getRequestDispatcher("resultMember.jsp?msg=2");
			rd.forward(req, resp);
		
		} else { resp.sendRedirect("member_login?error=1"); }
		
		
	}

 

   먼저 로그인 화면에서 받아온 ID와 PW를 위에서 작성했던 함수에 넣어 결과값을 받아 다시 컨트롤러로 돌아오게 된다. 여기서 반환받은 Member객체가 null(주소값도 존재하지 않는 상태)이 아니라면 데이터를 받아왔다는 뜻이 되므로 로그인 유지에 필요한 세션을 생성해준다. 이때 주의해야할 점이 있는데, 지금 다루고 있는 페이지가 jsp페이지라는 사실이다. 해당 페이지는 세션을 자동으로 생성해주기 때문에, 로그인의 세션을 받아와서 동작을 제한하기 위해서는 이 속성을 모두 꺼줘야한다. 심지어 jsp는 페이지마다 세션이 모두 true로 되어 있어서 모든 페이지를 하나하나 다… 꺼줘야한다. 한 페이지라도 true로 되어 있다면 해당 기능은 제대로 동작하지 않을 것이니 유의하자.

 

   여기서 로그인을 하게 될 때, 실패할 때 모두 어떤 파라미터를 들고가게 되는데 해당 값에 따라 보여지는 페이지가 다르게 나오도록 설정해두었다. 성공하면 환영 인사 페이지가, 실패하면 로그인 페이지에서 오류창을 띄워주게 된다.

 

<%

	String sessionId = null;
	
	HttpSession session = request.getSession(false);
	if(session != null){
		if(session.getAttribute("member")!=null){
			Member mb = (Member) session.getAttribute("member");
			sessionId = mb.getId();
		}
	}
    
%>

...(중략)

	<% if(sessionId == null) { %>
		<li class="nav-item"><a class="nav-link" href="member_login">로그인 </a></li>
		<li class="nav-item"><a class="nav-link" href="member_add">회원 가입</a></li>
	<% } else { %>
		<li style="padding-top: 7px;">[<%=sessionId%>님]</li>
		<li class="nav-item"><a class="nav-link" href="member_logout">로그아웃 </a></li>
		<li class="nav-item"><a class="nav-link" href="member_update">회원 수정</a></li>
	<% } %>

 

   이제 로그인을 한 후, 세션이 유지된 상태로 메인화면을 요청하면 '로그인/회원가입' 이 있던 탭에 현재 접속중인 계정의 아이디와 '로그아웃/회원수정' 이라는 항목이 나타나게 된다. 이런 식으로 request객체를 이용하여 받아온 변수나, 요청시 보내오는 파라미터의 여부로 같은 페이지라도 다른 내용을 보여줄 수 있는 것이다.

 

   이제 로그인을 하면 긴 시간 세션이 유지되는 상태이니, 게시판을 만들고 글을 작성할 수 있는 코드를 만들어보려한다.

   일단 로그인을 하지 않으면 게시판의 글쓰기 버튼에 접근할 수 없도록 유효성 검사와 sendRedirect를 통해 로그인 창으로 보내는 컨트롤러부터 제작해보았다.

 

@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException {
		System.out.println("BoardWrite 진입");
		
		HttpSession session = req.getSession(false);
		
		if(session == null) {
			System.out.println("세션이 존재하지 않습니다.");
			resp.sendRedirect("member_login");
		} else {
			RequestDispatcher rd = req.getRequestDispatcher("writeForm.jsp");
			rd.forward(req, resp);
		}
		
	}

 

   유효성 검사는 사실 Java에서 수행할 것이 아니라, HTML 자체에서 자바스크립트를 활용하여 하는 편이 좋다. Java가 할 수 없는 것은 아니나, 컨트롤러는 서버 내에서 이동하거나 혹은 나갔다가 들어오는 과정을 거치게 된다. 따라서 유효성 검사를 통해 서버 내를 활보하는 것은 그다지 효율적인 일이 아니며, 로그인의 여부나 form태그의 입력 여부 등은 서버로 전송되지 않고도 HTML 자체에서 처리할 수 있기 때문에 스크립트를 이용하는 것이 맞다.

 

   이제 게시판의 글쓰기에 접근하기 위해서는 세션을 가지고 있어야만 가능하다. 다음 시간에는 게시판 작성을 알아보자.

 

Cannot invoke "String.equals(Object)" because "edit" is null

 

   Null Pointer, 생각보다 쉽게 보는 오류다보니 해결도 쉬워서 그렇게 어려운 에러는 아니었는데 생각보다 꽤 애먹었던 부분이 있어 기록으로 남기고자 한다. 보통 널포인터 오류가 나면 참조변수에 아무것도 없겠거니 하고 대수롭지 않게 여겨서 이런 상황이 발생했다 생각한다.

 

	<ul class="nav nav-pills">
      	<!-- R : 전체상품 불러오기 -->
	  	<li class="nav-item"><a class="nav-link"  href="products">All Book</a></li>
	  	<!-- C : 상품입력 -->
		<li class="nav-item"><a class="nav-link" href="AddBook">Add Book</a></li>
		<!-- U : 상품수정 -->
		<li class="nav-item"><a class="nav-link" href="products?edit=update">Book update</a></li>
		<!-- D : 상품삭제 -->
		<li class="nav-item"><a class="nav-link" href="products?edit=delete">Book delete</a></li>
	</ul>

 

   먼저 요청 부분이다. products에 매핑할 때 수정과 삭제는 각각 파라미터를 지정해주었다.

 

	<% String edit = (String) request.getParameter("edit"); %>

	<div class="p-5 mb-4 bg-body-tertiary rounded-3">
		<div class="container-fluid py-5">
			<h1 class="display-5 fw-bold">
				<% if(edit.equals("update")){ %> 도서 편집
				
				<% } else if(edit.equals("delete")){ %> 도서 삭제
				
				<% } else { %> 도서 목록 <% } %>
			</h1>
			<p class="col-md-8 fs-4">
				<% if(edit.equals("update") || edit.equals("delete"))
				{ out.print("BookEdit"); }
				else { out.print("BookList"); } %>	
			</p>
		</div>
	</div>

 

   그리고 Null에러가 발생한 위치이다. 단순히 넘어온 파라미터를 String 변수에 담아 equals() 함수를 사용하여 조건문을 통해 요청에 맞는 데이터가 출력되도록 작성했는데 에러가 발생했다. 그것도 이상하게 편집과 삭제 페이지는 정상적으로 작동했지만 아무것도 없는 전체 목록 조회에서만 오류가 생겼는데 이유를 찾아보니 좀 더 명확하게 표시하라는 조언을 듣고 Null값을 직접 입력하기로 했다.

 

	<%  Stirng edit = null;
    
		if(request.getAttribute("edit")!=null){
			edit = (String)request.getAttribute("edit");
		}
	%>

	<div class="p-5 mb-4 bg-body-tertiary rounded-3">
		<div class="container-fluid py-5">
			<h1 class="display-5 fw-bold">
				<% if(edit.equals("update")){ %> 도서 편집
				
				<% } else if(edit.equals("delete")){ %> 도서 삭제
				
				<% } else if(edit==null) { %> 도서 목록 <% } %> 
			</h1>
			<p class="col-md-8 fs-4">
				<% if(edit.equals("update") || edit.equals("delete"))
				{ out.print("BookEdit"); }
				else { out.print("BookList"); } %>	
			</p>
		</div>
	</div>

 

   위와 같이 수정했는데 당연하게도 되지 않았다 ^0^…

 

   그래서 진짜 이유를 살펴보니, String은 저번에도 말했다싶이 일반 변수가 아니라 객체다. 즉 edit은 참조변수가 되며, 참조변수에 아무런 주소값을 가지고 있지 않은 상태에서 equals() 함수 를 실행하려 했기 때문에 에러가 뜨는것! 실제로 맨 처음처럼 작성했더니 JSP페이지 자체에서도 DeadCode라고 주의를 주었다. 하지만 이게 왜 안되는지 이해를 못했으니 실행했고 결과는 500페이지가 반겨주었다.

 

   쉽게 말해 null인 상태에서 equals() 함수 자체가 실행되지 않으니 조건식에서 에러가 발생한 경우였다. equals() 함수는 일단 String객체를 받지 않았기 때문에 그 함수를 실행하려하니 동작하지 않는 것.

   (단, edit != null 같이 입력하면 당연하게도 작동이 된다)

 

	<%  Stirng edit = "main";
    
		if(request.getAttribute("edit")!=null){
			edit = (String)request.getAttribute("edit");
		}
	%>

	<div class="p-5 mb-4 bg-body-tertiary rounded-3">
		<div class="container-fluid py-5">
			<h1 class="display-5 fw-bold">
				<% if(edit.equals("update")){ %> 도서 편집
				
				<% } else if(edit.equals("delete")){ %> 도서 삭제
				
				<% } else { %> 도서 목록 <% } %> 
			</h1>
			<p class="col-md-8 fs-4">
				<% if(edit.equals("update") || edit.equals("delete"))
				{ out.print("BookEdit"); }
				else { out.print("BookList"); } %>	
			</p>
		</div>
	</div>

 

   다시 원인을 파악했으니 기존 JSP화면에 edit참조변수에 "main"이라는 값을 저장하고 실행하니 무사히 화면이 로드되는 것을 확인할 수 있었다. String객체에 대해 이제 완벽하게 다 안다고 생각했는데 이런 오류를 통해 다시 기초부터 열심히 해야겠다는 생각이 들었다...

'오류노트' 카테고리의 다른 글

webflow Http Status 404 Error  (0) 2024.11.11
mySQL update 및 delete가 안될 때  (0) 2024.11.10
Tiles.xml 설정 주의 사항  (0) 2024.11.09
Downloading external resources is disabled  (0) 2024.11.08
Type mismatch & Cannot cast  (0) 2024.10.27

+ Recent posts