스프링 웹 MVC와 RESTful API 개발 방법

스프링 웹 MVC와 RESTful API 개발 방법

Spring Framework

스프링 프레임워크는 자바 기반의 오픈 소스 프레임워크로, 엔터프라이즈급 애플리케이션 개발을 위한 다양한 모듈과 라이브러리를 제공합니다. 이 중 스프링 웹 MVC와 RESTful API 개발 방법에 대해 알아보겠습니다.

스프링 웹 MVC 개발 방법

스프링 웹 MVC는 Model-View-Controller 아키텍처 패턴을 기반으로 하는 웹 애플리케이션 개발을 위한 프레임워크입니다. 스프링 웹 MVC를 이용하면 웹 애플리케이션의 구조를 쉽게 설정하고 관리할 수 있습니다.

스프링 웹 MVC 프로젝트 생성

스프링 웹 MVC 프로젝트를 생성하려면 스프링부트를 이용하면 쉽게 생성할 수 있습니다. 스프링부트를 이용하는 경우 spring-boot-starter-web 의존성을 추가하면 스프링 웹 MVC와 필요한 의존성들이 함께 추가됩니다.


    org.springframework.boot
    spring-boot-starter-web

스프링 웹 MVC 설정

스프링 웹 MVC는 @Controller@RestController 어노테이션을 이용하여 컨트롤러를 정의합니다. @Controller 어노테이션을 이용하면 View를 반환하고, @RestController 어노테이션을 이용하면 JSON이나 XML 형식의 데이터를 반환합니다.

@Controller
public class HomeController {
    @GetMapping("/")
    public String home() {
        return "index";
    }
}

위 코드는 "/" 요청을 처리하는 HomeController 클래스의 home() 메소드입니다. @GetMapping 어노테이션은 HTTP GET 요청을 처리하는 메소드를 지정합니다. 이 메소드는 "index" View를 반환합니다.

스프링 웹 MVC View 설정

스프링 웹 MVC에서 View는 Thymeleaf, JSP, Velocity 등의 템플릿 엔진을 이용하여 구현할 수 있습니다. 이 중 Thymeleaf는 HTML 템플릿 엔진으로, 스프링 웹 MVC에서 가장 많이 사용되는 템플릿 엔진입니다.

Thymeleaf를 사용하려면 spring-boot-starter-thymeleaf 의존성을 추가하고, application.properties 파일에 다음과 같이 설정합니다.

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

이제 src/main/resources/templates 디렉토리에 HTML 템플릿 파일을 작성하고 컨트롤러에서 반환하면 됩니다.


    Home

위 코드는 "message" 변수를 출력하는 간단한 HTML 템플릿입니다.

RESTful API 개발을 위한 스프링 설정

RESTful API는 Representational State Transfer의 약자로, HTTP 프로토콜을 이용하여 데이터를 전송하는 웹 서비스입니다. 스프링은 RESTful API를 개발하기 위한 다양한 기능을 제공합니다.

스프링 RESTful API 프로젝트 생성

스프링 RESTful API 프로젝트를 생성하려면 스프링부트를 이용하면 쉽게 생성할 수 있습니다. 스프링부트를 이용하는 경우 spring-boot-starter-webspring-boot-starter-data-jpa 의존성을 추가하면 스프링 웹 MVC와 데이터베이스 관련 의존성들이 함께 추가됩니다.


    org.springframework.boot
    spring-boot-starter-web

    org.springframework.boot
    spring-boot-starter-data-jpa

스프링 RESTful API 설정

스프링 RESTful API는 @RestController 어노테이션을 이용하여 컨트롤러를 정의합니다. @RestController 어노테이션을 이용하면 JSON이나 XML 형식의 데이터를 반환합니다.

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users")
    public List getUsers() {
        return userRepository.findAll();
    }

    @GetMapping("/users/{id}")
    public User getUserById(@PathVariable("id") Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
    }

    @PostMapping("/users")
    public User createUser(@RequestBody User user) {
        return userRepository.save(user);
    }

    @PutMapping("/users/{id}")
    public User updateUser(@PathVariable("id") Long id, @RequestBody User user) {
        User existingUser = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
        existingUser.setName(user.getName());
        existingUser.setEmail(user.getEmail());
        return userRepository.save(existingUser);
    }

    @DeleteMapping("/users/{id}")
    public ResponseEntity deleteUser(@PathVariable("id") Long id) {
        User existingUser = userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
        userRepository.delete(existingUser);
        return ResponseEntity.ok().build();
    }
}

위 코드는 RESTful API를 처리하는 UserController 클래스입니다. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping 어노테이션을 이용하여 HTTP GET, POST, PUT, DELETE 요청을 처리합니다.

스프링 RESTful API 예외 처리

RESTful API에서 예외 처리는 @ExceptionHandler 어노테이션을 이용하여 처리할 수 있습니다. 예외 처리는 컨트롤러에서 발생하는 예외를 처리하거나, 전역 예외 처리를 설정할 수 있습니다.

