티스토리 뷰

Server

[Spring] Annotation과 MVC

니용 2019. 9. 17. 18:44
반응형

Annotation의 @

 

 

기존에 자바 소스에서는 @Override, @Deprecated, @SuppressWarnings 의 형태로 사용했다.

 

Spring Framework에서는 위의 기능들 말고 좀 더 효율적으로 개발을 하기 위해 '@'라는 단어를 앞에 붙여 사용하고 있다.

 

@: at이라고도 읽지만 Spring 내에서는 Annotation(어노테이션, 애노테이션이라고도 함)으로 읽고 있다.

 

어노테이션은 스프링 프레임워크 3.0부터 본격적으로 사용되기 시작하였고, (현재는 5.2)

모든 어노테이션은 org.springframework 의 하위 패키지 클래스에 내장되어 있다.

* build.gradle의 설정에 따라 각각 호출되는 어노테이션 명 및 기능이 다를 수도 있다.

 

또, 어노테이션은 각각의 레벨이 있고 그 레벨마다

호출되는 순서가 전부 다르기 때문에 우선 순위를 잘 구분하여 코드를 짜야한다.

순서는 Context -> Configuration -> Autowired Bean의 순서대로 호출이 되며 먼저 호출되는 어노테이션일수록

중요도가 높고 생명 주기(Life Cycle)가 더 길다.

 

개발자가 필요에 따라 직접 정의하여 클래스 명에 @를 붙이는 행위도 가능하다.

 

스프링 프레임워크에서 모든 어노테이션은 연결(바인딩)이 되어 있다.

여기서 중요한 것이 바인딩이 되지 않으면 호출을 할 수 없는 영역으로 분류가 된다.

 

그럼 대표적으로 사용하는 어노테이션이 무엇이 있는지 간단히 알아보자.

