[Spring boot] Bank App - 로그인 처리

2025. 2. 17. 15:10·Spring
728x90

👨‍💻 지난 포스팅에서 회원 가입 화면을 구현하고, H2 데이터베이스를 설정하여 초기 데이터를 셋팅하는 과정을 다뤘습니다. 이번 포스팅에서는 로그인, 로그아웃 과정을 다뤄보겠습니다. 🚀

Spring Boot와 JSP를 활용한 로그인 기능 구현하기

웹 애플리케이션에서 로그인 기능은 필수적인 요소입니다.

이번 글에서는 Spring Boot와 JSP를 활용하여 로그인 기능을 구현하는 방법을 단계별로 정리하겠습니다.

🚀 학습 목표
1. signin.jsp 파일 생성 및 로그인 화면 요청 기능 구현
2. 로그인 처리 기능 만들기
3. 로그아웃 기능 만들기

1. 로그인 페이지(signin.jsp) 생성 및 요청 처리

📌 로그인 화면 JSP 생성

로그인 페이지를 구현하기 위해 signin.jsp 파일을 생성합니다.
이 파일은 기존 signUp.jsp 파일을 복사하여 수정하면 쉽게 만들 수 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!-- header.jsp -->
<%@ include file="/WEB-INF/view/layout/header.jsp"%>

<!-- 로그인 화면 -->
<div class="col-sm-8">
	<h2>로그인</h2>
	<h5>Bank App에 오신 것을 환영합니다.</h5>
	<form action="/user/sign-in" method="post">
		<div class="form-group">
			<label for="username">Username:</label>
			<input type="text" class="form-control" placeholder="Enter username" id="username" name="username" value="길동">
		</div>
		<div class="form-group">
			<label for="pwd">Password:</label>
			<input type="password" class="form-control" placeholder="Enter password" id="pwd" name="password" value="1234">
		</div>
		<div class="text-right">
			<button type="submit" class="btn btn-primary">로그인</button>
		</div>
	</form>
</div>

<!-- footer.jsp -->
<%@ include file="/WEB-INF/view/layout/footer.jsp"%>

📌 로그인 페이지 요청을 처리하는 컨트롤러

클라이언트가 로그인 페이지에 접근할 수 있도록 UserController에 signInPage() 메서드를 추가합니다.

	/**
	 * 로그인 화면 요청  
	 * 주소 설계 http://localhost:8080/user/sign-in
	 */
	@GetMapping("/sign-in")
	public String signInPage() {
	  // 인증 검사 불필요 
    //   prefix: /WEB-INF/view/
    //   suffix: .jsp
	return "user/signin";
}

 

이제 브라우저에서 http://localhost:8080/user/sign-in으로 이동하면 로그인 화면을 확인할 수 있습니다.

결과 화면


아래 그림은 스프링 컨테이너 안에서의 간략한 동작 흐름 입니다. viewResolver를 확인 하고 SSR 에 대한 개념을 다시 떠올려 보세요.

즉, 뷰 리졸버는 ModelAndView 객체를 View 영역으로 전달하기 위해 알맞은 View 정보를 설정하는 역할을 한다.


2. 로그인 처리 기능 구현

📌 UserRepository 인터페이스에 로그인 관련 메서드 추가

로그인 처리를 위해 UserRepository에 findByUsernameAndPassword() 메서드를 추가합니다.

package com.tenco.bank.repository.interfaces;

import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.tenco.bank.repository.model.User;

//interface 와 user.xml 매칭 - (메서드 명 기준)  
@Mapper // 반드시 선언해주어 한다. 
public interface UserRepository {
	public int insert(User user);
	public int updateById(User user);
	public int deleteById(Integer id);
	public User findById(Integer id);
	public List<User> findAll();
	
	// 코드 추가 1단계 - 조회 : username, password
	// 주의!! - 파미리터가 2개 이상일 경우 @Param 어노테니션을 반드시 선언 
	public User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
	
}

 

