자바 개발자를 위한 온라인 리소스 및 교육 플랫폼 중 "Baeldung" 내에서 제공하는 Spring 관련 Tutorial에 대해 학습해보는 시간을 갖겠습니다.
해당 내용은 전적으로 Baeldung에 기재된 내용을 바탕으로 서술되어 있으며, 관련 내용 중 필자가 부족한 개념은 추가로 포스팅할 예정입니다.
📜 참고 포스팅
이번 포스팅에서는 가장 인기 있는 Java 프레임워크 중 하나인 Spring을 사용하는 이유들에 대해서 살펴보겠습니다.
기존에는 당연하게 사용해왔던 Spring 프레임워크를 "왜 사용할까" 라는 관점에서 한번 접근해보겠습니다.
굳이 Framework를 사용하지 않더라도 개발은 가능하지만, 사용함으로써 얻는 이점이 상대적으로 크기 때문에 사용하게 됩니다.
Framework를 사용하면 좋은 이점은 다음과 같습니다.
몇 가지 단점으로는 다음과 같습니다.
Spring은 Java Enterprise Edition이 빠르게 발전하였습니다.
Spring은 처음 Java용 IOC 컨테이너로 시작되었습니다. 현재까지도 Spring을 프로젝트의 핵심을 구성하는데 주로 사용합니다.
Spring Framework는 모듈 단위로 나누어져 있어 모든 애플리케이션에서 사용할 기능을 쉽게 선택하고 사용할 수 있습니다.
Spring이 강력한 것은 수 년에 걸쳐 Spring을 중심으로 성장하고 활발하게 발전하는 강력한 생태계 덕분입니다. 생태계는 Spring Project로 구성되어 있으며, 이는 Spring Framework를 기반으로 개발됩니다.
스프링을 활용하여 hello-wrold 라는 프로젝트를 생성해보겠습니다.
위 과정을 통해서 프로젝트를 생성하고 테스트까지 완성해보겠습니다.
기본적으로 Spring 프로젝트 생성 시, Spring Initializr 를 활용하여 생성해줍니다. Spring Initilaizr는 여러 종속성을 가지고 새로운 Spring 프로젝트를 생성하기 위한 간편 온라인 도구 입니다.
우선, 기본적으로 Spring Web, Spring data JPA, H2, Spring Security를 추가하여 프로젝트를 생성해줍니다.
간단한 JPA 엔티티로 Employee 라는 클래스를 정의하겠습니다.
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private String firstName;
@NotNull
private String lastName;
// Standard constructor, getters and setters
}
그 다음으로 JPA 레포지토리를 정의합니다.
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
List<Employee> findAll();
}
웹 애플리케이션으로 들어오는 요청을 라우팅하고 처리하기 위해서 Controller를 정의해줍니다.
@RestController
public class EmployeeController {
@Autowired
private EmployeeRepository repository;
@GetMapping("/employees")
public List<Employee> getAll() {
return repository.findAll();
}
}
위처럼 개발자가 하는 일은 클래스에 어노테이션을 추가해주고 각 핸들러 메서드와 함께 라우팅 메타 정보를 정의하는 것뿐입니다.
웹 애플리케이션을 동작하기 위한 코드들을 정의했습니다. 그 다음으로 직원 생성과 삭제 및 인증 과정을 처리하기 위해서는 Spring Security 프로젝트를 활용하면 쉽게 구현이 가능합니다.
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers(new AntPathRequestMatcher("/employees", "GET")).permitAll()
.anyRequest().authenticated()
).httpBasic(basic->basic.realmName("My Realm")
.authenticationEntryPoint((request, response, authException) -> {
System.out.println("인증 실패");
})
);
return http.build();
}
위처럼 정의하면, "employees" 경로로 GET 작업을 요청한 경우에만 인증 없이 허용 가능하도록 하는 선언적 방식의 코드입니다.
모든 작업을 수행했습니다. 이를 테스트 하기 위해서는 Spring에서 제공하는 REST controller에 대한 단위 테스트를 진행하면 됩니다.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class EmployeeControllerTests {
@Autowired
private MockMvc mvc;
@Test
@WithMockUser()
public void givenNoEmployee_whenCreateEmployee_thenEmployeeCreated() throws Exception {
mvc.perform(get("/employees").content(
new ObjectMapper().writeValueAsString(new Employee("First", "Last")))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status()
.isOk());
// .andExpect((ResultMatcher) jsonPath("$.firstName", is("First")))
// .andExpect((ResultMatcher) jsonPath("$.lastName", is("Last")));
}
// other tests as necessary
}
Spring에서는 위처럼 간단한 단위 또는 통합 테스트 작성 시 필요한 인프라(JUnit)를 기본적으로 제공합니다.
마지막으로, Spring 애플리케이션의 실행을 보면, Spring Boot에서는 Tomcat 서버가 내장되어 있습니다. 이는 Bootstrap의 일부이며, 미리 생성된 클래스와 임베디드 서버를 사용하여 애플리케이션을 시작하는데 필요한 모든 세부 정보를 포함합니다.
Spring은 다양한 구성 옵션과 규칙을 통해 개발자가 필요한 것을 정확하게 구성하기가 쉽습니다. 또한, 복잡한 Spring 프로젝트의 생성을 간단하게 만들었습니다.
Spring은 필요에 따라서 선택적으로 하나 이상의 Spring 프로젝트로 구성할 수 있습니다.
Spring은 Jakarta EE에서 제공하는 모든 기술을 지원하며 필요한 경우에 표준 사양에 대한 지원을 향상 시켜줍니다.
Spring은 핵심 기능의 테스트 관련 모듈을 지원하며, 단위 테스트를 상대적으로 간단하게 수행할 수 있습니다. 복잡한 MVC 시나리오를 위해 Mock 객체를 지원합니다.
오랜 역사를 통해서 일반적인 문제에 대한 기본 솔루션을 제공해주며, 대규모 조직 및 개인 개발자 간의 커뮤니티가 활성화 되어 있습니다.
위와 같은 이유에서 Spring 프레임워크를 사용하는 것이 Java 웹 애플리케이션 개발 시 유용하다는 것을 알 수 있습니다.