해결된 질문
작성
·
38
0
todo list 에서 검색어를 입력하여 검색된 결과를 화면에 출력하려면 어떻게 구현해야 하는지요?
예제에는 이런 것이 없는 거 같은데 제가 대충봐서 잘못 이해하고 있는 건가요?
전체적인 흐름으로 설명해주시면 감사하겠습니다.
답변 2
0
좋은 질문 감사합니다.
우선 라우팅 환경에서 검색이란 URL에 검색 관련 키워드 등이 쿼리 스트링으로 처리되어야 합니다.
/list?page=1&size=10&keyword=AAA 와 같은 형식으로 만들어져야 합니다.
따라서 검색 조건을 담당하는 컴포넌트를 작성하고 키워드를 입력한 후에 검색 버튼을 클릭하면 URL에 검색 조건이 포함되도록 해야 합니다.
실제 리스트를 출력하는 컴포넌트는 추가적으로 키워드를 받아서 서버를 호출하고 해당 결과를 출력하는 형태가 되면 됩니다.
0
안녕하세요, 인프런 AI 인턴입니다.
Link님께서 물어보신 Todo List 검색 기능 구현에 대한 질문은 React와 Spring Boot의 통합 과정에서 필수적인 부분입니다. 아래에서는 검색 기능을 구현하기 위한 간단한 흐름을 설명드리겠습니다.
입력 필드 만들기
검색어 상태 관리
useState
등을 사용해 상태로 관리하여, 상태 변화를 실시간으로 감지할 수 있도록 준비합니다.API 요청
title
이나 content
가 검색어를 포함하는지를 조건으로 검색할 수 있습니다.검색 버튼 클릭 이벤트 핸들러
fetch
나 axios
같은 HTTP 클라이언트를 활용할 수 있습니다.검색 결과 출력
비슷한 질문이 있는 게시물을 통해 검색 기능에 대한 이해를 더욱 높이실 수 있습니다:
각 링크에서는 사용자가 마주할 수 있는 예외 상황과 그 해결책이 소개되어 있으니 참고하시기 바랍니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @Data @SuperBuilder // - **상속 관계가 있는 클래스**에서 부모 클래스의 빌더 패턴을 지원하기 위해 사용된다. @AllArgsConstructor // 모든 필드에 대해 값을 받아 전체 매개변수 생성자를 자동으로 생성한다. @NoArgsConstructor public class PageRequestDTO { @Builder.Default // 값을 명시적으로 설정하지 않을 때만 기본값을 부여 private int page = 1; @Builder.Default private int size = 10; private Integer blockSize; // Integer로 변경 (null 체크 가능하게) private String where; // 검색 KEY 추가 private String keyword; // 검색어 public int getBlockSize() { // blockSize가 null이면 size와 동일하게 처리 return (blockSize != null) ? blockSize : size; } }
import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class QueryDslConfig { @PersistenceContext private EntityManager entityManager; @Bean public JPAQueryFactory jpaQueryFactory() { return new JPAQueryFactory(entityManager); } }
@Service @Transactional @Log4j2 @RequiredArgsConstructor // 생성자 자동 주입 public class TodoServiceImpl implements TodoService { // 자동 주입 대상은 final 로 private final ModelMapper modelMapper; private final TodoRepository todoRepository; @Override public PageResponseDTO<TodoDTO> searchList(PageRequestDTO pageRequestDTO) { Page<Todo> result = todoRepository.search1(pageRequestDTO); Pageable pageable = PageRequest.of( pageRequestDTO.getPage() - 1 , // 1페이지가 0이므로 주의 pageRequestDTO.getSize(), Sort.by("tno").descending()); List<TodoDTO> dtoList = result.getContent().stream() .map(todo -> modelMapper.map(todo, TodoDTO.class)) .collect(Collectors.toList()); log.info("dtoList: " + dtoList); long totalCount = result.getTotalElements(); log.info("totalCount: " + totalCount); PageResponseDTO<TodoDTO> responseDTO = PageResponseDTO.<TodoDTO>withAll() .dtoList(dtoList) .pageRequestDTO(pageRequestDTO) .totalCount(totalCount) .build(); return responseDTO; } }
@Service @Transactional @Log4j2 @RequiredArgsConstructor // 생성자 자동 주입 public class TodoSearchImpl implements TodoSearch { private final JPAQueryFactory queryFactory; @Override public Page<Todo> search1(PageRequestDTO pageRequestDTO) { QTodo qTodo = QTodo.todo; BooleanBuilder builder = new BooleanBuilder(); String keyword = pageRequestDTO.getKeyword(); String where = pageRequestDTO.getWhere(); // 검색 조건 적용 if (keyword != null && !keyword.trim().isEmpty()) { switch (where) { case "title": builder.and(qTodo.title.containsIgnoreCase(keyword)); break; case "writer": builder.and(qTodo.writer.containsIgnoreCase(keyword)); break; default: builder.and( qTodo.title.containsIgnoreCase(keyword) .or(qTodo.writer.containsIgnoreCase(keyword)) ); } } Pageable pageable = PageRequest.of( pageRequestDTO.getPage() - 1, pageRequestDTO.getSize(), Sort.by("tno").descending() ); JPAQuery<Todo> query = queryFactory .selectFrom(qTodo) .where(builder) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .orderBy(qTodo.tno.desc()); List<Todo> resultList = query.fetch(); long totalCount = queryFactory .select(qTodo.count()) .from(qTodo) .where(builder) .fetchOne(); return new PageImpl<>(resultList, pageable, totalCount); } }
위와 같이 해서 해결했습니다.
감사합니다.