프레임워크/스프링
[Spring] @Component, @Controller, @Service, @Repository
believekim
2025. 4. 2. 11:46
Spring에서 자동으로 의존성 주입(DI)할 때 필수적인 어노테이션인
@Component, @Service, @Repository, @Controller를 알아보았다.
❗ @Controller, @Service, @Repository는 @Component를 모두 포함하여 정의된 어노테이션이다.
1. @Component 계열 어노테이션의 등장 배경
- XML 기반 설정의 한계
스프링이 처음 등장했을 때는 applicationContext.xml 같은 XML 파일을 사용해서 스프링 빈을 등록
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="com.example.service.UserService"/> <bean id="userRepository" class="com.example.repository.UserRepository"/> </beans>
문제점:
1. 빈 등록의 번거로움 → 클래스 하나 추가할 때마다 XML 수정 필요
2. 가독성이 떨어짐 → 설정 파일이 커질수록 관리가 어려워짐
3. DI(의존성 주입) 설정이 복잡 → 각 클래스 간의 관계를 XML에서 따로 지정
스프링 2.5부터는 XML을 최소화하고, 애너테이션을 이용한 빈 등록 방식이 추가
import org.springframework.stereotype.Component; @Component public class UserService { public String getUser() { return "사용자 정보 반환"; } }
장점:
1. 코드 내부에서 직접 빈을 선언할 수 있어서 가독성이 향상
2. XML 설정 없이도 스프링 빈을 등록 가능
3. 자동 스캔(@ComponentScan) 기능을 통해 클래스들을 자동으로 빈으로 등록
@Component만으로는 역할을 구분하기 어려웠기에 Spring 3.0 이후 역할별 어노테이션이 추가
장점:
어노테이션 역할 XML 설정 방식과 비교 @Component 기본적인 빈 등록 <bean class="com.example.MyClass"/> @Controller 비즈니스 로직 담당 <bean class="com.example.service.MyService"/> @Service DAO(데이터 접근) 계층 <bean class="com.example.repository.MyRepository"/> @Repository 웹 컨트롤러 계층 <bean class="com.example.controller.MyController"/>
1. 역할 구분 → 코드 가독성 향상
2. AOP 적용 시, 역할별 기능을 추가하기 용이
3. 스프링이 자동으로 처리하는 기능이 추가됨 (예: @Repository는 예외 변환)
2. @Component
- 가장 기본적인 어노테이션으로 싱글톤 클래스 빈을 생성
- 클래스에 @Component를 붙이면 스프링이 자동으로 빈으로 등록
- 메서드에서는 @Bean을 사용
import org.springframework.stereotype.Component;
@Component
public class SimpleComponent {
public void doSomething() {
System.out.println("Hello from SimpleComponent!");
}
}
3. @Controller
- 클라이언트의 요청을 받아 응답하는 컨트롤러 역할(MVC의 컨트롤러 역할)
- API를 만들 때는 @RestController를 사용
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.ui.Model;
@Controller
public class UserController {
@GetMapping("/users")
public String getUsers(Model model) {
model.addAttribute("users", List.of("User1", "User2", "User3"));
return "userList"; // userList.html로 이동
}
}
4. @Service
- 비즈니스 로직을 담당
- 서비스 역할이라는 의미를 명확히 하기 위해 사용
import org.springframework.stereotype.Service;
@Service
public class UserService {
public String processUserData(String username) {
// 비즈니스 로직: 사용자 이름을 가공하여 반환
return "Welcome, " + username.toUpperCase() + "!";
}
}
5. @Repository
- DAO(Data Access Object) 접근 역할
- JPA, MyBatis 같은 데이터베이스 처리와 관련된 예외를 Spring DataAccessException으로 변환
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.Map;
@Repository
public class UserRepository {
private final Map<String, String> userDatabase = new HashMap<>();
public UserRepository() {
// 더미 데이터 추가
userDatabase.put("john", "John Doe");
userDatabase.put("jane", "Jane Doe");
}
public String findUserByUsername(String username) {
// 데이터베이스에서 사용자 조회 (예제에서는 Map 사용)
return userDatabase.getOrDefault(username, "Unknown User");
}
}