개발스토리지😃

[Spring] @Component, @Controller, @Service, @Repository 본문

프레임워크/스프링

[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!");
    }
}

Component.Class


 

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로 이동
    }
}

 

Controller.Class


 

4. @Service

  • 비즈니스 로직을 담당
  • 서비스 역할이라는 의미를 명확히 하기 위해 사용
import org.springframework.stereotype.Service;

@Service
public class UserService {

    public String processUserData(String username) {
        // 비즈니스 로직: 사용자 이름을 가공하여 반환
        return "Welcome, " + username.toUpperCase() + "!";
    }
}

Service.Class


 

 

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");
    }
}

 

Repository.Class