Project/javachip

[2nd project] ² JSP를 활용하여 로그인/회원가입 그리고 유효성 검사하기

ParkYeseul 2024. 9. 18. 17:33

그렇다.

나는로그인/회원가입/마이페이지를 맡았다.

 

하고 싶었던 부분이기도 하고, 욕심만 내면 또 그 안에서 기능 개발을 

할 수 있어서 만족스럽다!!

백엔드 많이 시켜주세욤.. 많이 배우고 싶어요💥🖤

 

추석 연휴 마지막 날 학원에 와서 프론트 단 먼저 구성해보았다.

 


 

🥑<개발 환경>

1) Eclipse: jdk, 환경변수, UTF-8 인코딩
2) Apache Tomcat 
3) Oracle 

4) DBeaver -> 추후 MySql로 변경 예정

5) vs코드

6) lombok

 

 

이미 내 컴퓨터에 셋팅이 되어 있기 때문에 이클립스에서 Dynamic Web Project를 만들었다.

우리 프로젝트 이름은 'BBOL BBOL BBOL'

엄마 아빠가 맨날 어딜 그렇게 뽈뽈뽈 돌아 다니냐고 귀여운 잔소리를 자주 하셔서 짓게 되었다ㅋㅋ

 

무튼 BBOL_prjt라는 이름을 짓고 톰캣9.0을 연결해주었다.

 

 

 

🥑회원가입 페이지 만들기

사전에 그려둔 피그마 프로토타입을 통해서 바로 프론트를 그려봤다.

 

 

join.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>이메일 회원가입</title>
</head>
<body>
    <h1>이메일 가입</h1>
    <!-- 폼 태그 시작 -->
    <form name="joinForm" method="post" action="joinProcess.jsp" onsubmit="return sendit();">
        <!-- 이메일 입력 필드 -->
        <label for="email">이메일</label>
        <br>
        <input type="text" id="email" name="email" placeholder="아이디로 사용할 이메일을 입력해 주세요." required> 
        <br>

        <!-- 이메일 인증 입력 필드 -->
        <label for="email_auth">이메일 인증</label>
        <br>
        <input type="text" id="email_auth" name="email_auth" placeholder="인증번호를 입력해 주세요." required> 
        <!-- 이메일 인증 버튼 -->
        <button type="button">인증</button>
        <br>

        <!-- 닉네임 입력 필드 -->
        <label for="nickname">닉네임</label>
        <br>
        <input type="text" id="nickname" name="nickname" placeholder="한글, 숫자, 영어 2-7자" required> 
        <!-- 닉네임 중복 체크 버튼 -->
        <button type="button">중복체크</button>
        <br>

        <!-- 비밀번호 입력 필드 -->
        <label for="password">비밀번호</label>
        <br>
        <input type="password" id="password" name="password" placeholder="영문, 숫자, 특수문자 포함 8자 이상" required>
        <br>

        <!-- 비밀번호 확인 입력 필드 -->
        <label for="password_re">비밀번호 확인</label>
        <br>
        <input type="password" id="password_re" name="password_re" placeholder="비밀번호를 한 번 더 입력해 주세요." required>
        <br>

        <!-- 폼 제출 버튼 -->
        <p>
            <!-- 가입 완료 버튼, 클릭 시 sendit() 함수 호출 -->
            <button type="submit" value="가입완료">가입완료</button>
        </p>
    </form>
</body>
<!-- 외부 JavaScript 파일 불러오기 -->
<script src="../user.js"></script>
</html>

 

우리는 이메일, 닉네임, 비밀번호가 필요해서 간략한 form을 그려봤다.

이 부분은 HTML로 코드가 짜여 있어서 금방 했다. 

여기서 봐야할 건 2가지

1. form에 onsubmit="return sendit();.

sendit() 함수는 사용자가 회원가입 폼을 제출하기 전에 유효성 검사를 하고

유효성 검사를 통과하지 못하면 회원가입을 할 수 없도록 했다.

2. <script src="../user.js"></script>

user.js는 회원가입에 대한 유효성을 검사하는 파일이다.

jsp를 사용하는데 굳이 js를 불러오는지 궁금했다.

 

정리해보면 

JSP(서버): 데이터를 처리하고 페이지를 생성, 데이터베이스와 상호작용과 비즈니스 로직처리의 역할

JavaScript(클라이언트): 사용자와의 상호작용 처리 및 페이지의 동작제어, 빠른 반응의 역할

 

즉 둘이는 역할이 다르다. 함께 사용해서 성능과 사용자 경험을 올릴 수 있다!

 

 

 

