💡 Spring에서 자주 사용하는 Annotation
📌 @SpringBootApplication
- 자동 구성 활성화
- Bean 등록 활성화
@ComponentScan
활성화(@Component
가 붙은 클래스를 검색 후, Spring Bean으로 등록)
@Configuration
이 붙은 클래스를 검색 후, Spring Bean으로 등록하는 기능을 활성화
📌 @Configuration
- Spring Container는
@Configuration
이 붙은 class를 설정 정보로 사용한다
@Configuration
은 해당 class가 Bean Definitions의 소스임을 나타내는 Annotation이다
(* Bean Definition : Bean의 생성방법, Bean의 생명주기, Bean의 종속성 등에 대한 설정정보를 담고있는 데이터)
- 1개 이상의
@Bean
을 제공하고 있는 클래스의 경우, 반드시 @Configuration
을 사용해야한다
@Component
가 포함되어 있으므로 자동으로 Bean 등록이 된다
📌 @Bean
- method에서 반환된 객체를 Spring Container에 Bean으로 등록할 때 사용한다
- 주로 개발자의 제어가 불가능한 외부 라이브러리에서 method의 반환객체를 Bean으로 만들 때 사용한다
- Bean 이름은 method 이름을 사용한다
- Bean의 이름은 겹치지않도록 항상 서로 다른 이름을 부여해줘야 한다
@Configuration
와 @Bean
은 항상 같이 사용해야한다
📌 @Component
- class를 Spring Container에 Bean으로 등록할 때 사용한다
@Service
, @Repository
, @Controller
, @Configuration
에는 @Component
가 포함되어있다
📌 @Bean
과 @Component
의 차이점
@Component
와 @Bean
모두 Spring Container에 Bean을 등록할 때 사용한다
- 둘의 가장 큰 차이점은,
@Component
는 class를 Bean으로 등록할 때 사용하고
@Bean
은 method에서 반환된 객체를 Bean으로 등록할 때 사용한다는 점이다
- 또 다른 차이점은,
@Component
는 개발자가 생성한 class를 Bean으로 등록할 때 사용하고
@Bean
은 외부 라이브러리의 메서드 반환 객체를 Bean으로 등록할 때 사용한다는 점이다
📌 @ComponentScan
- Spring 실행 시에
@Component
나 @Bean
이 포함된 class, method들을 자동으로 Scan하여, Spring Container에 Bean으로 등록해준다
📌 @Import
- 다른
@Configuration
클래스에서 Bean Definitions를 가져올 수 있다
@Configuration
를 통해 Import해온 설정파일을 해당클래스에 Bean으로 주입받을 수 있다
📌 @Autowired
- Bean을 주입받기 위하여
@Autowired
를 사용한다
- 생성자에
@Autowired
를 하면 Spring Container에 @Component
로 등록된 Bean에서 생성자에 필요한 Bean들을 주입한다
- 생성자가 1개만 존재하는 경우에는
@Autowired
를 생략해도 자동 주입이 된다
@Autowired(required=false)
라고 사용하면 해당 타입의 객체가 존재하지 않아도 에러가 발생하지 않는다
📌 @Service
@Component
가 포함되어 있으므로 자동으로 Bean 등록이 된다
- Service계층(Business 계층)에 해당함을 의미한다
📌 @Repository
@Component
가 포함되어 있으므로 자동으로 Bean 등록이 된다
- 데이터 엑세스 계층에 해당함을 의미한다
📌 @Controller
, @RestController
@Component
가 포함되어 있으므로 자동으로 Bean 등록이 된다
@Controller
: API 계층에 해당함을 의미한다(View를 반환할 때 주로 HTML 페이지를 반환한다)
@RestController
: API 계층에 해당함을 의미한다(View를 반환할 때 주로 JSON으로 반환한다)
📌 @ResponseBody
- method의 return 값을 웹페이지에 띄워준다
📌 @Transactional
- 트랜잭션이 필요한 영역에 추가한다
- 클래스 레벨, 메서드 레벨에
@Transactional
을 적용할 수 있다
- 클래스 레벨에만
@Transactional
이 적용된 경우, 해당 클래스의 모든 메서드에 일괄 적용된다
- 클래스 레벨과 메서드 레벨에
@Transactional
이 함께 적용된 경우, 메서드 레벨의 @Transactional
만 적용되며, 만약 메서드레벨에 @Transactional
이 적용되지 않으면, 클래스 레벨의 @Transactional
이 적용된다
- readOnly attribute
@Transactional(readOnly = true)
- 읽기 전용 트랜잭션이 적용되며, 주로 조회하는 메서드(Get method)에 사용한다
- commit만 진행되고, flush와 스냅샷 생성을 하지않으므로 불필요한 추가 동작을 줄일 수 있다
- propagation attribute
- 트랜잭션 전파(Transaction Propagation)
- 트랜잭션의 경계에서 진행 중인 트랜잭션이 존재할 때 또는 존재하지 않을 때, 어떻게 동작할 것인지 결정하는 방식
- 일반적으로
Propagation.REQUIRED
을 많이 사용하며, 진행 중인 트랜잭션이 없으면 새로 시작하고, 진행 중인 트랜잭션이 있으면 해당 트랜잭션에 참여한다
서로 다른 클래스에 존재하는 여러 개의 작업을, 하나의 트랜잭션으로 묶기 위해 사용한다
- isolation attribute
- 트랜잭션 격리 레벨(Isolation Level)
- ACID 원칙 중 격리성에 관한 속성이다
(격리성 : 트랜잭션은 다른 트랜잭션에 영향을 주지 않고, 독립적으로 실행되어야 한다)
Isolation.DEFAULT
: 데이터베이스에서 제공하는 기본 값
Isolation.READ_UNCOMMITTED
: 다른 트랜잭션에서 커밋하지 않은 데이터를 읽는 것을 허용한다
Isolation.READ_COMMITTED
: 다른 트랜잭션에 의해 커밋된 데이터를 읽는 것을 허용한다
Isolation.REPEATABLE_READ
: 트랜잭션 내에서 한 번 조회한 데이터를 반복해서 조회해도 같은 데이터가 조회되도록 한다
Isolation.SERIALIZABLE
: 동일한 데이터에 대해서 동시에 두 개 이상의 트랜잭션이 수행되지 못하도록 한다
📌 @Slf4j
- Simple Logging Facade for Java
- 로깅 프레임워크와 함께 사용되는 어노테이션
- Java 애플리케이션을 위한 간단하고 유연한 로깅 API를 제공하는 로깅 퍼사드나 추상화 계층이다
- 클래스 레벨에 작성할 경우 프레임워크가 런타임에 SLF4J 로거 인스턴스를 자동으로 생성하며, 디버그, 정보, 경고, 오류 등의 SLF4J 로깅 레벨을 사용하여 메시지를 기록할 수 있다
📌 @ApplicationEventPublisher
, @EventListener
- Spring의 이벤트 퍼블리싱 관련 annotation
- 특정 작업을 이벤트로 보고, 해당 이벤트를 애플리케이션 전체에 보낼 수 있다
@ApplicationEventPublisher
: 이벤트를 @EventListener
가 있는 곳으로 보내준다
@EventListener
: @ApplicationEventPublisher
이 보낸 이벤트를 리스닝하여 사용하고싶은 메서드에 작성한다
📌 @Async
, @EnableAsync
- Spring에서 비동기적으로 쓰레드를 생성하도록 한다
@Async
: 비동기적으로 실행할 메서드 레벨에 작성한다
@EnableAsync
: @Async
가 붙은 메서드를 실행하는 클래스나, 애플리케이션을 실행하는 클래스에 작성한다
📌 @EnableWebSecurity
- SecurityConfig 클래스에 적용된다
- WebSecurityConfigurerAdapter를 상속받는 클래스에
@EnableWebSecurity
를 추가하면, SpringSecurityFilterChain이 자동으로 포함된다
- Spring Rest Docs에 대한 자동 구성을 위해
@AutoConfigureRestDocs
를 추가해준다
💡 Testing 관련 Annotation
📌 @SpringBootTest
- Spring Boot 기반의 애플리케이션을 테스트 하기 위한 Application Context를 생성한다
- 전체 Bean을 Application Context에 등록한다
- 테스트에 필요없는 부분까지 다 등록하게 된다
- 통합 테스트에 주로 사용된다
- 가장 손쉽게 테스트가 가능하다
@WebMvcTest
에 비해 상대적으로 무겁다
@AutoConfigureMockMvc
와 함께 사용한다
📌 @WebMvcTest
- 테스트에 필요한 Bean만 Application Context에 등록한다
- 자동구성을 안해주므로 추가적인 설정이 필요할 수 있으며, 필요한 Bean들을 수동으로 등록해야한다
@SpringBootTest
에 비해 상대적으로 가볍다
- Controller를 테스트 하기 위한 전용 애너테이션이다(Service 테스트, Repository 테스트에서 사용 불가)
- `@WebMvcTest(대상컨트롤러.class)
- 테스트를 위한 애플리케이션의 자동 구성 작업을 해준다
- MockMvc를 사용하기 위해 반드시 추가해야한다
- MockMvc란, Tomcat 같은 서버를 실행하지 않고 Spring 기반 애플리케이션의 Controller를 테스트할 수 있는 완벽한 환경을 지원해주는 일종의 Spring MVC 테스트 프레임워크이다
📌 @TestPropertySource
- test 파일의 설정 파일의 경로를 설정할 수 있다
@TestPropertySource(locations = "classpath:application-test.properties")
과 같이 작성한다
📌 @MockBean
- Application Context에 등록되어 있는 Bean에 대한 Mockito Mock 객체를 생성하고 주입해주는 역할을 한다
- 해당 필드의 Bean에 대한 Mock 객체를 생성한 후, 필드에 주입(DI)한다
📌 @Mock
- Mockito에서 제공하는 애너테이션
- 가짜 객체만 제공한다
@MockBean
와 달리 DI까지 해주지는 않는다
📌 @Test
- JUnit으로 단위 테스트를 적용할 때 사용된다
- 테스트를 실행하고자하는 대상에 대한
public void test(){…}
메서드를 만들고 @Test
annotation을 추가해준다
📌 @DisplayName
- 테스트 케이스를 실행시켰을 때, 실행 결과 창에 표시되는 이름을 지정한다
DispalyName("테스트1")
와 같이 지정한다
💡 Handler Method Annotation
📌 @RequestMapping
@RequestMapping
에는 value와 produces로 속성을 작성할 수 있다
- value에는 Request를 Mapping할 Url 주소를 작성한다
- produces에는 응답 데이터를 어떤 미디어 타입으로 클라이언트에게 전송할 지를 작성한다
ex) JSON은 MediaType.APPLICATION_JSON_VALUE
으로 작성한다
- produces를 삭제하고 JSON 문자열 수작업을 Map 객체로 대체하여 ResponseEntity 객체로 return 할 수 있다
이 때, new ResponseEntity<>(map, HttpStatus.CREATED);
처럼 ResponseEntity 객체를 생성하면서 생성자 파라미터로 응답 데이터(map)와 HTTP 응답 상태를 함께 전달해야한다
@RequestMapping
을 클래스에 작성하여 Controller 내부의 @GetMapping
이나 @PostMapping
에 공통적으로 적용시킬 수 있다
📌 @GetMapping
- @GetMapping은 클라이언트가 서버에 리소스를 조회할 때 사용한다
- 기본적으로
@GetMapping("/")
는 localhost:8080/ 경로로 들어왔을 때 실행해준다
- method의 return값이 html파일 이름과 같을 경우(String타입), html파일을 실행해준다
- url에 query방식을 사용하여 정보를 넘겨줄 경우
@GetMapping
가 포함된 method의 매개변수로 받을 수 있다
📌 @PostMapping
- JSON 타입으로 String 값을 return해주거나 html 파일 이름과 일치하는 String 값을 return 해줄 수 있다
@PostMapping
로 전달되는 url과 html form태그 post타입의 action속성 url이 일치해야한다
@PostMapping("url")
<form type="post" action="url"></form>
- html form태그 내부 태그들을 통해 입력받은 값들을
@PostMapping
이 지정된 method의 매개변수로 받을 수 있다
- 혹은 Entity로 지정한 클래스 그대로
@PostMapping
이 지정된 method의 매개변수로 받을 수 있다
💡 Handler Method Parameter Annotation
📌 @PathVariable
@PathVariable
는 전달받을 method의 매개변수 앞에 작성한다
@GetMapping
이나 @PostMapping
등을 통해 들어온 url의 역슬래시(/) 뒷부분이 인식되어 해당 메서드의 매개변수로 들어올 수 있게 한다
- 예를 들어
@GetMapping(/{id})
가 붙은 method 매개변수에@PathVariable("id") Integer id
를 사용할 경우, url을 통해 넘어온 id값을 받을 수 있다
📌 @RequestParam
- 쿼리 파라미터(Query Parmeter 또는 Query String), 폼 데이터(form-data), x-www-form-urlencoded 형식으로 전송하면 이를 서버 쪽에서 전달 받을 때 사용하는 annotation이다
- 주로
@RequestParam
는 url의 query방식으로 변수를 받을 때 사용한다
@RequestParam
은 전달받을 method의 매개변수 앞에 작성한다
- html파일을 통해 입력받은 값을 매개변수로 사용할 수 있다
- 이 때, input태그의 name속성과 일치하는 변수명을 괄호안에 작성한다
@RequestParam("변수명")
📌 @PathVariable
과 @RequestParam
차이점
@RequestParam
는 url의 query방식으로 변수를 받을 수 있다
@PathVariable
는 역슬래시 주소로 깔끔하게 변수를 받을 수 있다
📌 @RequestBody
📌 @Query
- Repository에 쿼리문을 직접 작성한다
- 직접 쿼리문을 작성해서 질의를 할 수 있도록 해준다
💡 Entity 관련 Annotation
📌 @Entity
- class를 Entity로 선언한다
- 해당 클래스가 DB에 있는 테이블을 의미한다
- Entity클래스는 반드시 기본키를 가져야하므로 @Id를 이용하여 id 멤버변수를 상품 테이블의 기본키로 설정한다
📌 @Table
- 데이터베이스와 클래스(엔티티클래스)를 매핑한다
- 따로 지정하지 않을 경우, 클래스 이름과 똑같은 이름의 데이터베이스와 매핑된다
📌 @Id
- DB의 기본키(primary key)를 의미한다
@Id
를 지정하면, 해당 클래스(엔티티클래스)와 데이터베이스가 매핑된다
📌 @Column
@Column
을 사용하여 해당 필드와 데이터베이스 테이블의 컬럼 간의 매핑을 설정할 수 있다
@Column
attribute
- name : 별도의 이름을 지정해서 엔티티 클래스 필드명과 다른 이름으로 컬럼을 생성할 수 있다
- length : 컬럼에 저장할 수 있는 문자 길이를 지정
- nullable : 컬럼에 null 값을 허용할지 여부를 지정
- updatable : 컬럼 데이터를 수정할 수 있는지 여부를 지정
- unique : 하나의 컬럼에 unique 유니크 제약 조건을 설정
@Column
을 사용하지 않을 경우, JPA는 기본적인 매핑 규칙을 적용한다
- 기본 매핑 규칙
- 필드이름과 똑같은 이름의 칼럼과 매핑된다
- nullable = true (int나 long 같은 원시 타입일 경우, nullable = false)
- updatable = true
- unique = false
📌 @GeneratedValue
- 기본키(primary key) 값에 대한 생성 전략(strategy)을 제공한다
@GeneratedValue(strategy = GenerationType.생성전략)
으로 작성한다
- strategy에는 TABLE, SEQUENCE, IDENTITY, AUTO가 있다
1. TABLE : 데이터베이스에 키 생성 전용 테이블을 하나 만들고 이를 사용하여 기본키를 생성한다.
2. SEQUENCE : 데이터베이스의 특별한 오브젝트 시퀀스를 사용하여 기본키를 생성한다.
3. IDENTITY : 기본키 생성을 데이터베이스에 위임한다 ex) MySQL은 AUTO_INCREMENT 사용
4. AUTO : JPA 구현체가 자동으로 생성 전략을 결정한다
📌 @Transient
- 테이블 컬럼과 매핑하지 않겠다는 의미로 JPA가 인식한다
→ 데이터베이스에 저장도 하지 않고, 조회할 때 역시 매핑되지 않는다
@Transient
은 주로 임시 데이터를 메모리에서 사용하기위한 용도로 사용된다
📌 @Enumerated
- enum 타입과 매핑할 때 사용하는 애너테이션
EnumType.ORDINAL
: enum의 순서를 나타내는 숫자를 테이블에 저장한다(enum의 순서가 뒤바뀔 가능성이 있으므로 권장되지 않는다)
EnumType.STRING
: enum의 이름을 테이블에 저장한다(권장)
📌 @ManyToOne
- 다대일 단방향 연관 관계를 매핑할 떄 사용한다
- 일반적인 테이블 관계에서는 보통 ‘일’에 해당하는 테이블의 기본키를 ‘다’에 해당하는 테이블에서 외래키로 가지고있어야한다
→ 다대일 관계에서는 일반적인 테이블 관계와 같은 방식의 매핑이기 때문에 JPA의 엔티티 연관 관계 중에서 가장 기본으로 사용되는 매핑 방식이다
@JoinColumn
과 같이 사용하여 외래키를 지정한다
📌 @JoinColumn
- name 속성으로 외래키에 해당하는 컬럼명을 적는다
@JoinColumn(name="외래키 이름")
📌 @OneToMany
- 일대다 단방향 연관 관계를 매핑할 떄 사용한다
- 일반적인 테이블 관계에서는 보통 ‘일’에 해당하는 테이블의 기본키를 ‘다’에 해당하는 테이블에서 외래키로 가지고있어야한다
→ 일대다 관계에서는 이런 일반적인 테이블 간의 관계를 정상적으로 표현하지 못하기 때문에 단독으로 사용하지 않는다(다대일 단방향 연관관계에 추가하여 양방향 관계로 사용)
- mappedBy 속성으로 관계를 소유하고 있는 필드를 지정한다
- 만약 A가 B를 다대일로 매핑하고있고, B가 A를 일대다로 매핑하고 싶다면,
1. B클래스의 필드로 A에 대한 리스트를 만들고
2. A클래스에서 외래키의 역할을 하는 변수명을 @OneToMany(mappedBy = "변수명")
를 통해 A와 B를 매핑하면된다
- Member(일), Order(다) 관계 예시
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
📌 @OneToMany
- 일대일 단방향 연관 관계를 매핑할 떄 사용한다
- 다대일 매핑 방법과 사용하는 annotation만 다르고 방법은 동일하다
💡 유효성 검사 Annotation
📌 @Valid
- Dto 객체에 유효성 검증을 적용하게 해주는 annotation
- 주로
@RequestBody
에 붙는다
📌 @Validated
- URI path에서 사용되는
@PathVariable
변수의 유효성을 검사한다
- 클래스에 적용하며, 검증하고싶은 변수에
@Valid
를 붙여준다
📌 @NotNull
, @NotEmpty
, @NotBlank
@NotNull
: Null값이 아닌지 확인한다
@NotEmpty
: NULL값이 아니고 공백("")값이 아닌지 확인한다
@NotBlank
: Null값이나 공백(""), 스페이스(" ")같은 값들을 모두 허용하지 않는다
- 속성값으로 message를 설정해서 적합한 형식이 아닌 경우 출력하는 메시지를 설정할 수 있다
📌 @Nullable
, @NotNull
, @Null
@Nullable
: Null값이어도, Null값이 아니어도 유효성 검사에 통과된다
@NotNull
: Null값만 아니면 유효성 검사에 통과된다
@Null
: Null값이어야 유효성 검사에 통과된다
📌 @Range
, @Min
, @Max
@Range
: 범위를 설정할 수 있으며, @Range(min=,max=)로 표시한다
@Min
: 최소 범위를 설정할 수 있다
@Max
: 최대 범위를 설정할 수 있다
📌 @Pattern
- 정규표현식(Reqular Expression)에 매치되는 유효한 정보인지를 검증한다
- regexp 속성을 통해 정규표현식을 작성한다
- 전화번호 예시 )
@Pattern(regexp = "^010-//d{3,4}=\\d{4}$")
- 속성값으로 message를 설정해서 적합한 형식이 아닌 경우 출력하는 메시지를 설정할 수 있다
@Pattern(message = "적합한 형식이 아닙니다.")
📌 @Email
- 이메일 형식인지 검사하는 annotation
- 속성값으로 message를 설정해서 적합한 형식이 아닌 경우 출력하는 메시지를 설정할 수 있다
@Email(message = "이메일 형식이 아닙니다.")
💡 예외 처리 Annotation
📌 @ExceptionHandler
- 유효성 검사에 실패하여 발생한 에러 응답 메시지를 개발자가 직접 처리하는 방법이다
- 유효성 검증에 실패하면 MethodArgumentNotValidException이 발생하며, 발생한 에러를 받는 메서드를 Controller에 따로 만들어
@ExceptionHandler
annotation을 추가해주면, 이 메서드가 던져진 에러를 받는다
📌 @ControllerAdvice
, @RestControllerAdvice
@ControllerAdvice
annotation을 추가한 클래스를 이용하면 예외 처리를 공통화할 수 있다
@RestControllerAdvice
= @ControllerAdvice
+ @ResponseBody
- @ControllerAdvice 의 기능과 @ResponseBody 의 기능을 모두 포함하고 있기 때문에 JSON 형식의 데이터를 Response Body로 전송하기 위해서 ResponseEntity로 데이터를 래핑할 필요가 없다
📌 @ResponseStatus
- ResponseEntity로 HttpStatus를 전달하는 것과 같은 기능을 한다
@RestControllerAdvice
가 붙은 클래스 내부에 정의된 에러메시지를 반환하는 메서드에 @ResponseStatus
를 적용하여, 에러메시지와 HttpStatus값을 ResponseEntity로 같이 반환할 때 사용한다
@ResponseStatus
은 고정된 예외를 처리할 경우에 사용할 수 있다
(HttpStatus가 동적으로 변경되는 경우에는 @ResponseStatus
없이 ResponseEntity 를 사용한다)
📌 @InitBinder
, @ModelAttribute
- JSP, Thymeleaf 같은 서버 사이드 렌더링(SSR, Server Side Rendering) 방식에서 주로 사용되는 예외 처리 방식
💡 Lombok Annotation
📌 @Data
@ToString
, @EqualsAndHashCode
, @Getter
, @Setter
, @RequiredArgsConstructor
를 합친 annotation
📌 @Getter
, @Setter
@Getter
: 해당 클래스의 필드값에 대하여 Getter method를 사용할 수 있도록 한다
@Setter
: 해당 클래스의 필드값에 대하여 Setter method를 사용할 수 있도록 한다
📌 @ToString
toString()
메서드를 생성해준다
- exclude attribute를 사용하면 원하지 않는 속성을 제외한
toString()
메서드를 생성해준다
toString(exclude={""})
📌 @Builder
📌 @AllArgsConstructor
, @NoArgsConstructor
, @RequiredArgsConstructor
@AllArgsConstructor
: 해당 클래스에 추가된 모든 멤버 변수를 파라미터로 갖는 Member 생성자를 자동으로 생성해준다
@NoArgsConstructor
: 해당 클래스에 파라미터가 없는 기본 생성자를 자동으로 생성해준다
@RequiredArgsConstructor
: 초기화되지 않은 Final, @NonNull
이 붙은 필드에 대한 생성자를 자동으로 생성해준다