앞에 글(https://abbo.tistory.com/4)에서 작성한 바와 같이

프로젝트를 생성하면 제일 먼저 확인할 수 있는 어노테이션이 있다.

 

@SpringBootApplication 

스프링 부트를 기반으로 작동할 때 환경 설정에 할당되는 어노테이션

 

 

환경 설정은 Context 어노테이션이 호출 된 후 WAS에 상주할 때 가장 먼저 호출되는 어노테이션이다.

환경 설정을 위한 어노테이션은 이 밖에도 몇가지가 더 있다.

작명 규칙은 따로 없지만 보통 아래의 어노테이션이 들어가는 클래스 명의 뒤에는 'Config' 가 붙이는게 관습이다.

 

@Configuration

환경 설정값(서버와의 통신, Servlet 등)을 프레임워크에서 사용할 수 있도록 바인딩

 

@Transactional 

다중 트랜잭션을 사용할 때 사용

 

@PropertySource 

특정 경로에 있는 파일의 설정값을 불러와서 주입할 때 사용

 

@EnableWebMvc

웹 어플리케이션에서 MVC 기반으로 작성할 때 사용(기본값)

 

 

다음으로 설명할 어노테이션은 MVC 패턴에 기반하여 주로 호출이 되고 있는 것들을 위주로 작성을 하려고 한다.

클라이언트의 기준에서는

Controller -> Service -> Mapper -> VO(Value Object) 의 순서로 호출이 되고 있다.

가장 먼저 Controller Class를 확인해보자

 

 

제일 먼저 클래스의 상단에 @Controller 어노테이션으로 선언을 하고,

해당 클래스에서 호출하는 어노테이션에 맞추어 @Autowired로 바인딩을 시도한다.

@RequestMapping 은 기존에 사용하던 방식으로 내부에 method와 value 프로퍼티를 선언하여 작동을 하였다.

이를 더 명시적으로 표현하기 위해 4.0 이후부터는

@GetMapping, @PostMapping과 같은 방식으로 호출하고 있는 추세다.

Get / Post / Put / Delete 의 4가지 method가 존재하며

이는 RESTful 방식에서 사용하므로 자세한 내용은 다른 글에서 다루도록 하겠다.

 

한편, @ResponseBody 를 작성한 메서드와 그렇지 않은 메서드가 존재하는데,

이 어노테이션을 적용하게 되면 Jackson의 ObjectMapper를 호출하여

Response를 JSON 포맷으로 리턴해주는 MessageConverter의 역할을 하게 된다.

적용하지 않게 되면 ViewResolver에 의해 선택된 경로의 .html 파일이 호출된다.

기본적으로 String을 리턴 타입으로 가지며 그렇지 않으면 에러가 발생한다.

(위에서는 작성하지 않은 메서드가 index 이므로 /src/main/resources/index.html 뷰가 열리게 된다.)

 

@RequestParam 은 클라이언트에서 전달받는 파라미터를 의미하는 어노테이션이며

하위 속성으로 value(전달받을 key), defaultValue(전달받지 못한 경우 기본값), required(필수값 여부) 등을 가진다.

 

다음으로 Service 클래스를 확인해보자

 

 

먼저 @Service, @Slf4j 어노테이션을 호출하였는데,

@Slf4j 는 Lombok 에서 지원하는 로그백 어노테이션이며 호출하게 되면

기본적으로 클래스 내에서 "log"라는 변수로 사용이 가능하다.

해당 어노테이션을 통해 info, debug, warning, error 레벨에 맞게 로그를 출력하는 기능도 지원한다.

 

@Autowired 로 기존에 @Configuration 어노테이션으로

적용을 하였던 Configuration Class도 바인딩을 시켜준다.

바인딩을 하지 않는다면 사용할 수 없다.

 

@Value는 application.yml(application.properties)에 적용되어 있는 환경 변수를 가져오는데 사용한다.

'.' 은 하위 레벨을 가리키며 (abc.def 는 abc property 아래 def를 가리킴)

"host"를 키값으로 가지고 있는 변수를 가져와서 사용하는데

문자인 경우는 앞에 '$' 기호를, 숫자인 경우는 앞에 '#'를 붙여 사용한다.

Optional 클래스에 대한 내용은 차후에 리뷰하도록 하겠다.

 

callService라는 메서드가 호출되면 다음과 같은 기능이 작동된다.

1. console에서 debug 레벨에 "host >>> http://localhost" 로 출력

2. mapper 의 selectIndexList 쿼리 수행

 

이번에는 Mapper 및 VO 클래스이다.

 

 

@Mapper 라는 어노테이션과 위에서 정의한 @DeveloperClass 어노테이션을 선언하여 해당 클래스와 바인딩 시켜주었다.

VO 클래스에서는 Lombok에서 제공해주는

 

@Data

getter(@Getter), setter(@Setter), toString(@ToString) 을 기본적으로 생성

 

@Builder

VO의 Builder Pattern이 적용

 

@AllArgsConstructor

모든 프로퍼티를 파라미터로 가지고 있는 생성자

 

@NoArgsConstructor

파라미터가 없는 기본 생성자

 

4개의 어노테이션을 적용하였고, @JsonIgnore 라는 어노테이션을 사용하여

select 쿼리를 사용하였을 때 'column3'이 가지고 있는 값이 보여지지 않도록 처리하였다. 

만일 호출이 진행되었고, Select Query의 결과값이 4Rows 라면 아래와 같이 json이 Response로 반환될 것이다.

 

확인한 것과 같이 어노테이션은 사용을 잘하면

개발자들이 손쉽게 개발을 마치도록 도와주는 역할을 하는 강력한 도구이다.

위에서 사용한 것 이외에도 자주 사용하는 것들로 정리를 해보았다.

 


환경변수


@Qualifier

같은 Type을 가진 Bean이 두 개 이상 존재할 때,

Type에 따라 매칭되는 @Autowired의 불편함을 줄여주기 위해 특정 Bean을 가리킨다.

@Resource

@Autowired@Qualifier 를 합친 형태이다.

@Component

component-scan을 선언에 의해 특정 패키지 안에 클래스들을 스캔하고,

@Component 어노테이션이 있는 클래스에 대하여 bean 인스턴스를 생성한다.

기본적으로 @Controller, @Service, @Repository 을 통칭한다.

@Bean

개발자가 직접 제어가 불가능한 외부 Library / Method 등을 Bean화 시킬 때 사용한다.

 

@EnableMongoRepositories

MongoDB를 사용하기위해 환경설정을 한다.


Controller, Service, Util 등


 

@RestController

@Controller + @ResponseBody의 목적으로 사용한다.

반면에 @Controller는 API와 View를 동시에 사용하는 경우

@ResponseBody를 제외하고 view return 을 주목적으로 한다.

(위에서는 명시적인 사용을 위해 @Controller를 사용했다.)

 

 

@ModelAttribute

HTML에서 요청한 form의 값들을 파라미터로 전송한다.

@PathVariable

HTTP 요청에 대해 매칭되는 Request Parameter의 값이 자동으로 들어간다. 

@NotNull, @NotBlank, @NotEmpty

null 체크, 공백 체크, 빈값을 가지고 있는지에 대한 String 체크를 위해 사용한다.


Lombok


 

@Getter

프로퍼티의 getter를 자동으로 생성한다.

 

@Setter

프로퍼티의 setter를 자동으로 생성한다.

 

@ToString

프로퍼티의 toString() 메서드 호출이 가능하고,

exclude 옵션으로 제거할 프로퍼티의 선택이 가능하다.

@Data

@Getter + @Setter + @ToString + @RequiredArgsConstructor + @EqualsAndHashCode 을 전부 포함한다.

 

@Builder

새로운 객체를 체이닝(Chaining)방식 으로 생성이 가능하다.

사용 방법은 정말 쉽다.

위의 방식처럼 '.'으로 메서드를 연결하는 것을 체이닝이라고 한다.

 

@Builder.Default

@Builder를 사용할 때 set을 하지 않아도 기본값으로 가지고 있는 값을 설정가능하다.

@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor

파라미터가 하나도 없는 생성자,

필수값을 파라미터로 갖는 생성자,

모든 프로퍼티를 파라미터로 갖는 생성자를 만들어준다.

@NonNull

변수가 null로 넘어오는 경우 NPE(NullPointerException) 이 출력된다.

즉, 필수값으로 사용해야 하는 경우 사용한다.

@Singular

변수가 Array, List인 경우 체이닝을 통해 값을 add시키도록 해준다.


JPA


 

@Transactional

위에서 언급했지만 트랜잭션이 가능하도록 설정한다.

메서드에도 가능하며 해당 메서드에서 Exception이 발생하면

위에서 해당 메서드에서 이루어진 모든 DB 작업이 초기화된다.

@Repository

Spring JPA를 사용할 때 해당 클래스가 데이터베이스에 접근하는 클래스임을 명시하고

CrudRepository(Common), MongoRepository(MongoDB) 등의 리파지토리로 분류한다.

 

@NoRepositoryBean

RepositoryBean을 생성하지 않고 자식 Repository의 공통 메서드를 위해 사용한다.

 

@Query

CrudRepository에서 제공하는 기본 쿼리말고 사용자가 수동으로 쿼리를 작성한다.

 

@Procedure

사용자가 작성한 SP(Stored Procedure) 를 호출한다.

 

@Modifying

Update Query의 일종으로 사용한다.

@Entity(Common), @Document(Mongo)

DBMS에 테이블을 생성하거나 데이터를 가공하기 위한 클래스이다.

클래스 명이 테이블이 되고, 프로퍼티가 필드가 된다.

하위에 작성되는 어노테이션 들도 모두 속성값을 세팅하는데 사용한다.

 

@Id

해당 프로퍼티가 PK임을 알려준다.

 

@CreatedBy, @LastModifiedBy, @CreatedDate, @LastModifiedDate

Insert, Update 시 값이 생성/수정될 때 자동으로 매핑되어 반영된다.

 

@GeneratedValue

PK의 생성 규칙으로 Long type의 AUTO_INCREMENT 설정이 적용된다.

 

@Column, @Field(Mongo)

테이블 생성 시 컬럼명을 다르게 주고 싶을 때 사용한다.

 

@NotNull, @NotEmpty

PK가 아닌 다른 필드가 필수값일 때 사용한다.

타입이 숫자 계열이면 @NotNull, 문자 계열이면 @NotEmpty를 사용한다.

 

@ManyToOne, @ManyToMany, @OneToMany

FK 설정 시 N:1, N:N, 1:N 임을 명시할 때 사용한다.

 

@JoinTable

다른 테이블과 조인관계에 있는 컬럼을 명시한다.

 

@JsonIgnore, @Transient

클라이언트에 데이터가 보여지지 않도록 처리한다.

 


AOP


 

@EnableAspectJAutoProxy

스프링 부트 앱의 메인 클래스에 사용이 되며

AOP를 사용가능하게 설정해준다.

 

@Aspect

관점 지향 프로그래밍에서 하나의 Bean으로 생성할 때 사용한다.

@Around, @Before, @After, @AfterReturning, @AfterThrowing

기능이 수행되는 시점을 어노테이션으로 지정할 때 사용한다.

 

 

AOP 기능에 대한 자세한 내용은 차후에 다루도록 해야겠다.

 

 

 

참조:

https://gmlwjd9405.github.io/2018/12/02/spring-annotation-types.html

 

[Spring] Spring Annotation의 종류와 그 역할 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

https://galid1.tistory.com/494

 

Spring - @Bean 어노테이션과 @Component 어노테이션(DI) - 2

@Component, @Bean 프로그램이 거대해 짐에 따라 XML 을 이용하여 IOC Container 를 설정하는 것이 점점 어려워졌고 때문에 Annota tion(@) 이란 것이 등장했다(이하 어노테이션). 어노테이션은 코드에 메타데이터..

galid1.tistory.com

https://ryudung.tistory.com/23

 

스프링 프로퍼티 설정 주입1 - @PropertySource와 Enviroment

스프링 프로젝트를 하면서 jdbc 설정 값, version 등과 같이 정적인 데이터를 프로퍼티로 많이 사용합니다. 우리는 프로퍼티를 annotation으로 쉽게 외부값을 가져와서 사용할 수 있습니다. 스프링에서 런타임시..

ryudung.tistory.com

 

반응형

'Server' 카테고리의 다른 글

[Java] NPE와 Optional Class  (1) 2019.10.26
[Java] Lambda와 Stream(2)  (0) 2019.10.15
[Java] Lambda와 Stream(1)  (2) 2019.10.15
REST의 정체는?  (1) 2019.10.15
[Spring] Spring Framework & Spring Boot  (1) 2019.09.16
[Spring] Maven vs Gradle  (1) 2019.09.16
댓글
공지사항