스프링 부트 백엔드 개발 강좌, 스프링 시큐리티로 로그인 로그아웃, 회원 가입 구현, 로그아웃 뷰 추가하기

본 강좌에서는 스프링 부트를 이용한 백엔드 개발을 진행하면서 주로 스프링 시큐리티를 통한 로그인/로그아웃 기능과 회원 가입 기능을 구현하는 방법에 대해 다루겠습니다. 또한, 로그아웃 뷰 추가 방법도 구체적으로 설명할 것입니다. 이 강좌는 기본적인 스프링 부트 프로젝트부터 시작하여, 점진적으로 필요한 기능을 추가해나가는 형태로 진행됩니다.

1. 스프링 부트 프로젝트 설정

스프링 부트는 자바 기반의 웹 애플리케이션을 빠르게 개발할 수 있도록 돕는 프레임워크입니다. 본 강좌에서는 최신 버전의 스프링 부트를 사용하여 프로젝트를 설정할 것입니다. 다음은 스프링 부트 프로젝트를 설정하는 단계입니다.

1. Spring Initializr를 사용하여 기본 프로젝트 생성
   - https://start.spring.io/로 이동합니다.
   - Project: Maven Project
   - Language: Java
   - Spring Boot: 최신 버전 선택
   - Project Metadata 설정:
     - Group: com.example
     - Artifact: demo
   - Dependencies 추가:
     - Spring Web
     - Spring Security
     - Spring Data JPA
     - H2 Database (내장 데이터베이스)
   - Generate 버튼 클릭하여 ZIP 파일 다운로드 후 압축 해제

1.1. IDE에서 프로젝트 열기

다운로드 받은 프로젝트를 IDE에서 열어줍니다. IntelliJ IDEA 혹은 Eclipse와 같은 IDE를 사용할 수 있습니다. 각 IDE에서 Maven을 통해 의존성 라이브러리를 자동으로 다운로드합니다.

2. 도메인 모델 설계

회원 가입과 로그인을 위해 사용자 정보를 저장할 도메인 모델을 설계합니다. User라는 클래스를 만들고, JPA를 활용하여 데이터베이스에 매핑합니다.

package com.example.demo.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String email;

    // Getter and Setter
}

2.1. User Repository 생성

사용자 데이터를 조작하기 위해 UserRepository 인터페이스를 생성합니다. JPA의 CrudRepository를 확장하여 기본적인 CRUD 기능을 사용할 수 있도록 합니다.

package com.example.demo.repository;

import com.example.demo.model.User;
import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository {
    User findByUsername(String username);
}

3. 스프링 시큐리티 설정

로그인 및 회원 가입 기능을 구현하기 위해 스프링 시큐리티를 설정합니다. 스프링 시큐리티는 애플리케이션의 보안 성능을 높여주는 강력한 프레임워크입니다.

3.1. Security Configuration 클래스

스프링 시큐리티의 설정을 위한 클래스를 생성합니다. SecurityConfig 클래스를 작성하여 인증 및 인가에 대한 기본적인 설정을 합니다.

package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // UserDetailsService와 PasswordEncoder 설정
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/register").permitAll() // 회원 가입 페이지는 모두 허용
                .anyRequest().authenticated() // 나머지 요청은 인증 필요
                .and()
            .formLogin()
                .loginPage("/login") // 커스터마이징된 로그인 페이지
                .permitAll()
                .and()
            .logout()
                .permitAll(); // 로그아웃을 허용
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

4. 회원 가입 기능 구현

회원 가입 기능을 위한 REST Controller와 회원 가입 뷰를 구현합니다. 사용자에게 입력받은 정보를 이용해 User 객체를 생성하고, 패스워드는 안전하게 해시 처리하여 저장해야 합니다.

4.1. User Controller 클래스 생성

package com.example.demo.controller;

import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/register")
public class UserController {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;

    @GetMapping
    public String showRegistrationForm(Model model) {
        model.addAttribute("user", new User());
        return "register";
    }

    @PostMapping
    public String registerUser(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword())); // 패스워드 해싱
        userRepository.save(user); // 사용자 저장
        return "redirect:/login"; // 회원 가입 후 로그인 페이지로 리디렉션
    }
}

4.2. 회원 가입 뷰

회원 가입을 위한 Thymeleaf 뷰를 생성합니다. 이는 HTML 파일로 존재하며, 사용자가 정보를 입력하고 제출할 수 있는 폼을 제공합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>회원 가입</title>
</head>
<body>
    <h1>회원 가입</h1>
    <form action="/register" method="post">
        <label for="username">사용자 이름</label>
        <input type="text" id="username" name="username" required>
        <label for="password">패스워드</label>
        <input type="password" id="password" name="password" required>
        <label for="email">이메일</label>
        <input type="email" id="email" name="email" required>
        <button type="submit">가입하기</button>
    </form>
</body>
</html>

5. 로그인 기능 구현

로그인 기능을 위해 추가적인 컨트롤러와 뷰를 설정합니다. 사용자가 로그인할 때 입력한 정보를 바탕으로 인증을 진행합니다.

5.1. 로그인 페이지 설정

로그인 페이지를 위한 HTML 파일을 생성합니다. 사용자 이름과 패스워드를 입력받는 필드가 포함되어야 합니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>로그인</title>
</head>
<body>
    <h1>로그인</h1>
    <form action="/login" method="post">
        <label for="username">사용자 이름</label>
        <input type="text" id="username" name="username" required>
        <label for="password">패스워드</label>
        <input type="password" id="password" name="password" required>
        <button type="submit">로그인</button>
    </form>
    <a href="/register">회원 가입하러 가기</a>
</body>
</html>

6. 로그아웃 구현 및 뷰 추가

로그아웃 기능을 추가합니다. 로그아웃 후에는 메인 화면으로 리디렉션되도록 설정합니다.

6.1. 로그아웃 기능 설정

이미 설정된 HttpSecurity를 통해 로그아웃 기능은 쉽게 구현할 수 있습니다. 사용자가 로그아웃을 요청하면, 인증 세션이 무효화되며 리디렉션됩니다.

6.2. 로그아웃 후 리디렉션 페이지 생성

로그아웃 후 사용자가 볼 수 있는 페이지를 만들어줍니다. 여기서 적절한 메시지를 제공할 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>로그아웃</title>
</head>
<body>
    <h1>로그아웃 되었습니다.</h1>
    <p>다시 로그인하려면 아래 버튼을 클릭하세요.</p>
    <a href="/login">로그인 페이지로 이동</a>
</body>
</html>

7. 결론 및 다음 단계

이번 강좌에서는 스프링 부트를 활용하여 백엔드 개발을 진행하며 스프링 시큐리티로 로그인 및 로그아웃 기능, 회원 가입 기능을 구현하였습니다. 이러한 기초적인 기능들을 익히고 나면, 추가적으로 JWT(JSON Web Token) 기반의 인증, OAuth2를 이용한 소셜 로그인, 비밀번호 재설정 기능 등 보다 확장된 기능을 구현하는 것도 가능합니다.

또한, 이 강좌를 바탕으로 RESTful API를 통해 웹 프론트엔드와의 통신, 클라우드 배포, 테스트 및 배포 자동화 등의 고급 주제에 대해서도 학습해보시기를 권장합니다.

여러분의 개발 여정에 도움이 되었길 바라며, 질문이나 더 궁금한 사항이 있으시다면 댓글로 남겨주세요. 감사합니다!