스프링 부트 백엔드 개발 강좌, OAuth2로 로그인 로그아웃 구현, 글 수정, 삭제, 글쓴이 확인 로직 추가하기

목차

  1. 소개
  2. 스프링 부트 소개
  3. OAuth2 개요
  4. 로그인/로그아웃 구현
  5. 글 수정 및 삭제 기능 구현
  6. 글쓴이 확인 로직 추가
  7. 결론

소개

오늘은 스프링 부트를 사용하여 백엔드 애플리케이션을 개발하는 방법을 알아보겠습니다. 이번 강좌에서는 OAuth2를 통한 로그인 및 로그아웃 구현 방법과 글 수정 및 삭제 기능, 그리고 글쓴이 확인 로직을 추가하는 방법을 다룰 것입니다. 이 과정을 통해 스프링 부트의 다양한 기능을 활용하는 방법을 배울 수 있습니다.

스프링 부트 소개

스프링 부트는 스프링 프레임워크를 기반으로 한 간편한 애플리케이션 개발을 지원하는 프레임워크입니다. 복잡한 설정 없이 빠르게 애플리케이션을 구축할 수 있도록 도와주며, 다양한 내장 서버(예: Tomcat, Jetty 등)를 지원합니다. 스프링 부트의 주요 이점은 다음과 같습니다:

  • 빠른 시작: 초기 설정이 간편하여 개발 시간을 단축할 수 있습니다.
  • 자동 구성: 필요한 라이브러리와 의존성을 자동으로 설정해줍니다.
  • 내장 서버: 별도의 서버 설정 없이 로컬에서 쉽게 애플리케이션을 실행할 수 있습니다.
  • 강력한 커뮤니티: 활발한 사용자와 풍부한 자료가 많아 학습과 문제 해결에 도움이 됩니다.

OAuth2 개요

OAuth2는 클라이언트 애플리케이션이 사용자 자원에 접근할 수 있도록 권한을 부여하는 인증 프로토콜입니다. OAuth2를 통해 사용자는 애플리케이션에 대한 접근 권한을 안전하게 관리할 수 있습니다. OAuth2는 여러 인증 방식(예: Authorization Code, Implicit, Resource Owner Password Credentials 등)을 지원하며, 일반적으로 웹 애플리케이션과 모바일 애플리케이션에서 많이 사용됩니다.

이번 강좌에서는 OAuth2를 사용하여 사용자 인증을 구현하고, 이 인증 정보를 가지고 글을 작성, 수정, 삭제하는 기능을 추가할 것입니다. 우리는 기본적으로 Authorization Code Grant 방식을 사용할 것입니다.

로그인/로그아웃 구현

스프링 부트 애플리케이션에 OAuth2 기반의 로그인/로그아웃 기능을 구현하는 방법을 살펴보겠습니다. 이 과정에서 스프링 시큐리티(Spring Security)를 사용하여 인증 및 권한 부여를 처리할 것입니다. 다음 단계로 진행해 보겠습니다.

1. 의존성 추가

우선, Maven pom.xml 파일에 필요한 의존성을 추가해야 합니다. 다음의 의존성을 추가하세요:


      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-oauth2-client</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
    

2. application.yml 설정

이제 oauth2 클라이언트 정보를 설정해야 합니다. src/main/resources/application.yml 파일에 다음과 같이 설정하세요:


    spring:
      security:
        oauth2:
          client:
            registration:
              google:
                client-id: YOUR_CLIENT_ID
                client-secret: YOUR_CLIENT_SECRET
                scope: profile, email
                redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
                authorization-grant-type: authorization_code
            provider:
              google:
                authorization-uri: https://accounts.google.com/o/oauth2/auth
                token-uri: https://oauth2.googleapis.com/token
                user-info-uri: https://www.googleapis.com/userinfo/v2/me
    

3. SecurityConfig 클래스 작성

안전한 애플리케이션 구성을 위해 SecurityConfig 클래스를 생성합니다. 이 클래스는 스프링 시큐리티의 보안 설정을 담당합니다.


    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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;

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers("/", "/login", "/error/**").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .oauth2Login()
                    .defaultSuccessUrl("/home", true)
                    .failureUrl("/login?error");
        }
    }
    

4. 로그인 및 로그아웃 컨트롤러 구현

사용자가 로그인을 시도할 때 호출되는 HomeController 클래스를 생성하여 로그인 후의 흐름을 처리합니다.


    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;

    @Controller
    public class HomeController {

        @GetMapping("/")
        public String index() {
            return "index"; // index.html 페이지로 리턴
        }

        @GetMapping("/home")
        public String home() {
            return "home"; // home.html 페이지로 리턴
        }
    }
    

