2025년, 코딩은 선택이 아닌 필수!

2025년 모든 학교에서 코딩이 시작 됩니다. 먼저 준비하는 사람만이 기술을 선도해 갑니다~

웹프로그래밍/스프링부트

스프링부트] 로그인 기능 구현하기

파아란기쁨1 2023. 10. 30. 10:45
반응형

로그인 후 세션을 가져 오는 방법에 대해 살펴 보자.

 

 

1. 프로젝트 만들고 실행하기

- Spring Initializr 를 사용해 프로젝트를 생성한다.

- Spring Initializr 페이지( https://start.spring.io ) 에 접속한 후 각 항목을 다음과 같이 설정한다.

- 화면 오른쪽에 있는 Dependencies - ADD EDPENDENCIES... 버튼을 클릭하고 web을 입력후 Spring Web 의 WEB 버튼을 클릭한다.

- 같은 방법으로 다음 3가지 도구를 추가한다. 도구 이름으로 검색하면 된다.

  • H2 Database : 자료를 저장하기 위한 데이터베이스
  • Mustache : 화면을 만들기 위해 필요한 도구
  • Spring Data JPA : 데이터베이스를 편리하게 다룰 수 있게 해 주는 도구

- GENERATE 버튼을 클릭해서 프로젝트를 내려 받는다.

프로젝트명.zip 파일로 다운로드 된다. 이 파일을 압축 해제 하자

 

- 인텔리제이를 실행하고 open을 클릭해서 압축 해제한 폴더를 선택한다.

이 프로젝트를 신뢰하는지 묻는창이 뜨면 신뢰한다(Trust..) 체크박스에 체크하고 Trust Project 버튼을 클릭한다

- 다음과 같은 에러가 발생한다면 처리해 주자.

고급시스템 설정 -> 환경변수 -> JAVA_HOME 이 다음과 같이 JDK 버젼이 17 버젼의 디렉토리를 가르키는지 확인한다.( https://coding-factory.tistory.com/838 참고)

또는 다음과 같이 Gradle JVM 폴더 변경

2. 디렉토리 구조

 

3. 메인 페이지 화면 구현(index.mustache)

<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Spring Boot</title>
</head>
<body>
    <h2>Hello Spring Boot!!</h2>
    <a href="/member/create">회원가입</a>
    <a href="/member/login">로그인</a>
    <a href="/member/">회원목록</a>

    session 값 확인: {{loginEmail}}

</body>
</html>

4. 메인페이지 호출 컨트롤러(MainController.js)

package com.example.AcademyManager.controller;

import com.example.AcademyManager.dto.MemberDto;
import com.example.AcademyManager.entity.MemberEntity;
import com.example.AcademyManager.web.SessionConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.SessionAttribute;

@Slf4j
@Controller
public class MainController {
    //기본페이지 요청 메서드
    @GetMapping("/")
    public String index(@SessionAttribute(name = SessionConstants.LOGIN_MEMBER, required = false) MemberDto loginMember, Model model){
        // 세션이 유지되면 세션정보를 화면에 출력 
        if(loginMember!=null){
            log.info(loginMember.getMemberEmail());
            model.addAttribute("loginEmail", loginMember.getMemberEmail());
        }
        else{
            model.addAttribute("loginEmail", "");
        }
        return "index"; //templates 폴더의 index.html 을 찾아간다.
    }
}

세션 정보가 있다면 loginMember 로 가져 와서 화면에 출력하는 형식으로 바꿨다. 여기서 로그인 전과 로그인 후로 다른 화면을 띄울 수가 있다.

 

5. 회원가입 화면 (create.mustache)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>save</title>
    <!-- jquery cdn -->
    <script
            src="https://code.jquery.com/jquery-3.6.3.min.js"
            integrity="sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU="
            crossorigin="anonymous"></script>
</head>
<body>
<!-- action속성: form에 작성한 데이터를 어디로 보낼지 지정 -->
<form action="/member/save" method="post">
    <!-- name속성: 서버로 전송할 때 변수이름의 역할 -->
    이메일: <input type="text" name="memberEmail" id="memberEmail" onblur="emailCheck()"> <br>
    <p id="check-result"></p>
    비밀번호: <input type="password" name="memberPassword"> <br>
    이름: <input type="text" name="memberName"> <br>
    <input type="submit" value="회원가입">

</form>
</body>
<script th:inline="javascript">
    const emailCheck = () => {
        const email = document.getElementById("memberEmail").value;
        const checkResult = document.getElementById("check-result");
        console.log("입력값: ", email);
        $.ajax({
            // 요청방식: post, url: "email-check", 데이터: 이메일
            type: "post",
            url: "/member/email-check",
            data: {
                "memberEmail": email
            },
            success: function(res) {
                console.log("요청성공", res);
                if (res == "ok") {
                    console.log("사용가능한 이메일");
                    checkResult.style.color = "green";
                    checkResult.innerHTML = "사용가능한 이메일";
                } else {
                    console.log("이미 사용중인 이메일");
                    checkResult.style.color = "red";
                    checkResult.innerHTML = "이미 사용중인 이메일";
                }
            },
            error: function(err) {
                console.log("에러발생", err);
            }
        });
    }
</script>
</html>

6. 로그인 화면(login.mustache)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<form action="/member/login" method="post">
    이메일: <input type="text" name="memberEmail"> <br>
    비밀번호: <input type="password" name="memberPassword"> <br>
    <input type="submit" value="로그인">
</form>
</body>
</html>

7. 회원가입,저장,로그인 호출 컨트롤러(MemberController.java)

package com.example.AcademyManager.controller;

import com.example.AcademyManager.dto.MemberDto;
import com.example.AcademyManager.service.MemberService;
import com.example.AcademyManager.web.SessionConstants;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

@Slf4j
@Controller
public class MemberController {

    @Autowired
    private MemberService memberService;    // 회원가입 페이지 출력 요청
    @GetMapping("/member/create")
    public String memberCreate() {
        return "member/create";
    }

    @PostMapping("/member/save")
    public String save(@ModelAttribute MemberDto memberDTO) {
        System.out.println("MemberController.save");
        System.out.println("memberDTO = " + memberDTO.toString());

        //MemberService memberService = new MemberService();
        memberService.save(memberDTO);
        //repositry 를 DB에 저장
        //Member saved = memberRepository.save(memberEntity);
        //log.info(saved.toString());
        //memberService.save(memberDTO);
        return "member/login";
    }

    @GetMapping("/member/login")
    public String loginForm() {
        return "member/login";
    }
    @PostMapping("/member/login")
    public String login(@ModelAttribute MemberDto memberDTO, HttpSession session) {
        MemberDto loginResult = memberService.login(memberDTO);
        if (loginResult != null) {
            // login 성공
            log.info(loginResult.getMemberEmail());
            session.setAttribute(SessionConstants.LOGIN_MEMBER, loginResult);
            return "redirect:/";
        } else {
            log.info("로그인 실패");
            // login 실패
            return "/member/login";
        }
    }
}

8. MemberDto.java

package com.example.AcademyManager.dto;

import com.example.AcademyManager.entity.MemberEntity;
import lombok.*;

@Getter
@Setter
@AllArgsConstructor
@ToString
public class MemberDto {
    private Long id;
    private String memberEmail;
    private String memberPassword;
    private String memberName;

    public MemberEntity toEntity() {
        return new MemberEntity(id, memberEmail, memberPassword,memberName);
    }
}

9. MemberEntity.java

package com.example.AcademyManager.entity;

import com.example.AcademyManager.dto.MemberDto;
import jakarta.persistence.*;
import lombok.*;

@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
@Setter
@Getter
@Table(name = "member")
public class MemberEntity {
    @Id
    @GeneratedValue
    private Long id;
    @Column(unique = true)// unique 제약조건 추가
    private String memberEmail;
    @Column
    private String memberPassword;
    @Column
    private String memberName;

    public static MemberDto toMemberDto(MemberEntity member) {
        return new MemberDto(
                member.getId(), // 댓글 엔티티의 id
                member.getMemberEmail(), // 댓글 엔티티가 속한 부모 게시글의 id
                member.getMemberPassword(), // 댓글 엔티티의 nickname
                member.getMemberName() // 댓글 엔티티의 body
        );
    }
}

10. MemberRepository.java

package com.example.AcademyManager.repository;

import com.example.AcademyManager.entity.MemberEntity;
import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface MemberRepository extends CrudRepository<MemberEntity,Long>  {
    // 이메일로 회원 정보 조회 (select * from member_table where member_email=?)
    Optional<MemberEntity> findByMemberEmail(String memberEmail);
}

11. MemberService.java

package com.example.AcademyManager.service;

import com.example.AcademyManager.dto.MemberDto;
import com.example.AcademyManager.entity.MemberEntity;
import com.example.AcademyManager.repository.MemberRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Slf4j
@Service
public class MemberService {
    @Autowired
    private MemberRepository memberRepository;
    public void save(MemberDto memberDTO) {
        // 1. dto -> entity 변환
        //DTO를 엔티티로 변환
        MemberEntity memberEntity = memberDTO.toEntity();
        log.info(memberEntity.toString());
        // 2. repository의 save 메서드 호출
        memberRepository.save(memberEntity);
        // repository의 save메서드 호출 (조건. entity객체를 넘겨줘야 함)
    }

    public MemberDto login(MemberDto memberDTO) {
        /*
            1. 회원이 입력한 이메일로 DB에서 조회를 함
            2. DB에서 조회한 비밀번호와 사용자가 입력한 비밀번호가 일치하는지 판단
         */
        log.info(memberDTO.toString());
        Optional<MemberEntity> byMemberEmail = memberRepository.findByMemberEmail(memberDTO.getMemberEmail());

        if (byMemberEmail.isPresent()) {
            log.info(byMemberEmail.toString());
            // 조회 결과가 있다(해당 이메일을 가진 회원 정보가 있다)
            MemberEntity memberEntity = byMemberEmail.get();
            log.info(memberEntity.toString());
            if (memberEntity.getMemberPassword().equals(memberDTO.getMemberPassword())) {
                // 비밀번호 일치
                // entity -> dto 변환 후 리턴
                MemberDto dto = MemberEntity.toMemberDto(memberEntity);
                return dto;
            } else {
                // 비밀번호 불일치(로그인실패)
                return null;
            }
        } else {
            // 조회 결과가 없다(해당 이메일을 가진 회원이 없다)
            return null;
        }
    }
}

12.SessionConstants.java

package com.example.AcademyManager.web;

public interface SessionConstants {
    String LOGIN_MEMBER = "loginMember";
}

 

로그인 후 

 

반응형