MyBatis에서 사용할 SQL 쿼리는 user.xml 파일에 추가합니다.

<select id="findByUsernameAndPassword" resultType="com.tenco.bank.repository.model.User">
    select * from user_tb where username = #{username} and password = #{password}
</select>

✅  SigninDTO 생성

SigninDTO는 로그인 폼 데이터를 담는 객체로 사용합니다.

package com.tenco.bank.dto;
import com.tenco.bank.repository.model.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SigninDTO {
	
	private String username;
	private String password;   
    public User toUser() {
        return User.builder()
                .username(this.username)
                .password(this.password)
                .build();
    }
}

 


📌 로그인 서비스(UserService) 구현

UserService에서 로그인 처리를 담당할 signIn() 메서드를 작성합니다.

	/**
	 * 로그인 서비스 처리 
	 * @param SigninDTO
	 * @return userEntity or null 
	 */
	public User signIn(SigninDTO dto) {
		// 유효성 검사는 Controller 에서 먼저 하자. 
		User userEntity = null; 
		try {
			userEntity = userRepository.findByUsernameAndPassword(dto.getUsername(), dto.getPassword());
		} catch (DataAccessException e) {
			throw new DataDeliveryException("잘못된 처리 입니다",HttpStatus.INTERNAL_SERVER_ERROR);
		} catch (Exception e) {
			// 예외 처리 - 에러 페이지 호출 
			throw new RedirectException("알 수 없는 오류" , HttpStatus.SERVICE_UNAVAILABLE);
		}
		
		// 예외 클래스 발생 안됨. 프로세스 입장에서 예외로 처리 throw 처리 함 
		if(userEntity == null) {
			throw new DataDeliveryException("아이디 혹은 비번이 틀렸습니다",
					HttpStatus.BAD_REQUEST);
		}

		return userEntity;
	}

 


📌 로그인 요청 처리 (UserController 추가)

로그인 요청을 POST 방식으로 처리하고, 인증이 성공하면 세션(HttpSession)에 사용자 정보를 저장합니다.

package com.tenco.bank.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.tenco.bank.dto.SignUpDTO;
import com.tenco.bank.dto.SigninDTO;
import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.repository.model.User;
import com.tenco.bank.service.UserService;
import jakarta.servlet.http.HttpSession;

@Controller
@RequestMapping("/user") // 대문 처리 
public class UserController {
	
	@Autowired  
	private final UserService userService;
	// 코드 추가 
	// 세션 메모리지에 접근하기 위한 HttpSession 을 선언 해주세요 
	@Autowired  
	private final HttpSession session;
	
	// 코드 수정 - DI 처리 
	public UserController(UserService userService, HttpSession session) {
		this.userService = userService;
		this.session = session;
	}
	/**
	 * 회원 가입 페이지 요청 
	 * 주소 설계 http://localhost:8080/user/sign-up
	 * @return signUp.jsp 파일 리턴
	 */
	@GetMapping("/sign-up")
	public String signUpPage() {
	   //   prefix: /WEB-INF/view/
	   //   suffix: .jsp
		return "user/signUp";
	}
	
	// 회원 가입 요청 처리 
	// 주소 설계 http://localhost:8800/user/sign-up
	// Get, Post -> sign-up 같은 도메인이라도 구분이 가능하다. 
	// REST API 를 사용하는 이유에 대해한번 더 살펴 보세요  
	@PostMapping("/sign-up")
	public String signProc(SignUpDTO dto) {
		
		// 1. 인증검사 x 
		// 2. 유효성 검사 
		if(dto.getUsername() == null || dto.getUsername().isEmpty()) {
			throw new DataDeliveryException("username을 입력 하세요", 
					HttpStatus.BAD_REQUEST);
		}
		
		if(dto.getPassword() == null || dto.getPassword().isEmpty()) {
			throw new DataDeliveryException("password을 입력 하세요", 
					HttpStatus.BAD_REQUEST);
		}
		
		if(dto.getFullname() == null || dto.getFullname().isEmpty()) {
			throw new DataDeliveryException("fullname을 입력 하세요", 
					HttpStatus.BAD_REQUEST);
		}		
		userService.createUser(dto);
		
		// todo 로그인 페이지로 변경 예정
		return "redirect:/user/sign-up"; 
	}
	
