@Service의 짝꿍들

키요·2025년 9월 1일

공부

목록 보기
19/32

이제 막 스프링의 @Service가 비즈니스 로직을 처리하는 핵심 역할이라는 것을 배웠습니다. 그런데 실제 코드를 보다 보면, @Service 혼자 쓰이는 경우는 드문 것 같더라고요.

그래서 앞으로 배우게 될, @Service와 함께 쓰이며 강력한 기능을 더해주는 '짝꿍' 어노테이션들이 각각 어떤 역할을 하는지 미리 예습하는 느낌으로 정리해보려고 합니다.

1. @Autowired: 기본 중의 기본, 부품 주입 요청

이건 이제 막 배운 내용인데, 서비스가 일을 하려면 @Repository 같은 다른 부품이 필요하고, @Autowired는 바로 그 부품을 주입해달라는 '기본적인 요청'이죠. 앞으로 스프링을 사용하는 내내 계속 마주칠 가장 기본적인 짝꿍인 것 같습니다.

2. @Transactional: 데이터 일관성을 지키는 파수꾼

서비스 로직에서 여러 DB 작업이 있을 때 데이터 일관성을 지켜주는 아주 중요한 기능이라고 들었습니다. 'All-or-Nothing' 원칙을 보장해준다고 하는데, 앞으로 가장 중요하게 배울 기능 중 하나일 것 같습니다.

3. @Cacheable: 성능을 높이는 똑똑한 기억력

찾아보니 성능을 위한 어노테이션도 있었습니다. @Cacheable은 자주 요청되는 메서드의 결과를 기억(캐시)해두었다가, DB까지 가지 않고 바로 결과를 돌려주는 역할을 한다고 합니다. 성능 튜닝할 때 꼭 필요해 보입니다.

4. @Async: 사용자를 기다리지 않게 하는 배려

이건 좀 더 신기한 기능인데, @Async는 오래 걸리는 작업을 별도의 '뒷주방'에서 비동기적으로 처리하게 만드는 기능이라고 합니다. 덕분에 사용자는 기다릴 필요 없이 바로 다음 화면으로 넘어갈 수 있다고 하네요. 사용자 경험을 좋게 만들려면 꼭 알아둬야겠습니다.

5. @Scheduled: 정해진 시간에 스스로 일하는 일꾼

심지어 정해진 시간에 코드를 실행시키는 어노테이션도 있었습니다. @Scheduled를 사용하면 '매일 자정에 이 작업을 실행해줘' 같은 예약이 가능하다고 합니다. 주기적인 데이터 정리나 리포트 생성 같은 배치(Batch) 작업에 유용하게 쓰일 것 같습니다.


종합 예시: 이 어노테이션들이 실제로 쓰이는 모습

이론적인 설명들을 보고 나니, 이 어노테이션들이 실제 코드에서 어떻게 어우러지는지 궁금해졌습니다. 간단한 '회원가입 서비스'를 상상하며 코드를 만들어보면 다음과 같을 것 같습니다.

@Service // 1. 이 클래스는 서비스 계층의 컴포넌트임을 선언
public class UserServiceImpl implements UserService {

    @Autowired // 2. 다른 컴포넌트(Repository)를 주입받음
    private UserRepository userRepository;

    @Autowired
    private EmailService emailService;

    @Override
    @Transactional // 3. 이 메서드는 하나의 트랜잭션으로 동작함
    public void registerUser(User user) {
        userRepository.save(user); // DB 작업 1
        emailService.sendWelcomeEmail(user.getEmail()); // 비동기 작업 호출
    }

    @Override
    @Cacheable("users") // 4. 캐싱 기능 적용
    public User findUserById(Long id) {
        return userRepository.findById(id);
    }
}

@Service
public class EmailServiceImpl implements EmailService {
    
    @Async // 5. 이메일 발송은 비동기적으로(백그라운드에서) 처리
    public void sendWelcomeEmail(String email) {
        // ... 시간 걸리는 이메일 발송 로직 ...
    }
}
  • @Service, @Autowired: UserServiceImplEmailServiceImpl은 핵심 부품(Bean)으로 등록되고, UserServiceImplUserRepositoryEmailService를 주입받아 사용합니다.
  • @Transactional: registerUser 메서드에서 만약 save는 성공했는데 sendWelcomeEmail에서 오류가 발생하면, 저장되었던 회원 정보까지 다시 롤백되어 데이터 일관성을 지켜줍니다.
  • @Cacheable: findUserById를 통해 한번 조회된 유저는 캐시에 저장됩니다. 다음에 똑같은 ID로 조회하면 DB를 거치지 않고 캐시에서 바로 응답하여 훨씬 빠릅니다.
  • @Async: registerUsersendWelcomeEmail을 호출해도, 이메일 발송이 끝날 때까지 기다리지 않습니다. 이메일은 뒷주방(@Async)에서 천천히 보내고, 사용자에게는 회원가입 성공 응답을 즉시 보낼 수 있습니다.

예습을 마치며

아직 모든 어노테이션을 직접 사용해본 것은 아니지만, 미리 훑어보니 @Service가 단순히 로직을 담는 공간을 넘어, 여러 강력한 기능들을 조합하는 '지휘 본부' 역할을 한다는 것을 알게 되었습니다.

앞으로 이 기능들을 하나씩 배우고 적용해보면서, 더 견고하고 효율적인 애플리케이션을 만드는 방법을 익혀나가야겠습니다.

profile
운도 실력

0개의 댓글