여기까지 입력하면 기본 로그인 및 로그아웃 기능이 구현되었습니다. 이제 사용자가 Google 계정을 통해 로그인할 수 있습니다.

글 수정 및 삭제 기능 구현

이제 기본적인 로그인/로그아웃 기능을 구현했으니, 다음으로는 글 작성, 수정 및 삭제 기능을 추가하겠습니다.

1. 글 게시를 위한 엔티티 및 리포지토리 작성

먼저, Post 엔티티와 이를 위한 JPA 리포지토리를 생성합니다.


    import javax.persistence.*;
    import java.time.LocalDateTime;

    @Entity
    public class Post {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        
        private String title;
        private String content;

        @ManyToOne
        @JoinColumn(name="user_id")
        private User user; // 작성자 정보

        private LocalDateTime createdAt;
        private LocalDateTime updatedAt;

        // getters and setters
    }
    

    import org.springframework.data.jpa.repository.JpaRepository;

    public interface PostRepository extends JpaRepository {
    }
    

2. 글 작성 및 수정 기능 구현

컨트롤러를 작성하여 글 작성 및 수정 기능을 처리합니다.


    import org.springframework.security.core.annotation.AuthenticationPrincipal;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;

    @Controller
    @RequestMapping("/posts")
    public class PostController {

        private final PostRepository postRepository;

        public PostController(PostRepository postRepository) {
            this.postRepository = postRepository;
        }

        @GetMapping("/new")
        public String newPost(Model model) {
            model.addAttribute("post", new Post());
            return "newpost"; // 글 작성 페이지
        }

        @PostMapping
        public String createPost(@ModelAttribute Post post, @AuthenticationPrincipal User user) {
            post.setUser(user); // 현재 로그인한 사용자 설정
            post.setCreatedAt(LocalDateTime.now());
            postRepository.save(post);
            return "redirect:/posts";
        }

        @GetMapping("/{id}/edit")
        public String editPost(@PathVariable Long id, Model model) {
            Post post = postRepository.findById(id).orElseThrow();
            model.addAttribute("post", post);
            return "editpost"; // 글 수정 페이지
        }

        @PostMapping("/{id}")
        public String updatePost(@PathVariable Long id, @ModelAttribute Post post) {
            post.setId(id);
            post.setUpdatedAt(LocalDateTime.now());
            postRepository.save(post);
            return "redirect:/posts";
        }
    }
    

3. 글 삭제 기능 구현

글 삭제를 위한 메소드도 PostController에 추가합니다.


    @DeleteMapping("/{id}")
    public String deletePost(@PathVariable Long id) {
        postRepository.deleteById(id);
        return "redirect:/posts";
    }
    

글쓴이 확인 로직 추가

마지막으로, 글쓴이 확인 로직을 추가하여 사용자가 자신이 작성한 글만 수정 또는 삭제할 수 있도록 설정합니다. 이를 위해 사용자가 로그인했을 때, 해당 사용자의 정보와 글의 작성자를 비교하는 로직을 추가합니다.


    @PostMapping("/{id}/edit")
    public String editPost(@PathVariable Long id, @AuthenticationPrincipal User user) {
        Post post = postRepository.findById(id).orElseThrow();
        if (!post.getUser().equals(user)) {
            throw new AccessDeniedException("이 글은 수정할 수 없습니다."); // 접근 거부 예외
        }
        return "editpost"; // 수정 페이지로 이동
    }

    @DeleteMapping("/{id}")
    public String deletePost(@PathVariable Long id, @AuthenticationPrincipal User user) {
        Post post = postRepository.findById(id).orElseThrow();
        if (!post.getUser().equals(user)) {
            throw new AccessDeniedException("이 글은 삭제할 수 없습니다."); // 접근 거부 예외
        }
        postRepository.deleteById(id);
        return "redirect:/posts";
    }
    

결론

이번 강좌에서는 스프링 부트를 사용하여 OAuth2 기반의 로그인 및 로그아웃 기능을 구현하고, 글 작성, 수정, 삭제 기능을 추가하는 방법을 배웠습니다. 또한, 글쓴이 확인 로직을 통해 사용자가 자신의 글만 수정 또는 삭제할 수 있도록 하는 안전 장치를 마련했습니다. 이러한 과정을 통해 스프링 부트와 OAuth2의 기본적인 사용법을 익힐 수 있었으며, 실제 애플리케이션 개발에 필요한 기초 지식을 쌓을 수 있었습니다.

앞으로도 스프링 부트를 활용한 다양한 기능에 대해 학습하며, 더 나아가 실력이 향상되기를 바랍니다. 여러분의 개발 여정에 행운을 빕니다!