	/**
	 * 로그인 화면 요청  
	 * 주소 설계 http://localhost:8080/user/sign-in
	 */
	@GetMapping("/sign-in")
	public String signInPage() {
		// 인증 검사가 불필요 하다.
	    //   prefix: /WEB-INF/view/
	    //   suffix: .jsp
		return "user/signin";
	}
	
	// 코드 추가 
	/**
	 * 로그인 처리 
	 * @param signInFormDto
	 * @return 메인 페이지 이동 (수정 예정)
	 * 생각해보기 
	 * GET 방식 처리는 브라우저 히스토리에 남겨지기 때문에 
	 * 예외적으로 로그인 POST 방식으로 처리 한다. (보안) 
	 */
	@PostMapping("/sign-in")
	public String signInProc(SigninDTO dto) {
		// 1. 유효성 검사 
		if(dto.getUsername() == null || 
				dto.getUsername().isEmpty()) {
			throw new DataDeliveryException("username을 입력하시오", HttpStatus.BAD_REQUEST);
		}
		if(dto.getPassword() == null || 
				dto.getPassword().isEmpty()) {
			throw new DataDeliveryException("password을 입력하시오", HttpStatus.BAD_REQUEST);
		}
		User principal = userService.signIn(dto);

		// 세션메모리에  등록 처리 
		session.setAttribute("principal", principal);
		
		// 처리 후에 새로운 request 를 생성할 수 있도록 리다이렉트 처리 합니다. 
		// TODO - 추후 계좌 목록 페이로 변경해 주세요  
		// return "redirect:/account/list";
		System.out.println("111111111");
		return "redirect:/main-page";
	}
}

3. 로그아웃 기능 구현

세션을 초기화하여 로그아웃을 처리하고, 로그인 페이지로 리다이렉트합니다.

@GetMapping("/logout")
public String logout() {
    session.invalidate();  // 세션 삭제
    return "redirect:/user/sign-in";  // 로그인 페이지로 이동
}

4. 세션(HttpSession)과 DispatcherServlet의 역할

📌 세션은 어떻게 관리될까?

  • Spring Boot 애플리케이션에서 세션 정보는 웹 애플리케이션 서버(WAS, 예: Tomcat) 가 관리합니다.
  • 서버는 각 클라이언트마다 JSESSIONID 라는 고유한 세션 ID를 발급하여 사용자의 로그인 상태를 유지합니다.
  • HttpSession 객체를 통해 개발자는 세션 데이터를 저장하고 가져올 수 있습니다.
session.setAttribute("principal", user);  // 세션 저장
User user = (User) session.getAttribute("principal");  // 세션에서 데이터 가져오기
session.invalidate();  // 세션 삭제 (로그아웃)

📌 DispatcherServlet의 역할

  1. 클라이언트가 HTTP 요청을 보내면 DispatcherServlet이 요청을 수락합니다.
  2. 요청을 분석하여 적절한 컨트롤러(Controller)로 전달합니다.
  3. 컨트롤러는 서비스(Service) 계층을 호출하여 비즈니스 로직을 수행합니다.
  4. 최종적으로 응답(View 또는 JSON)을 생성하여 클라이언트에게 반환합니다.

5. Spring Boot 로그인 처리 흐름 정리

