1. Board_Test
@Test
public void mFindAll1_test() throws JsonProcessingException {
// given
String title = "제목";
// when
Pageable pageable = PageRequest.of(0, 3);
Page<Board> boardPG = boardRepository.mfindAll1(title, pageable);
// eye
ObjectMapper om = new ObjectMapper();
String responseBody = om.writeValueAsString(boardPG);
//om.readValue(responseBody, Board.class);
System.out.println(responseBody);
}
- 코드설명
이 코드는 JUnit을 사용한 테스트 메소드로, 게시물 조회 기능을 검증하는 테스트입니다. 이 테스트는 제목을 기준으로 게시물을 검색하고 페이지네이션을 적용하여 결과를 얻는 로직을 확인합니다.
1. 메소드 시그니처
@Test
public void mFindAll1_test() throws JsonProcessingException {
- @Test: 이 메소드는 JUnit 테스트 메소드임을 나타냅니다.
- throws JsonProcessingException:
ObjectMapper
를 사용해 JSON 변환 작업을 할 때 발생할 수 있는 예외를 처리하기 위해 선언한 부분입니다.
2. given (테스트 준비)
String title = "제목";
- 테스트에 필요한 입력 값을 설정합니다.
- 여기서는
title
변수에"제목"
을 설정하여 제목을 기준으로 게시물을 조회하려고 합니다.
3. when (실제 테스트 대상 실행)
Pageable pageable = PageRequest.of(0, 3);
Page<Board> boardPG = boardRepository.mfindAll1(title, pageable);
- Pageable: 페이지네이션을 위한 객체로,
PageRequest.of(0, 3)
는 0번 페이지(첫 번째 페이지)에서 3개의 게시물을 가져오도록 요청합니다. - 첫 번째 인자
0
: 페이지 번호. - 두 번째 인자
3
: 한 페이지에 표시할 게시물의 개수.
- boardRepository.mfindAll1(title, pageable):
boardRepository
에서title
과pageable
을 기준으로 게시물을 검색하는 메소드입니다. 이 메소드는 제목에 해당하는 게시물 리스트를 페이지 단위로 반환합니다. 반환 타입은Page<Board>
입니다. mfindAll1
: 사용자 정의된 쿼리 메소드일 가능성이 높습니다.Page<Board>
: 결과는 페이지 객체로 반환되며, 내부에 게시물(Board) 리스트와 페이지네이션 관련 정보를 담고 있습니다.
4. eye (결과 검증을 위한 JSON 변환 및 출력)
ObjectMapper om = new ObjectMapper();
String responseBody = om.writeValueAsString(boardPG);
System.out.println(responseBody);
- ObjectMapper:
jackson-databind
라이브러리의 클래스이며, 자바 객체를 JSON 형식으로 변환하거나, 그 반대로 변환할 때 사용됩니다. om.writeValueAsString(boardPG)
:boardPG
객체를 JSON 문자열로 변환합니다.- responseBody: JSON으로 변환된 결과가 문자열로 저장됩니다.
- System.out.println(responseBody): 변환된 JSON 문자열을 콘솔에 출력합니다. 이를 통해 결과가 제대로 나오는지 확인할 수 있습니다.
주석 처리된 코드
// om.readValue(responseBody, Board.class);
- 이 주석은 JSON 문자열을 다시 자바 객체로 변환하는 코드입니다.
om.readValue(responseBody, Board.class)
는 JSON 문자열을Board
객체로 역직렬화(deserialize)합니다. 테스트에서는 필요 없는 부분이라 주석 처리한 것 같습니다.
전체적인 흐름
"제목"
이라는 제목을 가진 게시물을 검색하고, 첫 번째 페이지에서 3개의 게시물을 요청합니다.
- 결과로 반환된 게시물 리스트 및 페이지 정보를 JSON 형식으로 변환하여 출력합니다.
- 이 테스트는 데이터베이스에 올바르게 쿼리가 실행되는지, 그리고 페이지네이션이 잘 적용되는지를 검증합니다.
2. 테스트 결과 → JSON viewer로 보기!
{"content":[{"id":5,"title":"제목5","content":"내용5","createdAt":1726102187386},
{"id":4,"title":"제목4","content":"내용4","createdAt":1726102187386},
{"id":3,"title":"제목3","content":"내용3","createdAt":1726102187385}],
"pageable":{"pageNumber":0,"pageSize":3,"sort":{"empty":true,"sorted":false,"unsorted":true},
"offset":0,"paged":true,"unpaged":false},
"last":false,"totalElements":5,
"totalPages":2,"size":3,"number":0,
"sort":{"empty":true,"sorted":false,"unsorted":true},
"first":true,"numberOfElements":3,"empty":false}

이 JSON 구조는 페이지네이션(pagination)을 처리하는 객체를 나타내고 있습니다. 아래는 각 필드에 대한 설명입니다:
- content: 배열(
[]
) 형태로 나타나 있으며, 실제 데이터가 들어갈 자리입니다. 여기서는 데이터가 비어 있습니다.
- pageable: 페이지네이션 관련 정보를 담고 있는 객체입니다.
- last:
false
로 설정되어 있어, 현재 페이지가 마지막 페이지가 아님을 의미합니다. - totalElements: 총 5개의 요소가 있음을 나타냅니다.
- totalPages: 총 2개의 페이지로 나누어져 있음을 의미합니다.
- size: 한 페이지당 3개의 요소를 표시합니다.
- number: 현재 페이지 번호를 나타내며, 0은 첫 번째 페이지임을 의미합니다.
- sort: 정렬 정보와 관련된 객체입니다.
- first:
true
로 설정되어 있어, 현재 페이지가 첫 번째 페이지임을 나타냅니다. - numberOfElements: 현재 페이지에 3개의 요소가 포함되어 있음을 의미합니다.
- empty:
false
로 설정되어 있어, 페이지가 비어 있지 않음을 나타냅니다.
이 구조는 서버에서 페이지별 데이터를 처리할 때 사용되는 일반적인 JSON 형태로, 페이지네이션 및 정렬 상태를 설명하고 있습니다.
※ 테스트 오류(ByteBuddy 란)
ByteBuddy는 자바 언어에서 바이트코드 조작을 통해 동적으로 클래스를 생성하거나 수정할 수 있는 라이브러리입니다. 이 라이브러리는 리플렉션(reflection)보다 더 효율적이며, 자바의 바이트코드를 런타임에 직접 조작할 수 있는 강력한 도구입니다.
주요 특징:
- 런타임에 클래스 생성 및 수정:
- ByteBuddy를 사용하면 런타임 시점에 동적으로 새로운 클래스를 생성하거나, 기존 클래스를 수정하여 새로운 메소드나 필드를 추가할 수 있습니다.
- 예를 들어, 프록시 클래스나 인터셉터 클래스와 같은 구조를 쉽게 구현할 수 있습니다.
- 자바 바이트코드 조작:
- 바이트코드는 자바 소스코드가 컴파일된 후 JVM에서 실행되는 중간 코드입니다. ByteBuddy는 이 바이트코드를 조작하여 특정 기능을 추가하거나 기존 동작을 변경할 수 있습니다.
- 높은 성능:
- 자바 리플렉션은 런타임에 메타 데이터를 사용하여 클래스 및 객체 정보를 읽고 수정할 수 있는 기능을 제공하지만, 성능 면에서 다소 느릴 수 있습니다. ByteBuddy는 바이트코드를 직접 수정하기 때문에 리플렉션에 비해 성능이 뛰어납니다.
- 에이전트 및 프레임워크 통합:
- ByteBuddy는 자바의 에이전트 API와 통합되어 애플리케이션의 동작을 변경하거나 프로파일링, 로깅 등을 구현하는 데 사용할 수 있습니다. 대표적인 예로 스프링의 AOP(Aspect-Oriented Programming)에서 ByteBuddy를 사용할 수 있습니다.
- 간단한 API:
- 복잡한 바이트코드 조작을 쉽게 수행할 수 있는 간단한 API를 제공합니다. 직접 바이트코드를 다루는 것에 비해 훨씬 직관적이고 코드가 간결합니다.
예시 코드:
public class Example {
public static void main(String[] args) throws Exception {
// ByteBuddy를 사용하여 새로운 클래스를 생성하고 메소드를 추가함
Class<?> dynamicType = new ByteBuddy()
.subclass(Object.class) // Object 클래스를 상속하는 새 클래스를 생성
.method(ElementMatchers.named("toString")) // toString 메소드를 오버라이드
.intercept(FixedValue.value("Hello ByteBuddy!")) // toString 메소드는 "Hello ByteBuddy!"를 반환
.make()
.load(Example.class.getClassLoader())
.getLoaded();
// 동적으로 생성된 클래스의 인스턴스를 생성하고 toString 호출
System.out.println(dynamicType.newInstance().toString()); // 출력: Hello ByteBuddy!
}
}
주요 용도:
- 프록시 클래스 생성:
- 클래스의 동작을 가로채기 위해 프록시 클래스를 생성할 수 있습니다.
- 런타임에서의 동적 클래스 수정:
- 런타임에 클래스의 메소드를 추가하거나 기존 메소드의 동작을 수정할 수 있습니다.
- 코드 성능 최적화:
- 리플렉션을 사용할 때보다 더 빠르게 동적으로 클래스를 생성하거나 수정할 수 있습니다.
- AOP 구현:
- 특정 메소드에 대해 사전 또는 사후에 동작을 추가하는 AOP와 같은 기능을 구현할 때 유용합니다.
ByteBuddy는 매우 유연하고, 고급 기능을 제공하여 자바 개발에서 필요한 동적 클래스 생성 및 조작 작업을 손쉽게 수행할 수 있게 해줍니다.
Share article