joinProcess.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %> <!-- 데이터베이스 연동을 위해 Java의 SQL 패키지를 임포트 -->
<%@ page import="dto.MemberDTO, dao.MemberDAO" %> <!-- DTO(Data Transfer Object)와 DAO(Data Access Object)를 사용하기 위한 패키지 임포트 -->

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 프로세스</title>
</head>
<body>
<%
    // 클라이언트가 전송한 회원가입 폼 데이터를 가져옴
    String email = request.getParameter("email"); // 사용자가 입력한 이메일 값
    String password = request.getParameter("password"); // 사용자가 입력한 비밀번호 값
    String nickname = request.getParameter("nickname"); // 사용자가 입력한 닉네임 값

    // DTO 객체를 생성하여 입력받은 데이터를 저장함
    // DTO는 데이터를 캡슐화하고, 해당 데이터를 전송하기 위한 객체임
    MemberDTO dto = new MemberDTO();
    dto.setEmail(email); // DTO에 이메일 값 설정
    dto.setPassword(password); // DTO에 비밀번호 값 설정
    dto.setNickname(nickname); // DTO에 닉네임 값 설정

    // DAO 객체를 생성하여 데이터베이스에 회원 정보를 삽입하는 작업을 처리
    // DAO는 데이터베이스와 상호작용하는 클래스
    MemberDAO dao = new MemberDAO();
    int result = dao.insertMember(dto); // 데이터베이스에 회원 정보 삽입

    // 삽입 성공 여부에 따라 다른 페이지로 리다이렉트 또는 포워딩 처리
    if(result == 1){ // 회원가입 성공 시
        response.sendRedirect("../index.jsp"); // 메인 페이지로 리다이렉트
    } else { // 회원가입 실패 시
        request.setAttribute("msg", "회원가입이 정상적으로 이루어지지 않았습니다."); // 에러 메시지 설정
        RequestDispatcher dispatcher = request.getRequestDispatcher("../SignUp/join.jsp"); // 회원가입 페이지로 이동
        dispatcher.forward(request, response); // 에러 메시지와 함께 페이지를 포워딩
    }
%>
</body>
</html>

 

request.getParameter()메소드는 JSP/Servlet에서 사용되는 메소드로

사용자가 입력한 데이터를 서버로 전송할 때 그 값을 받아오는 역할

(여러 개의 값을 가진 파라미터는 request.getParameterValues())

 

나는 이런 메소드들이 무섭고. .낯설어서 정리를 해두려고 한다..리퀘스트겟파라미터!!!

너가 있어야 이메일 값을 받아올 수 있구나?

 

MemberDAO dao = new MemberDAO();

 

MemberDAO는 데이터베이스와 상호작용 담당 클래스

(=데이터베이스와 상호작용을 하는 데 필요한 기능을 담고 있는 설계도로, 집을 짓기 위한 가이드!)

 

new MemberDAO()MemberDAO클래스의 인스턴스 생성

(=인스턴스는 클래스의 기능을 사용할 수 있는 실제 객체)

인스턴스는 설계도를 따라 지어진 실제 집! 설계도는 하나여도 여러 채의 집을 지을 수 있다.

 

dao 위에서 생성한 dao라는 변수에 저장되어 dao를 통해 MemberDAO 클래스의 기능 사용 가능

 

 


int result = dao.insertMember(dto);

dao 객체의 insertMember() 메소드를 호출하여 데이터베이스에 회원 정보를 삽입하는 코드

 

dto 객체에는 사용자가 입력한 이메일, 비밀번호, 닉네임 등의 정보가 담겨 있다.

 

메소드가 실행된 후, 결과값을 int result에 저장, 보통 1은 성공, 0 또는 음수는 실패

 

 

request.setAttribute (String name, Object value) 메소드

요청 객체(HttpServletRequest)에 데이터를 저장하는 데 사용

서버에서 처리한 결과를 클라이언트에게 다시 보여주기 위해 값을 저장

 

ex)

request.setAttribute("userName", "John"); 

name: 저장할 데이터의 이름(키).

value: 저장할 실제 데이터(값).

(request.getAttribute("userName")을 통해 저장한 값을 가져올 수 있다.)

 

 

RequestDispatcher dispatcher = request.getRequestDispatcher(String path)

하나의 요청을 처리할 때, 여러 JSP나 서블릿을 거쳐야 할 때 사용된다

예를 들어, 로그인이 필요한 경우 로그인 검증을 처리하는 서블릿에서 검증 후 다른 페이지로 포워딩하는 데 유용.

RequestDispatcher dispatcher = request.getRequestDispatcher("nextPage.jsp");
dispatcher.forward(request, response);

 

 

 

 

 

