Spring Framework의 확장인 SpringBoot는 Spring 애플리케이션을 빠르고 쉽게 구성할 수 있도록 도와주는 도구입니다. 복잡한 설정을 간소화하고 개발자가 비즈니스 로직에 집중할 수 있게 해주는 SpringBoot의 주요 특징과 사용법을 알아보겠습니다.
SpringBoot 프로젝트 구조
SpringBoot 애플리케이션은 일관된 디렉토리 구조를 가지고 있어 프로젝트 관리와 개발을 용이하게 합니다.
- src/main/java
- 일반적인 자바 코드가 위치하는 디렉토리
- 컨트롤러, 서비스, 모델 등 애플리케이션의 핵심 로직이 이곳에 위치
- 패키지 구조를 통해 관심사를 분리하고 코드를 체계적으로 관리
- src/main/resources
- 자바 이외의 리소스 파일들이 위치하는 디렉토리
- 정적 웹 리소스 (static): CSS, JavaScript, 이미지 등 정적 파일
- 동적 웹 리소스 (templates): Thymeleaf, JSP 등 템플릿 파일
- 애플리케이션 설정 정보: application.properties 또는 application.yml 파일
- src/test/java
- 테스팅 관련 소스 코드 및 리소스
- 단위 테스트, 통합 테스트를 위한 코드
- 테스트 환경 설정 파일
이 구조는 Maven 또는 Gradle 빌드 시스템의 표준 레이아웃을 따르며, SpringBoot는 이 구조를 기반으로 자동 설정 기능을 제공합니다.
Application 설정 정보
SpringBoot에서는 application.properties 또는 application.yml 파일을 통해 애플리케이션의 설정 정보를 관리합니다. 두 형식 모두 같은 기능을 제공하지만, YAML 형식은 계층적 구조를 더 직관적으로 표현할 수 있다는 장점이 있습니다.
Properties 파일 작성법
- property와 value는 = 로 구분
- 계층 구조는 .(점)을 사용하여 표현
- 리스트 값은 쉼표로 구분
설정 값 활용하기
- @Value("${property_name}") 애노테이션을 사용해 자바 코드에서 설정 값 참조
- 설정된 스칼라 값을 자동으로 적절한 타입으로 변환 지원
- 리스트, 맵 등의 복합 데이터 타입도 지원
Built-in Properties
SpringBoot는 기본 설정 값을 제공하며, 필요에 따라 재정의할 수 있습니다.
- server.port: 서버 포트 설정 (기본값: 8080)
- spring.datasource.*: 데이터베이스 연결 설정
- logging.level.*: 패키지별 로깅 레벨 설정
- 예: logging.level.org.springframework=DEBUG
설정 예제
@SpringBootTest
class Fw03ApplicationTests {
private final Logger log = LoggerFactory.getLogger(Fw03ApplicationTests.class);
@Value("${service.manager.name}")
private String managerName;
@Value("${service.manager.age}")
private int managerAge;
@Value("${service.roles}")
private List<String> roles;
@Test
void contextLoads() {
Assertions.assertEquals(managerAge, 30);
Assertions.assertEquals(managerName, "hong");
log.debug("debug: {}", roles);
}
}
위 코드에 대응하는 application.properties
spring.application.name=FW_03
service.manager.name=hong
service.manager.age=30
service.roles=admin, manager, guest
logging.level.com.ssafy=trace
logging.pattern.console=%msg%n
pom.xml
Maven 기반 SpringBoot 프로젝트의 의존성 관리는 pom.xml 파일을 통해 이루어집니다.
- SpringBoot 의존성 관리 시스템의 가장 큰 특징은 Spring에서 관리되는 라이브러리는 버전이 생략된다는 점입니다.
- spring-boot-starter-parent를 상속받음으로써 적절한 버전의 라이브러리 자동 선택
- 필요한 기능별로 스타터 패키지를 추가하여 관련 의존성을 한번에 가져올 수 있음
- spring-boot-starter-web: 웹 애플리케이션 개발 시 필요한 의존성
- spring-boot-starter-data-jpa: JPA를 이용한 데이터 접근 시 필요한 의존성
- spring-boot-starter-security: 보안 관련 기능 구현 시 필요한 의존성
스타터 의존성의 장점
- 필요한 라이브러리들의 호환되는 버전을 자동으로 관리
- 빌드 설정 간소화
- 검증된 라이브러리 조합으로 안정성 제공
@SpringBootApplication
@SpringBootApplication은 SpringBoot 애플리케이션의 시작점인 클래스에 선언하는 애노테이션으로, 내부적으로 세 가지 중요한 애노테이션을 포함하고 있습니다:
- @SpringBootConfiguration
- 내부적으로 @Configuration을 가짐
- 자바 기반 설정 클래스임을 나타냄
- 빈 등록을 처리할 수 있는 근거가 됨
- @EnableAutoConfiguration
- SpringBoot의 핵심 기능인 자동 설정 활성화
- 의존성에 근거하여 필요한 빈들을 자동으로 구성
- 예: spring-boot-starter-web 의존성이 있으면 Tomcat과 Spring MVC 관련 설정 자동 구성
- @ComponentScan
- 묵시적 빈 등록 형태로 선언된 컴포넌트를 스캔
- @Component, @Service, @Repository, @Controller 등이 붙은 클래스를 찾아 빈으로 등록
- @SpringBootApplication이 선언된 클래스의 하위 패키지를 자동으로 스캔
간단한 SpringBoot 애플리케이션 예제
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
이 간단한 코드만으로도 완전한 웹 애플리케이션을 구동할 수 있습니다. 내부적으로 SpringBoot는 다음과 같은 작업을 수행합니다
- 클래스패스에 있는 라이브러리를 기반으로 필요한 빈을 자동 구성
- 내장 서버(기본값: Tomcat) 실행
- 애플리케이션 컨텍스트 초기화
- 컴포넌트 스캔을 통한 빈 등록
@SpringBootTest
@SpringBootTest는 스프링 애플리케이션의 통합 테스트를 위한 애노테이션입니다. 테스트 시 전체 애플리케이션 컨텍스트를 로드하여 실제 환경과 유사한 조건에서 테스트를 수행할 수 있습니다.
주요 특징
- 전체 애플리케이션 컨텍스트 로드 지원
- 실제 애플리케이션과 동일한 환경에서 테스트 가능
- 테스트를 위한 별도의 설정 제공 가능
Slice Test 권장
전체 애플리케이션 컨텍스트를 로드하는 것은 테스트 시간이 오래 걸릴 수 있으므로, 필요한 모듈만 로딩하는 Slice Test를 권장합니다
- @WebMvcTest: 컨트롤러 레이어 테스트
- @DataJpaTest: JPA 관련 컴포넌트 테스트
- @JsonTest: JSON 직렬화/역직렬화 테스트
- @RestClientTest: REST 클라이언트 테스트
이러한 슬라이스 테스트를 활용하면 테스트 실행 속도를 높이고 특정 레이어에 집중하여 테스트할 수 있습니다.
Spring HRM (HTTP Request Management)
SpringBoot는 HTTP 요청을 처리하기 위한 다양한 기능을 제공합니다. 이를 통해 웹 애플리케이션의 요청-응답 흐름을 효율적으로 관리할 수 있습니다.
Bean의 Scope
스프링 컨테이너가 빈 객체를 어떻게 생성하고 언제까지 관리할 것인지 결정하는 것을 Bean의 Scope라고 합니다. 적절한 스코프 선택은 애플리케이션의 성능과 메모리 사용에 영향을 미칩니다.
- Singleton Scope
- 스프링 컨테이너당 하나의 인스턴스만 생성
- 비즈니스 로직을 재사용하기 위해 빈을 관리하는 스코프
- 빈의 기본 스코프
- 상태를 유지하지 않는(Stateless) 서비스나 DAO에 적합
- Prototype Scope
- 요청할 때마다 매번 새로운 빈 객체 생성
- 재사용되지 않으므로 빈으로 만들어야 하는지 고민 필요
- 상태를 가지는(Stateful) 객체에 적합
- Request Scope & Session Scope
- 웹 환경에서 사용되는 스코프
- Request Scope: HTTP 요청이 유지되는 동안 존재하는 빈
- Session Scope: HTTP 세션이 유지되는 동안 존재하는 빈
- 웹 애플리케이션에서 사용자별 데이터를 관리할 때 유용
스코프 지정은 @Scope 애노테이션을 통해 할 수 있습니다
@Component
@Scope("prototype")
public class PrototypeBeanExample {
// ...
}
Lombok
Lombok은 자바 개발 시 반복적인 코드(getter, setter, 생성자 등)를 애노테이션을 통해 자동 생성해주는 라이브러리입니다. SpringBoot와 함께 사용하면 보일러플레이트 코드를 크게 줄일 수 있습니다.
DTO 자동 생성
- @Data
- @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 모두 포함
- 많은 코드를 한번에 생성 → 생각지 못한 문제 발생 가능성 있음
- @ToString에서 순환 참조 문제가 발생할 수 있으므로 주의 필요
- @Builder
- 생성자의 파라미터를 바탕으로 빌더 패턴 형식으로 객체 설정 가능
- 클래스 레벨에서는 전체 필드를 포함하는 생성자 필요
- 생성자 레벨에서는 파라미터를 대상으로 빌더 구성
- 기본값을 유지하기 위해 @Builder.Default 활용 가능
Lombok 예제
@Data
@AllArgsConstructor
@NoArgsConstructor
@RequiredArgsConstructor
@Builder
public class Member {
private int mno;
private @NonNull String name;
private @NonNull String email;
private @NonNull String password;
private String role;
@ToString.Exclude // toString() 메서드에서 제외
@EqualsAndHashCode.Exclude // equals(), hashCode() 메서드에서 제외
@Builder.Default // 빌더 패턴 사용 시 기본값 유지
private List<Address> addresses = new ArrayList<>();
}
빌더 패턴 사용법
빌더 패턴을 사용하면 객체 생성 시 매개변수의 순서에 관계없이 직관적으로 값을 설정할 수 있습니다
Member member = Member.builder()
.mno(mno)
.name(name)
.email(email)
.password(pass)
.role(role)
.build();
MVC 패턴 구현
SpringBoot에서는 MVC(Model-View-Controller) 패턴을 구현하기 위한 다양한 컴포넌트를 제공합니다.
DAO (Data Access Object)
DAO는 데이터 접근 로직을 캡슐화하는 객체로, 데이터베이스 연산을 담당합니다.
- Stereotype Annotation 적용: @Repository
- JPA를 사용할 경우 JpaRepository 인터페이스를 상속받아 간편하게 구현 가능
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastName(String lastName);
Optional<User> findByEmail(String email);
}
Service
서비스 계층은 비즈니스 로직을 담당하며, DAO를 통해 데이터에 접근합니다.
- Stereotype Annotation 적용: @Service
- 의존성 주입을 통해 필요한 컴포넌트 사용
- @RequiredArgsConstructor 활용으로 final 필드 기반 생성자 자동 생성
@Service
@RequiredArgsConstructor
public class BasicAddressService implements AddressService {
private final AddressDao dao;
private final DBUtil util;
@Override
public List<Address> findByUserId(long userId) {
// 비즈니스 로직 구현
return dao.findByUserId(userId);
}
}
Controller
컨트롤러는 클라이언트의 요청을 받아 적절한 서비스로 전달하고, 결과를 응답으로 반환합니다.
- 기존 생성자 대신 의존성 주입을 활용
- @RequiredArgsConstructor를 사용하여 코드 간소화
@WebServlet(urlPatterns = "/auth")
@SuppressWarnings("serial")
@RequiredArgsConstructor
public class AuthController extends HttpServlet implements ControllerHelper {
private final MemberService mService;
private final AddressService aService;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 요청 처리 로직
}
}
RESTful API 개발 시에는 @RestController 애노테이션을 사용하는 것이 더 일반적입니다
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping
public List<UserDto> getAllUsers() {
return userService.findAll();
}
@PostMapping
public ResponseEntity<UserDto> createUser(@RequestBody UserDto userDto) {
UserDto created = userService.createUser(userDto);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
}
결론
SpringBoot는 Spring Framework의 복잡성을 크게 줄이고, 개발자가 비즈니스 로직에 집중할 수 있도록 도와줍니다. 자동 설정, 내장 서버, 간편한 의존성 관리 등의 기능을 통해 애플리케이션 개발 생산성을 크게 향상시킵니다.
또한 Lombok과 같은 도구를 함께 사용하면 반복적인 코드를 최소화하고, MVC 패턴을 효율적으로 구현할 수 있습니다. SpringBoot의 이러한 특징들은 현대적인 Java 웹 애플리케이션 개발에 있어 필수적인 요소로 자리 잡았습니다.
'BackEnd > Spring Framework' 카테고리의 다른 글
| Interceptor | ErrorPage | FileUpload (0) | 2025.04.30 |
|---|---|
| Spring MVC (0) | 2025.04.27 |
| Spring AOP (0) | 2025.04.26 |
| SLF4J와 JUnit (2) | 2025.04.24 |
| Spring Framework 개요 (0) | 2025.04.23 |