인프런에서 주최하는 Warming-up 클럽 0기 백엔드 스터디에 참여하고 있다.
스터디에 참여하면서 배우게 된 내용을 전체적으로 정리하고 과제로 수행했던 내용들을 정리해 보고자 한다.
(1) 1일 차 : 2024-02-19(Mon)
1. 개요
- 이번 과제는 크게 3가지로 나누어서 정리해 보고자 한다.
(1) 자바(스프링)에서 어노테이션(Annotation)의 정의와 특징?
(2) 어노테이션을 사용함으로써 얻게 되는 장점?
(3) 사용자 정의(커스텀) 어노테이션을 지정하는 방법? (별도의 테스트를 통해 확인, 관련 내용이 4번에 기재)
2. 어노테이션(Annotation)의 정의와 특징
2-1. 어노테이션이란 무엇일까?
(1) Annotation은 단어의 의미를 해석해 보면 "주석"이라는 의미를 가진다. 하지만 자바에서의 Annotation은 코드 레벨에서 특정한 의미를 부여하는 데 사용되거나 특정한 기능을 수행시키고자 할 때 명시하는 추가적인 기능이라고 볼 수 있다.
2-2. 어노테이션의 특징
- 어노테이션이 갖고 있는 특징에 대해 확인해 보자.
(1) 위에서 언급한 것처럼 코드 레벨에서의 메타 데이터 제공
- 어노테이션을 사용함으로써, 코드에 대한 추가 정보를 제공할 수 있게 된다. 메타 데이터를 제공한다는 것은 의미가 나름 크다고 생각된다.
- 코드는 사람이 작성한다. 이러한 이유로 실수로 그냥 넘어갈 수 있는 부분이 생길 수도 있는데, 어노테이션을 적용시킴으로써 컴파일러, 빌드 과정에서 추가적인 정보를 제공해서 실수할 수 있는 부분을 캐치하고 교정할 수 있다.
(2) 런타임 레벨에서의 주요 기능 처리
- 서비스 계층에서 자주 사용되는 @Transactional 어노테이션을 예로 들어보자.
- 트랜잭션 처리가 중요한 서비스 레이어에서 @Transaction 어노테이션을 적용하면, 위의 같이 메서드 레벨에 선언적 트랜잭션(Declarative transaction)을 적용할 수 있다. 일반적으로 @Repository 어노테이션이 붙은 영역에서 데이터를 받아와서 이에 대한 처리를 서비스 계층에서 수행하기 때문에 트랜잭션 처리가 매우 중요해진다.
- 위와 같은 어노테이션을 적용하여 애플리케이션 런타임 시점에 동적으로 주요 기능을 처리하게 된다.
(3) 어노테이션의 주요 특징으로는 더 많은 내용들이 있겠지만 본인이 생각하는 주요 특징은 코드 레벨에서의 메타 데이터 제공(1), 런타임 시점에서의 주요 기능 처리(2) 크게 두 가지로 볼 수 있을 것 같다.
3. 어노테이션을 사용하며 얻게 되는 장점
- 어노테이션을 사용해 보며 생각해 본 장점은 아래와 같이 정리해 볼 수 있을 것 같다.
3-1. 코드 가독성 향상, 반복되는 어노테이션을 공통화해서 줄일 수 있다.
- 어노테이션을 사용하면 특정 코드가 어떤 기능을 수행하고자 하는 코드인지 의도를 명시적으로 표현할 수 있다는 부분이 큰 장점이다.
- 또한 어노테이션을 적절하게 사용하면 협업 과정에서 내가 쓴 코드를 다른 개발자가 읽는 상황이라고 한다면 코드를 조금 더 쉽게 이해할 수 있을 것이다.
- 4번 항목에서 설명하겠지만, 어노테이션도 공통화가 가능하다. 사용자 정의(커스텀) 어노테이션을 만들어서 자주 사용되는 어노테이션을 공통화할 수도 있다.
3-2. 사용자 지정 어노테이션 생성
- 뒤에서도 기재할 내용이지만 개발 과정에서 사용할 별도의 어노테이션을 생성하여 사용할 수도 있다. 이를 통해 기존 어노테이션 + 별도의 커스텀 어노테이션으로 확장성이 좋아지게 된다.
3-3. 컴파일 시점에서의 오류 체크
- 특정 어노테이션의 경우 컴파일 타임에 오류를 체크해 주기도 한다. 이전에 함수형 인터페이스를 공부하며 배웠던 @FunctionalInterface가 컴파일 타임에 오류를 일으켜서 코드를 교정할 수 있게 도와준다.
- 예시를 설명하기 위해 아래와 같이 코드를 작성해 보았다.
- 해당 코드를 보면 함수형 인터페이스의 특징상 한 개의 추상 메서드를 별도로 가져야 한다.
- 현재 추상 메서드가 선언되어 있지 않아서 인텔리제이 IDE가 어노테이션 부분을 빨갛게 하이라이팅해 주고 있다.
- 현재 상태에서 프로그램을 실행시키면 추상 메서드가 존재하지 않는다는 컴파일 오류가 발생한다.
- 위와 같이 컴파일러가 추상 메서드를 해당 인터페이스에서 찾을 수 없다는 오류를 내준다.
4. 사용자 정의(Custom) 어노테이션 정의 후 사용하기
(1) 온라인으로 학습하며 생성한 프로젝트 디렉토리에 커스텀 어노테이션을 테스트하기 위해 저장된 회원의 전체 목록을 API로 반환할 수 있게 MemberController, MemberService, MemberRepository를 각각 생성해 주었다
(2) 커스텀 어노테이션을 만들어 보기 전에 커스텀 어노테이션들에게 적용할 수 있는 메타 어노테이션에 대해 간략히 정리해 보았다.
4-2. Meta Annotation : 커스텀 어노테이션에 지정할 수 있는 별도의 어노테이션들
(1) @Retention : 어노테이션의 정보를 어느 범위(시점)까지 유효하게 할 것인지 설정
주요 속성 | 설명 |
RetentionPolicy.SOURCE | 컴파일 이전까지만 유효하며 컴파일 타임 이후 기능이 사라진다. |
RetentionPolicy.CLASS | 컴파일러가 클래스를 참조할 때까지만 유효하다. |
RetentionPolicy.RUNTIME | 컴파일 이후에도 자바 가상 머신에 의해 계속 유효하다. |
(2) @Target :해당 어노테이션이 사용될 수 있는 위치를 설정
주요 속성 | 설명 |
ElementType.PACKAGE | 패키지 선언 |
ElementType.TYPE | 타입 선언 |
ElementType.CONSTRUCTOR | 생성자 선언 |
ElementType.FIELD | 멤버 변수 선언 |
ElementType.METHOD | 메서드 선언 |
ElementType.ANNOTATION_TYPE | 어노테이션 타입 선언 |
ElementType.LOCAL_VARIABLE | 지역 변수 선언 |
ElementType.PARAMETER | 매개변수 타입 선언 |
(3) @Inherited : 하위 클래스에도 해당 어노테이션을 지정하도록 설정
(4) 장점에서 설명한 커스텀(사용자 정의)어노테이션을 만들어서 반복되는 어노테이션을 공통화해 보자.
4-3. MemberRepository.java (데이터베이스 접근 영역, Spring Data JPA 사용)
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
4-4. MemberService (서비스 계층)
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService {
private final MemberRepository memberRepository;
public List<Member> findAllMembersList() {
return memberRepository.findAll();
}
}
4-5. MemberController (API를 반환하는 컨트롤러 계층)
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {
private final MemberService memberService;
@GetMapping("/list")
public List<MemberListResponseDto> getAllMemberList() {
List<Member> allMemberList = memberService.findAllMembersList();
return allMemberList.stream()
.map(member -> new MemberListResponseDto(member))
.collect(Collectors.toList());
}
(1) 회원과 관련된 컨트롤러이기 때문에 @RestController, @RequestMapping 어노테이션이 공통화가 가능할 것으로 확인된다. 따라서 어노테이션을 공통화하여 반복되는 코드를 줄여보자.
4-6. 사용자 정의 어노테이션 생성
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.TYPE)
@RestController
@RequestMapping("/new")
public @interface CustomMyAnnotation {
String name() default "MemberController";
String value();
}
(1) 우선 @interface 키워드로 커스텀 어노테이션을 생성하기 위해 CustomMyAnnotation 인터페이스를 생성했다.
(2) 위의 표에 기재된 내용을 바탕으로 본인에게 필요한 속성을 명시하면 된다.
(3) 우선 @RestController, @RequestMapping 어노테이션을 공통화할 것이기 때문에 인터페이스 상단에 선언해 둔다.
(4) @Retention(RetentionPolicy.RUNTIME)
- 이후 컴파일 타임 이후 과정에서도 자바 가상머신이 해당 어노테이션을 참조할 수 있도록 설정한다.
(5) @Inherited
- 해당 커스텀 어노테이션이 적용된 하위 클래스에서도 커스텀 어노테이션을 사용할 수 있다.
String name() default "MemberController";
String value();
(6) 커스텀 어노테이션에 이름을 주기 위해 위와 같은 필드를 지정해 주었다.
(7) 이제 최종적으로 커스텀 어노테이션이 반영된 컨트롤러를 확인해 보자.
4-7. 커스텀 어노테이션이 적용된 MemberController
@CustomMyAnnotation(name = "MemberController", value = "MemberController")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@GetMapping("/list")
public List<MemberListResponseDto> getAllMemberList() {
List<Member> allMemberList = memberService.findAllMembersList();
return allMemberList.stream()
.map(member -> new MemberListResponseDto(member))
.collect(Collectors.toList());
}
}
5. 정리
(1) 자바로 프로그래밍을 한다면 어노테이션은 꾸준히 사용되는 것을 확인해 볼 수 있다.
(2) 어노테이션의 정의, 특징과 장점에 대해 정리해 보았고 단순히 정리만 하고 끝내기 보다는 이를 테스트하는 과정을 거치면서 더 오래 기억에 남을 수 있을 것이다.
※ 해당 포스팅에 대해 내용 추가가 필요하다고 생각되면 기존 포스팅 내용에 다른 내용이 추가될 수 있습니다.
개인적으로 공부하며 정리한 내용이기에 오타나 틀린 부분이 있을 수 있으며, 이에 대해 댓글로 알려주시면 감사하겠습니다!
'기록, 회고 > InFlearn Warming-up 0기 BE' 카테고리의 다른 글
[3일 차] - 내용 정리, 개인 회고 (0) | 2024.02.20 |
---|---|
[2일 차] - 과제 수행 : GET, POST API 설계 (4) | 2024.02.19 |
[2일 차] - 내용 정리, 개인 회고 (2) | 2024.02.19 |
[1일 차] - 내용 정리, 개인 회고 (2) | 2024.02.18 |
[0일 차 OT] 일간 내용 정리, 회고 (2024-02-16) (0) | 2024.02.16 |
댓글