🥑로그인 페이지 만들기

 

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!-- 로그인 페이지: 메인 페이지에서 로그인 버튼이 클릭되면 이 로그인 화면으로 이동함 -->
<!-- 사용자가 로그인 정보를 입력하고, 로그인 버튼을 클릭하면 loginProcess.jsp로 데이터를 전송하는 형태로 작성할 수 있음 -->

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>로그인</title>
</head>
<body>
    <!-- 페이지 타이틀 및 설명 -->
    <h1>로그인하고 BBOL BBOL BBOL과 여행을 시작해 보세요!</h1>

    <!-- 로그인 폼 시작 -->
    <form method="post" action="loginProcess.jsp">
        <!-- 이메일 입력 필드 -->
        <label for="email">이메일</label>
        <input type="text" id="email" name="email" placeholder="example@bbol.com" required> 
        <br>

        <!-- 비밀번호 입력 필드 -->
        <label for="password">비밀번호</label>
        <input type="password" id="password" name="password" placeholder="........" required> 
        <br>

        <!-- 로그인 옵션 및 링크 -->
        <p>
            <h6>로그인 유지</h6> <!-- 로그인 유지 옵션 (옵션을 추가할 수 있음) -->
            <h6><a href="#">아이디, 비밀번호 찾기</a></h6> <!-- 아이디/비밀번호 찾기 페이지로 이동할 수 있는 링크 -->
        </p>

        <!-- 로그인 버튼 -->
        <p>
            <!-- 로그인 버튼을 클릭하면 메인 페이지로 이동 (이후에는 로그인 검증 로직 추가 필요) -->
            <button type="button" onclick="window.location.href='../index.jsp'">로그인</button>
        </p>

        <!-- 회원가입 유도 -->
        <br>
        <h6>아직 BBOL BBOL BBOL 회원이 아니신가요?</h6>
        <!-- 회원가입 페이지로 이동 -->
        <a href="../SignUp/join.jsp"><span>회원가입</span></a>
    </form>
</body>
</html>

 

 

 

loginProcess.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- MemberDTO와 MemberDAO를 사용하여 로그인 처리 -->
<%@ page import="dto.MemberDTO, dao.MemberDAO"%>

<%
    // 사용자가 입력한 이메일과 비밀번호를 request 객체에서 가져옴
    String email = request.getParameter("email"); // 입력한 이메일을 가져옴
    String password = request.getParameter("password"); // 입력한 비밀번호를 가져옴

    // DAO 객체를 생성하여 데이터베이스와 상호작용
    MemberDAO dao = new MemberDAO();
    
    // DAO의 login() 메소드를 호출하여 로그인 처리 결과를 얻음
    // 1: 로그인 성공, 0: 로그인 실패
    int result = dao.login(email, password);

    if (result == 1) { 
        // 로그인 성공 시, 세션에 이메일 정보를 저장하고 메인 페이지로 리디렉션
        session.setAttribute("member", email); // 세션에 로그인한 이메일 저장
        response.sendRedirect("../index.jsp"); // 메인 페이지로 리다이렉트
    } else {
        // 로그인 실패 시, 실패 메시지를 request 객체에 설정하고 로그인 페이지로 포워딩
        request.setAttribute("msg", "아이디나 비밀번호가 일치하지 않습니다."); // 에러 메시지 설정
        RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp"); // 로그인 페이지로 이동
        dispatcher.forward(request, response); // 페이지 이동
    }
%>

 

메소드들은 joinProcess와 거의 흡사해서 설명은 스킵!

 

 

다음은 유효성 검사다!

여기서는 js파일에 작성을 하고 불러오는 형태로 진행했다.

 

user.js(회원가입에 대한 유효성검사)