@RestControllerAdvice
public class RestExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity handleResourceNotFoundException(ResourceNotFoundException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity handleException(Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
    }
}

위 코드는 RESTful API에서 발생하는 ResourceNotFoundException 예외와 그 외의 예외를 처리하는 예외 처리 클래스입니다.

RESTful API 구현을 위한 스프링 애노테이션

스프링은 RESTful API 개발을 위한 다양한 애노테이션을 제공합니다. 이 애노테이션들을 이용하면 RESTful API를 더욱 쉽게 개발할 수 있습니다.

@RestController

@RestController 어노테이션은 @Controller@ResponseBody 어노테이션을 합친 것으로, 컨트롤러에서 반환하는 데이터가 HTTP 응답 본문으로 전송됩니다.

@RequestMapping

@RequestMapping 어노테이션은 컨트롤러의 요청 URL을 매핑합니다. 메소드에서 @RequestMapping 어노테이션을 지정하면 해당 메소드가 처리하는 요청 URL이 지정됩니다.

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping 어노테이션은 각각 HTTP GET, POST, PUT, DELETE 요청을 처리합니다.

@GetMapping("/users")
public List getUsers() {
    return userRepository.findAll();
}

위 코드는 HTTP GET 요청을 처리하는 메소드입니다. /users 요청에 대해 List 객체를 반환합니다.

@PathVariable

@PathVariable 어노테이션은 URL 경로에 포함된 변수를 메소드 매개변수로 전달합니다.

@GetMapping("/users/{id}")
public User getUserById(@PathVariable("id") Long id) {
    return userRepository.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("User not found"));
}

위 코드는 HTTP GET 요청을 처리하는 메소드입니다. /users/{id} 요청에 대해 @PathVariable("id")로 지정된 매개변수로 id 값을 전달받아 User 객체를 반환합니다.

@RequestBody

@RequestBody 어노테이션은 HTTP 요청 본문에 포함된 데이터를 메소드 매개변수로 전달합니다.

@PostMapping("/users")
public User createUser(@RequestBody User user) {
    return userRepository.save(user);
}

위 코드는 HTTP POST 요청을 처리하는 메소드입니다. /users 요청에 대해 @RequestBody로 지정된 매개변수로 User 객체를 전달받아 저장합니다.

스프링 시큐리티를 이용한 RESTful API 보안 구현

스프링 시큐리티는 스프링 기반의 보안 프레임워크로, 웹 애플리케이션에 대한 인증과 권한 부여를 처리합니다. 스프링 시큐리티를 이용하면 RESTful API에 대한 보안을 쉽게 구현할 수 있습니다.

스프링 시큐리티 설정

스프링 시큐리티를 사용하려면 spring-boot-starter-security 의존성을 추가하면 됩니다. 이 의존성을 추가하면 스프링 시큐리티가 기본 설정으로 적용됩니다.


    org.springframework.boot
    spring-boot-starter-security

스프링 시큐리티 인증

스프링 시큐리티 인증은 UsernamePasswordAuthenticationToken 객체를 이용하여 처리합니다. UserDetailsService 인터페이스를 구현하여 사용자 정보를 조회하고, PasswordEncoder 인터페이스를 구현하여 패스워드를 암호화합니다.

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found"));
        return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(), new ArrayList());
    }
}

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated().and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

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

위 코드는 스프링 시큐리티 인증과 인가를 처리하는 설정 클래스입니다. UserDetailsServiceImpl 클래스는 UserDetailsService 인터페이스를 구현하여 사용자 정보를 조회하고, SecurityConfig 클래스는 WebSecurityConfigurerAdapter 클래스를 상속받아 인증과 인가를 처리합니다.

스프링 시큐리티 인가

스프링 시큐리티 인가는 @PreAuthorize 어노테이션을 이용하여 처리할 수 있습니다. @PreAuthorize 어노테이션은 메소드 실행 전에 인가를 처리합니다.

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @PreAuthorize("hasAuthority('ADMIN')")
    @GetMapping("/users")
    public List getUsers() {
        return userRepository.findAll();
    }

    @PreAuthorize("hasAuthority('USER')")
    @GetMapping("/users/{id}")
    public User getUserById(@PathVariable("id") Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
    }
}

위 코드는 @PreAuthorize 어노테이션을 이용하여 인가를 처리하는 RESTful API 컨트롤러 클래스입니다. hasAuthority 메소드를 이용하여 권한을 지정하고, 메소드 실행 전에 인가를 처리합니다.

결론

스프링 웹 MVC와 RESTful API 개발 방법에 대해 알아보았습니다. 스프링을 이용하면 웹 애플리케이션과 RESTful API를 쉽게 개발할 수 있습니다. 스프링 시큐리티를 이용하면 RESTful API에 대한 보안을 쉽게 구현할 수 있습니다. 스프링을 이용한 웹 개발과 RESTful API 개발에 대해 더욱 깊이 있게 학습하고 개발해 보시기 바랍니다.