Java/Spring

[Spring] 자주 사용하는 어노테이션 정리 및 예시

범데이 2025. 10. 28. 08:13

Spring Framework는 객체를 관리하고 계층 간 의존성을 자동 주입하기 위해 다양한 어노테이션을 제공한다.

이 중 실제 개발 현장에서 자주 사용되는 핵심 어노테이션들을 중심으로 설명한다.

 

1. @Component, @Service, @Repository, @Controller

이 네 가지는 Spring Bean 등록용 어노테이션이다.

즉, Spring이 해당 클래스를 컨테이너에서 관리하도록 등록하는 역할을 한다.

내부적으로는 모두 @Component를 기반으로 하며, 역할에 따라 의미만 다르다.

 

(1) @Component

가장 기본적인 Bean 등록용 어노테이션이다.

Helper, Util, Validator 등 특정 계층에 속하지 않는 일반 클래스를 Bean으로 등록할 때 사용한다.

import org.springframework.stereotype.Component;

@Component
public class FileNameHelper {

    public String makeFileName(String original) {
        return System.currentTimeMillis() + "_" + original;
    }
}

 

이후 다른 클래스에서 자동 주입하여 사용할 수 있다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class FileService {

    private final FileNameHelper fileNameHelper;

    @Autowired
    public FileService(FileNameHelper fileNameHelper) {
        this.fileNameHelper = fileNameHelper;
    }

    public void saveFile(String fileName) {
        String newName = fileNameHelper.makeFileName(fileName);
        System.out.println("저장 파일명: " + newName);
    }
}

 

 

 

(2) @Service

비즈니스 로직을 담당하는 계층에 사용한다.

트랜잭션이 걸리거나 여러 DAO를 조합하는 등의 처리를 담당한다.

코드상 기능은 @Component와 동일하지만, 역할을 명확히 구분하기 위해 사용한다.

import org.springframework.stereotype.Service;

@Service
public class MemberService {

    public String getMemberGrade(int point) {
        if (point > 1000) return "VIP";
        if (point > 500) return "GOLD";
        return "SILVER";
    }
}

 

 

(3) @Repository

데이터베이스와 직접 통신하는 DAO 계층에 사용한다.

@Repository는 예외 변환 기능이 내장되어 있어, JDBC나 MyBatis, JPA에서 발생한 예외를

Spring 공통 예외(DataAccessException)로 변환해준다.

import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.Map;

@Repository
public class MemberRepository {

    private static final Map<Integer, String> MEMBER_DB = new HashMap<>();

    static {
        MEMBER_DB.put(1, "홍길동");
        MEMBER_DB.put(2, "이몽룡");
    }

    public String findMemberName(int id) {
        return MEMBER_DB.get(id);
    }
}

 

 

(4) @Controller / @RestController

Controller 계층은 클라이언트의 요청을 받아 처리하는 역할을 한다.

@Controller는 View(JSP, Thymeleaf 등) 를 반환하고,

@RestController는 JSON 데이터를 직접 반환한다.

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MemberViewController {

    @GetMapping("/member/view")
    public String showMember(Model model) {
        model.addAttribute("name", "홍길동");
        return "memberView"; // memberView.jsp
    }
}

 

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;

@RestController
public class MemberApiController {

    @GetMapping("/api/member")
    public Member getMember() {
        return new Member("홍길동", "VIP");
    }
}

 

public class Member {
    private String name;
    private String grade;

    public Member(String name, String grade) {
        this.name = name;
        this.grade = grade;
    }

    // getter, setter 생략
}

 

 

 

2. @Autowired와 의존성 주입(Dependency Injection)

@Autowired는 Bean을 자동 주입해주는 어노테이션이다.

즉, @Component, @Service, @Repository, @Controller로 등록된 Bean을

필요한 곳에 가져다 쓸 수 있게 해준다.

 

필드 주입 (비권장)

@Autowired
private MemberService memberService;

간단하지만 테스트나 유지보수 시 불편하므로 권장되지 않는다.

 

 

생성자 주입 (권장)

@Service
public class OrderService {

    private final MemberService memberService;

    @Autowired
    public OrderService(MemberService memberService) {
        this.memberService = memberService;
    }
}

 

Spring 4.3 이상부터는 생성자가 하나뿐이면 @Autowired를 생략할 수 있다.

 

 

Lombok과 함께 사용 (@RequiredArgsConstructor)

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class OrderService {

    private final MemberService memberService;

    public void process() {
        System.out.println(memberService.getMemberGrade(700));
    }
}

 

 

 

3. @Value (프로퍼티 값 주입)

Spring의 설정 파일(application.properties 또는 .yml)에 정의된 값을 클래스에 주입할 수 있다.

# application.properties
app.title=FOO PORTAL

 

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class AppInfo {

    @Value("${app.title}")
    private String title;

    public void printTitle() {
        System.out.println("애플리케이션 이름: " + title);
    }
}

 

 

 

4. @RequestMapping 계열 (요청 매핑)

Spring MVC에서 요청 URL을 메서드에 연결할 때 사용한다.

HTTP Method별로 축약형 어노테이션이 존재한다.

 

예시 1. @RequestMapping

@Controller
@RequestMapping("/member")
public class MemberController {

    @RequestMapping("/list")
    public String listMembers() {
        return "memberList";
    }
}

 

 

예시 2. HTTP 메서드별 축약형

@RestController
@RequestMapping("/api/member")
public class MemberRestController {

    @GetMapping("/{id}")
    public String getMember(@PathVariable int id) {
        return "회원번호: " + id;
    }

    @PostMapping
    public String addMember(@RequestParam String name) {
        return "등록된 회원: " + name;
    }
}

 

 

 

5. @Transactional

DB 변경이 포함된 비즈니스 로직에 트랜잭션을 적용한다.

메서드 내 예외 발생 시 자동으로 롤백이 수행된다.

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class PaymentService {

    @Transactional
    public void pay(Long memberId, int amount) {
        // 1. 잔액 차감
        // 2. 결제 내역 기록
        // 예외 발생 시 모든 작업이 롤백됨
        System.out.println("회원 " + memberId + "에게 " + amount + "원 결제 처리 완료");
    }
}

 

 


마무리

Spring에서 자주 사용하는 어노테이션은 단순히 “문법”이 아니라,

프로젝트 구조를 명확히 하고 계층 간 책임을 분리하기 위한 약속이다.

  • @Component : 범용 Bean 등록
  • @Service : 비즈니스 로직
  • @Repository : 데이터 접근
  • @Controller / @RestController : 요청 처리
  • @Autowired, @Value : 의존성 및 설정값 주입
  • @Transactional : 트랜잭션 처리

각 어노테이션은 “Spring이 언제, 어떻게 객체를 관리할지” 결정하는 핵심 도구이며,

이 개념만 정확히 이해해도 대부분의 Spring 프로젝트 구조를 파악할 수 있다.

728x90
반응형