📌 로그인 요청이 처리되는 과정

  1. 사용자가 signin.jsp 에서 username, password를 입력하여 로그인 요청을 보냄
  2. DispatcherServlet이 요청을 수락하고, UserController 의 signInProc() 호출
  3. UserService 에서 로그인 검증 후, DB에서 사용자 정보 조회
  4. 로그인 성공 시, HttpSession에 사용자 정보 저장
  5. redirect:/main-page 를 통해 로그인 후 페이지로 이동
  6. 이후 요청마다 세션을 사용하여 로그인 상태 유지

6. 결론

Spring Boot 기반의 로그인 기능을 구현하면서 DispatcherServlet과 세션(HttpSession)의 동작 원리를 함께 이해할 수 있었습니다.

  • DispatcherServlet 은 요청을 분석하여 컨트롤러에 전달하고, 최종 응답을 반환하는 역할을 합니다.
  • 세션(HttpSession) 은 사용자의 로그인 정보를 유지하고, WAS가 이를 관리합니다.
  • 로그인 후 JSESSIONID를 사용하여 클라이언트의 로그인 상태를 유지합니다.
  • 로그아웃 시 session.invalidate() 를 호출하여 세션을 삭제합니다.

이러한 요청 처리 흐름을 이해하면, Spring Boot에서 인증 및 인가 시스템을 더욱 효과적으로 구현할 수 있습니다. 🚀

🚀다음 포스팅에서는 계좌생성에 대해서 적어볼게요! 🚀


회원가입이 궁금하다면??

 

Spring[Spring boot] Bank App - 회원가입(화면구현)

👨‍💻 지난 포스팅에서 회원 가입 로직을 설계하고 구현한 것에 이어, 이번에는 회원 가입 화면을 구현하고 H2 데이터베이스를 설정하여 초기 데이터를 셋팅하는 과정을 다뤄보겠습니다. 🚀

seohong.tistory.com

 

회원가입

회원가

'Spring' 카테고리의 다른 글

[Spring boot] Bank App - 계좌 목록 조회  (0) 2025.02.18
[Spring boot] Bank App - 계좌 생성  (0) 2025.02.17
Spring[Spring boot] Bank App - 회원가입(화면구현)  (2) 2025.02.15
[Spring boot] Bank App - 회원가입  (0) 2025.02.15
[Spring boot] Bank App - MyBatis 설정 (DB 접근 기술)  (0) 2025.02.14
'Spring' 카테고리의 다른 글
  • [Spring boot] Bank App - 계좌 목록 조회
  • [Spring boot] Bank App - 계좌 생성
  • Spring[Spring boot] Bank App - 회원가입(화면구현)
  • [Spring boot] Bank App - 회원가입
공돌이 출신 개발자
공돌이 출신 개발자
공돌이 출신 개발자입니다
  • 공돌이 출신 개발자
    공돌이 출신 개발자
    공돌이 출신 개발자
  • 전체
    오늘
    어제
    • 분류 전체보기 (124)
      • Database (0)
        • SQL (0)
        • 1일 1쿼리 (9)
      • Flutter (40)
        • Dart 언어 (18)
        • App (22)
      • Git (0)
      • Http 기초 지식 (14)
      • HTML5 & CSS3 (0)
      • Java (33)
      • JSP (0)
      • JavaScript (0)
      • Linux (0)
      • MSA (0)
      • Project (0)
      • React (0)
      • Spring (19)
      • 설치 메뉴얼 (1)
      • [Flutter] 프로젝트 (눈길) (8)
        • 작업일지 (8)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    프로젝트
    HTTP
    SQLD
    Java
    dart
    객체지향
    앱개발
    앱 개발
    1일1쿼리
    프로그래밍
    spring boot
    공부
    로그인
    플러터
    개발
    JAVA 기초
    회원가입
    블로그 만들기
    flutter
    객체
    android studio
    안드로이드
    SQL
    코딩
    클래스
    데이터
    Android
    메서드
    jsp
    안드로이드 앱 개발
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
공돌이 출신 개발자
[Spring boot] Bank App - 로그인 처리
상단으로

티스토리툴바