function sendit() {
    const joinForm = document.forms["joinForm"]; // 폼 객체
    const result = document.getElementById("result"); // 닉네임 중복 체크 결과
    const nickname = joinForm.nickname; // 닉네임 입력 필드
    const password = joinForm.password; // 비밀번호 입력 필드
    const password_re = joinForm.password_re; // 비밀번호 확인 필드
    const email = joinForm.email; // 이메일 입력 필드
    
    // 이메일 유효성 검사
    var emailPattern = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$/;
    if (!emailPattern.test(email.value)) {
        alert("이메일 형식이 올바르지 않습니다.");
        email.focus();
        return false;
    }
    
    // 닉네임 유효성 검사
    var nicknamePattern = /^[a-zA-Z0-9가-힣]{2,7}$/; // 영문, 숫자, 한글 2~7자
    if (nickname.value === "") {
        alert("닉네임을 입력하세요!");
        nickname.focus();
        nickname.style.borderColor = "red";
        return false;
    }
    if (!nicknamePattern.test(nickname.value)) {
        alert("닉네임은 한글, 영문, 숫자만 사용 가능하며, 2자 이상 7자 이하이어야 합니다.");
        nickname.focus();
        return false;
    }
    if (result && result.innerHTML === "") {
        alert("닉네임 중복체크를 해주세요!");
        return false;
    }
    if (result && result.innerHTML === "이미 존재하는 닉네임입니다.") {
        alert("닉네임이 중복되었습니다.");
        nickname.focus();
        return false;
    }

    // 비밀번호 유효성 검사
    if (password.value === "") {
        alert("비밀번호를 입력하세요!");
        password.focus();
        return false;
    }
    if (password.value.length < 8) {
        alert("비밀번호는 8자 이상으로 작성해 주세요!");
        password.focus();
        return false;
    }
    let passwordPattern = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/;
    if (!passwordPattern.test(password.value)) {
        alert("비밀번호는 8자 이상, 숫자, 대문자, 소문자, 특수문자를 모두 포함해야 합니다.");
        password.focus();
        return false;
    }
    if (password.value.includes(" ")) {
        alert("비밀번호는 공백을 포함할 수 없습니다.");
        password.focus();
        return false;
    }
    if (password_re.value === "") {
        alert("비밀번호 확인을 입력해 주세요!");
        password_re.focus();
        return false;
    }
    if (password.value !== password_re.value) {
        alert("비밀번호가 일치하지 않습니다. 다시 확인해 주세요!");
        password_re.focus();
        return false;
    }

    // 모든 검사 통과 시 폼 제출
    return true; // 폼 제출 허용
}

document 객체는 웹 페이지의 모든 요소에 접근할 수 있는 전역 객체

 

 

자바스크립트에서 정말 많이 쓰이는 getElementById(id) 메서드는

 

id 속성이 주어진 값을 가진 HTML 요소를 찾는다.

 

페이지 내에서 유일해야 하는 id 값을 사용하여 요소를 선택하여 특정 요소를 참조하거나 조작할 때 사용

 

 

예제>

<!DOCTYPE html>
<html>
<head>
    <title>Example</title>
</head>
<body>
    <h1 id="header">Welcome to My Website</h1>
    <button id="changeText">Change Header Text</button>

    <script>
        // 'header' id를 가진 요소를 찾음
        var header = document.getElementById("header");
        
        // 버튼을 클릭하면 헤더의 텍스트를 변경
        document.getElementById("changeText").onclick = function() {
            header.textContent = "Text Changed!";
        };
    </script>
</body>
</html>

 

 

1. document.getElementById("header")를 사용하여 id="header"인 <h1> 요소를 찾는다.

 

2. 버튼을 클릭하면 header.textContent를 통해 <h1> 요소의 텍스트를 "Text Changed!"로 변경한다.

 

(textContent는 JavaScript에서 DOM 요소의 텍스트 내용을 읽거나 설정하는 데 사용되는 프로퍼티

이 프로퍼티는 HTML 요소의 텍스트를 가져오거나 변경할 때 사용)

 

3. onclick 이벤트가 발생했을 때 할당된 함수가 호출된다.

 

 

 

✔ HTML DOM 객체의 자주 사용되는 프로퍼티

  • innerHTML: 요소의 HTML 내용을 가져오거나 설정
  • textContent: 요소의 텍스트 콘텐츠를 가져오거나 설정
  • value: <input>, <textarea>, <select> 요소의 값을 가져오거나 설정
  • style: 요소의 인라인 스타일을 가져오거나 설정
  • className: 요소의 클래스 이름을 가져오거나 설정
  • src: <img> 요소의 이미지 URL을 가져오거나 설정
  • checked: <input type="checkbox"> 또는 <input type="radio"> 요소의 체크 상태를 가져오거나 설정

✔ 자바스크립트 객체의 자주 사용되는 프로퍼티

  • length: 배열의 요소 개수를 가져옴
  • constructor: 객체를 생성한 함수(생성자)를 가져옴
  • toString(): 객체의 문자열 표현을 반환
  • valueOf(): 객체의 원시 값을 반환

 

 


🌱마무으리

 

아직 데베에 연동을 못시켰지만 큰 틀은 잡아놓고 자세히 몰랐던 부분을 정리해놔서

기분이 좋다. 한 번 더 읽어봐야지!

 

어려운 문법은 없었지만 하나 하나 뜯어 볼수록 놓쳤던 부분을 알아가는 부분이 참 좋은 것 같다!