did_story
[Spring Boot / JAVA] Bean๋ถํฐ @Component, @Controller, @Service, @Repository ๊น์ง. ๋ณธ๋ฌธ
[Spring Boot / JAVA] Bean๋ถํฐ @Component, @Controller, @Service, @Repository ๊น์ง.
์ด์ ์์ 2025. 6. 30. 15:43์ฐ๋ฆฌ๊ฐ Spring์ ์ฌ์ฉํ๋ ์ด์ ๊ฐ ๋ฌด์์ผ๊น?
์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋!.
์คํ๋ง์ ์๋ฐ ๋น์ ์ฐพ์์ ApplicationContext๋ผ๊ณ ํ๋ ์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋ ์ค๋ธ์ ํธ์ ๋ฑ๋ก์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋๋ค๊ฐ ์ด๋ค ํ๋ก์ ํธ๊ฐ ํ์ํ๋ค๋ฉด ์์กดํ๋ ์ค๋ธ์ ํธ๋ฅผ ์ฐพ์์ ์ฐ๊ฒฐํด์ค๋ค.
์คํ๋ง์ ์ด๋ป๊ฒ ์๋ฐ ๋น์ ์ฐพ์๊ฐ์ง๊ณ ์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋์ ๋ฑ๋กํ๋๊ฑธ๊น???
๊ทธ๋ฆฌ๊ณ ์๋ฐ ๋น์ ๋ฌด์์ด๊ณ ์คํ๋ง ๋น์ ๋ฌด์์์ ์๋ฏธํ ๊น???
์๋ฐ ๋น(Java Bean)์ด๋??
์์ํ ์๋ฐ ํด๋์ค(Java class)์ด๋ค
์ฆ ์๋ฐ ์ธ์ด์์ ๋ฐ์ดํฐ ๊ฐ์ฒด๋ก ์ฌ์ฉํ๊ธฐ ์ํด์ ์ผ์ ํ ๊ท์น์ ๋ฐ๋ฅด๋ ํด๋์ค๋ฅผ ์๋ฏธํ๋ค.
DTO ํน์ VO์ ํํ๊ฐ Java Bean์ด๋ผ๊ณ ์๊ฐํ๋ฉด ์ฝ๋ค!
- getter / setter
- public์ no-argument ์์ฑ์
- ๋ชจ๋ ํ๋๋ private๋ก getter์ setter๋ฅผ ํตํด์๋ง ์ ๊ทผ ๊ฐ๋ฅ
getter์ setter, ์์ฑ์๋ฅผ ๊ฐ์ง๋ ํด๋์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ป์ผ๋ก ์ฌ์ฉ๋๋ ๋งํผ POJO(Plain Old Java Object)์ ๊ฑฐ์ ๋์ผํ ๊ฐ๋ ์ด๋ผ๊ณ ์ดํดํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
// Java Bean์ ์์
public class User {
// field๋ private๋ก ์ ์ธ
private String name;
private int age;
// ์์ฑ์
public User() {}
// getter
public String getName() {
return name;
}
// setter
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Spring Bean ์ด๋?
๋น(Bean)์ ์คํ๋ง ์ปจํ ์ด๋์ ์ํด ๊ด๋ฆฌ๋๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ํํธ์จ์ด ์ปดํฌ๋ํธ์ด๋ค.
์คํ๋ง IoC์ปจํ ์ด๋๊ฐ ๊ด๋ฆฌํ๋ Java ๊ฐ์ฒด๋ฅผ ๋ปํ๋ค
์ฌ๊ธฐ์ ํต์ฌ์ Spring์ด ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ค๋ ์ ์ด๋ค.
๋น์ ์ธ์คํด์คํ๋ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ฉฐ, ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๊ฐ์ฒด๋ฅผ ์คํ๋ง ๋น์ด๋ผ๊ณ ํฉ๋๋ค.
์ฝ๊ฒ ์ดํดํ์๋ฉด new ํค์๋ ๋์ ์ฌ์ฉํ๋ค๊ณ ๋ณด๋ฉด ํธํฉ๋๋ค.
์ ์ฌ์ฉํ์ง??
๊ฐ์ฅ ํฐ ์ด์ ๋ ์คํ๋ง ๊ฐ ๊ฐ์ฒด๊ฐ ์์กด ๊ด๊ณ๋ฅผ ๊ด๋ฆฌํ๋๋ก ํ๋ ๊ฒ์ ๊ฐ์ฅ ํฐ ๋ชฉ์ ์ด ์์ต๋๋ค. ๊ฐ์ฒด๊ฐ ์์กด๊ด๊ณ๋ฅผ ๋ฑ๋กํ ๋ ์คํ๋ง ์ปจํ ์ด๋์์ ํด๋น ๋น์ ์ฐพ๊ณ , ๊ทธ ๋น๊ณผ ์์กด์ฑ์ ๋ง๋ค๋๋ก ํฉ๋๋ค.
๊ทธ๋ผ ๋์์์, @Component, @Controller, @Service, @Repository ๊ฐ ๋ฌด์์ด์ง?!
- @Component๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํํ์ ์ด๋ ธํ ์ด์ ์ผ๋ก, ํน์ ์ญํ ์ ์ข ์๋์ง ์๋ ์ผ๋ฐ์ ์ธ Spring Bean์ ๋ํ๋ ๋๋ค. ๊ณตํต ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ์ ํธ๋ฆฌํฐ ํด๋์ค๋, ํน์ ๊ณ์ธต์ ์ํ์ง ์๋ ์ผ๋ฐ์ ์ธ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- @Service๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ํํ๋ ํด๋์ค์ ์ฌ์ฉ๋๋ฉฐ ์๋น์ค ๋ ์ด์ด์ Bean์ ๋ํ๋ ๋๋ค.
- @Controeller๋ Spring MVC์์ ์น ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ ํด๋์ค์ ์ฌ์ฉ๋๋ฉฐ ํ๋ ์ ํ ์ด์ ๋ ์ด์ด์ Bean์ ๋ํ๋ ๋๋ค.
- @Repository๋ ๋ฐ์ดํ๋ฒ ์ด์ค์ ์ํธ์์ฉ์ ์ํํ๋ ํด๋์ค์ ์ฌ์ฉ๋๋ฉฐ, ๋ฐ์ดํฐ ์์ธ์ค ๋ ์ด์ด์ Bean์ ๋ํ๋ ๋๋ค.
@Controller, @Repository ๋์ @Component ์ฌ์ฉํ๋ฉด ์๋๋์?
Spring 6(Spring Boot 3) ์ด์ ๋ฒ์ ์์๋ @Component + @RequestMapping์ผ๋ก๋ Bean ๋ฐ ํธ๋ค๋ฌ๋ก ๋ฑ๋ก๋์์ต๋๋ค. ํ์ง๋ง Spring 6 ์ดํ ๋ถํฐ @Controller ์ธ์๋ ํธ๋ค๋ฌ๋ก ๋ฑ๋กํ์ง ์์ ์น ์์ฒญ์ ์ ์์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค.
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
...
@Override
protected boolean isHandler(Class<?> beanType) {
return AnnotatedElementUtils.hasAnnotation(beanType, Controller.class); // ์ปจํธ๋กค๋ฌ ์ ๋ํ
์ด์
์ธ์ง ํ์ธ
}
...
}
@Repository๋ฅผ @Component๋ก ๋์ฒดํ ๊ฒฝ์ฐ, PersistenceExceptionTranslationPostProcessor์ ์ํด ์์ธ๊ฐ DataAccessException์ผ๋ก ๋ณํ๋์ง ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ๋ฐ์ดํฐ ์ก์ธ์ค ๊ณ์ธต์์ ๋ฐ์ํ๋ ์์ธ ์ฒ๋ฆฌ์ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค. ⇒ why? @Component์๋ ์์ธ ๋ณํ์ ์ํ ํน์ ๊ธฐ๋ฅ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์กฐ๊ธ๋ ์ค๋ช ์ ํ์๋ฉด,
Spring์ JPA, JDBC, Hibernate ๋ฑ์ ๋ฐ์ดํฐ ์์ธ์ค ๊ธฐ์ ์์ ๋ฐ์ํ๋ ํ๋ซํผ ๋ ๋ฆฝ์ ์ธ ์์ธ์ฒ๋ฆฌ๋ฅผ ์ํด์ org.springframework.dao.DataAccessException ๊ณ์ด์ ์์ธ๋ก ๋ณํํด์ฃผ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋๋ฐ, ์ด๋ฅผ ๋ด๋นํ๋ ๊ณณ์ด ๋ฐ๋ก
→ PersistenceExceptionTranslationPostProcessor
์ด ํด๋์ค๋ AOP๋ฅผ ์ฌ์ฉํ์ฌ, @Repository๋ก ๋งํน๋ ํด๋์ค์ public ๋ฉ์๋์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์๋์ผ๋ก ๊ฐ์งํ์ฌ ์ ์ ํ DataAccessException์ผ๋ก ๊ฐ์ธ์ ๋ณํํฉ๋๋ค.
PersistenceExceptionTranslationPostProcessor (Spring Framework 6.2.8 API)
Bean post-processor that automatically applies persistence exception translation to any bean marked with Spring's @Repository annotation, adding a corresponding PersistenceExceptionTranslationAdvisor to the exposed proxy (either an existing AOP proxy or a
docs.spring.io
DataAccessException (Spring Framework 6.2.8 API)
Root of the hierarchy of data access exceptions discussed in Expert One-On-One J2EE Design and Development. Please see Chapter 9 of this book for detailed discussion of the motivation for this package. This exception hierarchy aims to let user code find an
docs.spring.io
๋ @Service, @Controller, @Repository๋ ๊ฐ๊ฐ ํน์ ๊ณ์ธต์ ๋ํ๋ด๋ฏ๋ก, AOP์ ํฌ์ธํธ์ปท์ ์ ์ํ ๋ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. @Component๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ๊ณ์ธต ๊ตฌ๋ถ์ด ๋ถ๋ถ๋ช
ํด์ ธ AOP ์ ์ฉ์ด ์ด๋ ค์ธ ์ ์์ต๋๋ค.
์ฐธ์กฐ
- ๋งค์ผ๋ฉ์ผ,
- https://coding-nyan.tistory.com/158
- https://galid1.tistory.com/494