Spring Rest Docs 스니핏을 이용한 API 문서화 API 문서 템플릿 생성을 위한 디렉토리 및 템플릿 문서 생성 API 문서 스니핏은 문서 일부에 포함되는 조각 모음이다. 이 조각 모음을 제대로 된 문서로 만들기 위해서는 스니핏을 포함하는 템플릿 문서가 필요하다. "index.adoc"파일을 아직 생성하지 않았다면 “src/docs/asciidoc” 디렉토리를 생성하고 비어 있는 “index.adoc” 파일을 생성한다. 템플릿 문서 내용 추가 위 코드는 Asciidoc 문법으로 작성된 템플릿 문서이다. (1)은 API 문서의 제목이다. (2)는 API 문서를 생성한 생성자의 정보이다. (1)과 (2) 사이에 있는 항목은 API 문서의 목차와 관련되 내용이다. (3)은 API 문서의 생성 날짜이다. (4)부터는 테스트 케이스 실행을 통해 생성한 API 문서 스니핏을 사용하는 부분이다. 템플릿 문서
Spring Rest Docs Controller 테스트 케이스에 Spring RestDocs 적용 API 문서 생성을 위한 슬라이스 테스트 케이스 작성 API 문서 생성을 위한 테스트 케이스 기본 구조 (1)에서 @SpringBootTest 애너테이션을 사용하지 않고, @WebMvcTest 애너테이션을 사용한다. @WebMvcTest 애너테이션은 Controller를 테스트 하기 위한 전용 애너테이션이며, @WebMvcTest 애너테이션의 괄호 안에는 테스트 대상 Controller 클래스를 지정한다. (2)는 JPA에서 사용하는 Bean 들을 Mock 객체로 주입해주는 설정이다. Spring Boot 기반의 테스트는 항상 최상위 패키지 경로에 있는 xxxxxxxApplication 클래스를 찾아서 실행한다. @EnableJpaAuditing 을 xxxxxxApplication 클래스에 추가하게 되면 J
Spring Rest Docs Spring Rest Docs란? Spring Rest Docs는 REST API 문서를 자동으로 생성해 주는 Spring 하위 프로젝트이다. Spring Rest Docs의 가장 큰 특징은 Controller의 슬라이스 테스트를 통해 테스트가 통과 되어야지만 API 문서가 정상적으로 만들어 진다는 것이다. Spring Rest Docs의 API 문서 생성 흐름 테스트 코드 작성 슬라이스 테스트 코드 작성 Spring Rest Docs는 Controller에 대한 슬라이스 테스트 코드를 먼저 작성한다. API 스펙 정보 코드 작성 슬라이스 테스트 코드 다음으로 Controller에 정의
API 문서화 API 문서화란? API 문서화란 클라이언트가 REST API 백엔드 애플리케이션에 요청을 전송하기 위해서 알아야 되는 요청 정보(요청 URL(또는 URI), request body, query parameter 등)를 문서로 잘 정리하는 것을 의미한다. API 문서화가 필요한 이유 우리가 개발한 REST API 기반의 백엔드 애플리케이션을 클라이언트 쪽에서 사용하려면 API 사용을 위한 어떤 정보가 필요하기 때문이다. API 사용을 위한 어떤 정보가 담겨 있는 문서를 API 문서 또는 API 스펙(사양)이라고 한다. API 문서는 개발자가 요청 URL(또는 URI) 등의 API 정보를 직접 수기로 작성할 수도 있고, 애플리케이션 빌드를 통해 API 문서를 자동 생성할 수도 있다. API 문서 생성의 자동화가 필요한 이유 한번 작성된 API 문서에 기능이 추가되거나 수정되면 API 문서 역시 수정되어야 하는데 사
테스팅(Testing) TDD(Test Driven Development) TDD란? TDD(테스트 주도 개발)의 개념을 요약하면 '테스트를 먼저 하고 구현을 그 다음에 한다'라고 할 수 있다. TDD가 아닌 전통적인 개발 방식 어떤 서비스 애플리케이션을 개발할 때 개발 절차는 일반적으로 다음과 같다. (고객의 요청으로 고객이 원하는 시스템을 구축하는 것이 아닌, 서비스 제공 기업에서 불특정 다수의 회원에게 제공하는 서비스 애플리케이션을 의미) 서비스 제작에 관여하는 이해 당사자(기획자, 프톤트엔드 개발자, 백엔드 개발자, 웹 디자이너 등)가 모여 서비스에 대한 컨셉과 해당 컨셉에 따른 요구 사항을 지속적으로 수집한다. 수집된 요구 사항에 맞춰 서비스를 화면으로 제공하기 위한 UI(User Interface)를 설계하면서 구체적인 기능 요구 사항들을 정의한다. 프론트엔드 개발자는 기능 요구 사항와 UI를 통해 개
테스팅(Testing) Mockito Mock이란? 테스트 세계에서의 Mock은 바로 가짜 객체를 의미한다. 그리고 단위 테스트나 슬라이스 테스트 등에 Mock 객체를 사용하는 것을 Mocking이라고 한다. Mockito란? Mock 객체로 Mocking을 할 수 있게 해주는 여러 오픈 소스 라이브러리가 있지만 그 중에서 가장 많이 사용되고, Spring Framework 자체적으로도 지원하고 있는 Mocking 라이브러리가 Mockito이다. Mockito의 Mocking 기능을 이용해서 테스트하고자 하는 대상에서 다른 영역(다른 계층 또는 외부 통신이 필요한 서비스 등)을 단절시켜 오로지 테스트 대상에만 집중할 수 있다. 슬라이스 테스트에 Mockito 적용 Controller의 postMember() 테스트에 Mockito 적용 @MockBean 애너테이션은 Applica
슬라이스 테스트(Slice Test) 데이터 액세스 계층 테스트 현재 데이터 액세스 계층에서 사용하고 있는 기술은 Spring Data JPA이며 Spring에서는 JPA에 대한 테스트를 쉽게 진행할 수 있는 몇 가지 방법들을 제공한다. 데이터 액세스 계층을 테스트 하기 위한 한 가지 규칙 DB의 상태를 테스트 케이스 실행 이전으로 되돌려서 깨끗하게 만든다. Repository 테스트 예시 saveMember() 테스트 예시 (1)의 @DataJpaTest 는 Spring에서 데이터 액세스 계층을 테스트하기 위한 가장 핵심적인 방법이다. @DataJpaTest 애너테이션을 테스트 클래스에 추가함으로써, MemberRepository의 기능을 정상적으로 사용하기 위한 Configuration을 Spring이 자동으로 해준다. @DataJpaTest 애너테이션은 @Transactional
슬라이스 테스트(Slice Test) 하나의 애플리케이션은 계층별로 역할이 있고, 계층별로 서로 연동되기 때문에 각각의 계층 별로 잘 동작하는지 테스트를 진행한 후에 마지막으로 통합 테스트를 통해서 계층 간의 연동에 문제가 없는지 확인해야 비로소 개발자의 테스트 작업이 마무리 되는것이라고 할 수 있다. 이처럼 개발자가 각 계층에 구현해 놓은 기능들이 잘 동작하는지 특정 계층만 잘라서 테스트하는 것을 슬라이스 테스트(Slice Test)라고 한다. > 참고사항 통합 테스트는 아니지만 QA 부서에서 본격적으로 전체적인 기능 테스트를 진행하기 전에 애플리케이션의 특정 수정 사항으로 인해 영향을 받을 수 있는 범위에 한해서 제한된 테스트를 진행하기도 한다. 테스트 세계에서는 이를 스모크 테스트(Smoke Test)라고 부른다. API 계층 테스트 API 계층의 테스트 대상은 대부분 클라이언트의 요청을 받아들이는 핸들러인 Controller이다. Cont
테스팅(Testing) Hamcrest를 사용한 Assertion Hamcrest란? Hamcrest는 JUnit 기반의 단위 테스트에서 사용할 수 있는 Assertion Framework이다. JUnit에서도 Assertion 을 위한 다양한 메서드를 지원하지만 Hamcrest는 다음과 같은 이유로 JUnit에서 지원하는 Assertion 메서드보다 더 많이 사용된다. Assertion을 위한 매쳐(Matcher)가 자연스러운 문장으로 이어지므로 가독성이 향상 된다. 테스트 실패 메시지를 이해하기 쉽다 다양한 Matcher를 제공한다. 단위 테스트에 Hamcrest Assertion 적용 예시 위 코드는 Unit의 Assertion 메서드를 사용한 HelloJunitTest 클래스와 Hamcrest의 매쳐(Matcher)를 사용한 HelloHamcrestTest 클래스이다. JUnit A
테스팅(Testing) JUnit을 사용한 단위 테스트 JUnit이란? JUnit은 Java 언어로 만들어진 애플리케이션을 테스트하기 위한 오픈 소스 테스트 프레임워크이며, Spring Boot의 디폴트 테스트 프레임워크이다. JUnit 기본 작성법 Spring Boot Initializr에서 Gradle 기반의 Spring Boot 프로젝트를 생성하고 오픈하면 기본적으로 'src/test' 디렉토리가 생성된다. Spring Boot Intializr를 이용해서 프로젝트를 생성하면 기본적으로 testImplementation >'org.springframework.boot:spring-boot-starter-test' 스타터가 포함되며, JUnit도 포함이 되어 있다. 따라서 별다른 설정없이 JUnit을 사용할 수 있다. JUnit을 사용한 테스트 케이스의 기본 구조 위 코드는 테스트 케이스에 JUnit을 적용하는 기본 구조이다. (
테스팅(Testing) 단위 테스트(Unit Test) 위 그림은 애플리케이션의 일반적인 테스트 분류를 나타낸 것이다. 기능 테스트 기능 테스트는 주로 애플리케이션을 사용하는 사용자 입장에서 애플리케이션이 제공하는 기능이 올바르게 동작하는지를 테스트한다. 기능 테스트를 하는 주체는 주로 해당 애플리케이션을 개발한 개발자가 될수도 있지만 일반적으로는 테스트 전문 부서(QA 부서) 또는 외부 QA 업체가 된다. 통합 테스트 통합 테스트는 애플리케이션을 만든 개발자 또는 개발팀이 테스트의 주체가 되는것이 일반적이다. 통합 테스트는 클라이언트 측 툴 없이 개발자가 짜 놓은 테스트 코드를 실행시켜서 이루어지는 경우가 많다. 예를 들어, 개발자가 Contro
트랜잭션 JTA를 이용한 분산 트랜잭션 적용 서로 다른 데이터소스를 사용하는 한 개 이상의 데이터베이스를 하나의 트랜잭션으로 묶어서 처리하는 것을 분산 트랜잭션이라고 한다. H2 인메모리 DB의 경우 분산 트랜잭션이 정상적으로 동작하지 않는다. 분산 트랜잭션은 하나의 PC에 물리적으로 데이터베이스의 인스턴스 두 개를 실행히키는 것이 아니라 'create dababase' 명령어로 두 개의 데이터베이스를 생성해서 각각 별도의 데이터소스를 사용하는 구조이다. 분산 트랜잭션 구조 위 그림은 MySQL을 사용할 경우, 분산 트랜잭션의 적용 예시이다. 백업용 회원 정보는 기존 회원 정보의 백업 데이터 역할을 하며, 분산 트랜잭션의 적용을 확인하기 위한 임시 테이블이라고 가정한다. 백업을
트랜잭션 선언형 방식의 트랜잭션 적용 Spring에서 선언형 방식으로 트랜잭션을 적용하는 방법은 크게 두 가지이다. 애너테이션 방식의 트랜잭션 적용 AOP 방식의 트랜잭션 적용 Spring Boot에서의 트랜잭션 설정 트랜잭션은 기본적으로 데이터베이스와의 인터랙션과 관련이 있기 때문에 (1)과 같이 데이터베이스 커넥션 정보를 포함하고 있는 Datasource가 필요하다. Spring에서 트랜잭션은 기본적으로 PlatformTransactionManager에 의해 관리되며, PlatformTransactionManager 인터페이스를 구현해서 해당 데이터 액세스 기술에 맞게 유연하게 트랜잭션을 적용 할 수 있도록 추상화 되어 있다. 현재 사용하는 데이터 액세스 기술이 JPA이기 때문에 (2)와 같이 PlatformTransactionManager의 구현 클래스인 JpaTransactionManager를 사용한다.
트랜잭션(Transaction) 트랜잭션이란? 트랜잭션은 여러 개의 작업들을 하나의 그룹으로 묶어서 처리하는 처리 단위이다. 무조건 여러 개의 작업을 그룹으로 묶는다고 해서 트랜잭션이라고 부를 수 있는게 아니라 물리적으로는 여러 개의 작업이지만 논리적으로는 마치 하나의 작업으로 인식해서 전부 성공하든가 전부 실패하든가(All or Nothing)의 둘 중 하나로만 처리되어야 트랜잭션의 의미를 가진다. All or Nothing이라는 트랜잭션 처리 방식은 애플리케이션에서 사용하는 데이터의 무결성을 보장하는 핵심적인 역할을 한다. ACID 원칙 트랜잭션의 특징을 이야기할 때는 일반적으로 ACID라는 원칙을 이용한다. 원자성(Atomicity) 트랜잭션에서의 원자성은 작업을 더 이상 쪼갤 수 없음을 의미한다. 논리적으로 하나의 작업으로 인색해서 둘 다 성공하든가 둘 다 실패하든가() 중에서 하나로만 처리되는 것이 보장되어야 한다.
Spring Data JPA Spring Data JPA를 통한 데이터 액세스 계층 구현 Spring Data JPA란? Spring Data JPA는 Spring Data 패밀리 기술 중 하나로써, JPA 스펙을 구현한 구현체의 API를 조금 더 쉽게 사용할 수 있도록 해주는 모듈이다. Spring에서는 애플리케이션이 특정 기술에 결합되지 않도록 Spring이 추구하는 PSA를 통해 개발자는 일관된 코드 구현 방식을 유지하도록 하고, 기술의 변경이 필요할 때 최소한의 변경만을 하도록 지원한다. (Spring Data JDBC -> Spring Data JPA) Spring Data JPA 적용 순서 엔티티 클래스를 Spring Data JPA에 맞게 수정 리포지토리(Repository) 인터페이스 구현 서비스 클래스 구현 기타 기능 추가로 인한 코드 수정 리포지토리 인터페이스 구현 (1)과 같이 Spr
Spring Data JPA 엔티티 간의 연관 관계 매핑 연관 관계 매핑이란 연관 관계 매핑이란 엔티티 클래스 간의 관계를 만들어주는 것을 말한다. 연관 관계 매핑은 참조하는 방향성을 기준으로 생각했을 때 단방향 연관 관계와 양방향 연관 관계로 구분할 수 있다. 그리고, 엔티티 간에 참조할 수 있는 객체의 수에 따라서 일대다(1:N), 다대일(N:1), 다대다(N:N), 일대일(1:1) 의 연관 관계로 나눌 수 있다. 단방향 연관 관계 한쪽 클래스만 다른 쪽 클래스의 참조 정보를 가지고 있는 관계를 단방향 연관 관계라고 한다. 위 그림은 Order 클래스가 Member 객체를 가지고 있으므로 Member 클래스를 참조
Spring Data JPA 엔티티 매핑 JPA를 이용해 데이터베이스의 테이블과 상호 작용(데이터 저장, 수정, 조회, 삭제 등)하기 위해 가장 우선되는 작업은 데이터베이스의 테이블과 엔티티 클래스 간의 매핑 작업니다. 엔티티 매핑 작업은 크게 객체와 테이블 간의 매핑, 기본키 매핑, 필드(멤버 변수)와 컬럼 간의 매핑, 엔티티 간의 연관 관계 매핑 등으로 나눌 수 있다. 엔티티 테이블 간의 매핑 @Entity 애너테이션 애트리뷰트 name 엔티티 이름을 설정할 수 있다. name 애트리뷰트를 설정하지 않으면 기본값으로 클래스 이름을 엔티티 이름으로 사용한다. @Table 애너테이션 애트리뷰트 name 테이블 이름을 설정할 수 있다. name 애트리뷰트를 설정하지 않으면 기본값으로 클래스 이름을 테이블 이름으로 사용한다.
Spring Data JPA JPA(Java Persistence API)란? JPA는 Java 진영에서 사용하는 ORM(Object-Relational Mapping) 기술의 표준 사양(또는 명세, Specification)이다. 표준 사양은 Java의 인터페이스로 사양이 정의되어 있기 때문에 JPA라는 표준 사양을 구현한 구현체는 따로 있다는 것을 의미한다. JPA 표준 사양을 구현한 구현체로 Hibernate ORM, EclipseLink, DataNucleus 등이 있다. 이 Hibernate ORM은 JPA에서 정의해둔 인터페이스를 구현한 구현체로써 JPA에서 지원하는 기능 이외에 Hibernate 자체적으로 사용할 수 있는 API 역시 지원하고 있다. 데이터 액세스 계층에서의 JPA 위치  및 예외 처리 체크 예외와 언체크 예외 애플리케이션에서 발생하는 예외(Exception)는 크게 체크 예외(Check Exception)와 언체크 예외(Unchecked Exception)로 구분할 수 있다. 체크 예외 예외를 잡아서(catch) 체크한 후에 해당 예외를 복구 또는 회피 등의 어떤 구체적인 처리를 해야 하는 예외 Ex) ClassNotFoundException 언체크 예외 예외를 잡아서(catch) 해당 예외에 대한 어떤 처리를 할 필요가 없는 예외 Ex) NullPointerException, ArrayIndexOutOfBoundsException 개발자가 의도적으로 예외를 던질 수 있는 상황 백엔드 서버와 외부 시스템과의 연동에서 발생하는 에러 처리 **시스템 내부에서
Spring MVC에서의 예외 처리 @RestControllerAdvice를 이용한 예외처리 @RestControllerAdvice를 사용한 예외 처리 공통화 애너테이션을 추가한 클래스를 이용하면 예외 처리를 공통화할 수 있다. 특정 클래스에 애너테이션을 추가하면 여러개의 Controller 클래스에서 , 또는 가 추가된 메서드를 공유해서 사용할 수 있다. @RestControllerAdvice 적용 순서 기존의 Controller 클래스에서 사용한 가 추가된 메서드는 특정 클래스에서 공통으로 처리되므로 모두 제거한다. ExceptionAdvice 클래스 정의 Controller 클래스에서 발생하는 예외들을 공통으로 처리할 클래스 정의 Exception 핸들러 메서드 구현 ErrorResponse 수정 Exception 핸들러 메서드 수정 @RestControllerAdvice 적용 방식 E