티스토리 뷰
그리드간 형태 드래그 기능 예시
Sort 5를 Sort 2로 드래그를 하여 Sort 1과 Sort 2사이에 삽입이 되었다.
그래서 Sort 2이후의 순번들은 하나씩 밀리게 된다.
나의 문제 상황
나는 이 그리드간 드래그 앤 드랍기능을 구현하면서 성능을 하나도 고려하지 않고 그냥 기능 구현에 급급했다.
구현은 되었고 코드 리뷰와 테스트를 할 때 몇가지의 문제 상황을 발견하였다.
- 드래그를 하여 순번이 바뀌면 전체의 순번을 재정렬을 하는 코드로 구현하였다.
- 중간에 삭제를 하면 전체의 순번을 재정렬하는 코드로 구현하였다.
- JPA를 사용하여 저장을 하였는데 전체의 순번을 재정렬하는데 반복문을 돌리면서 커넥션을 막 찌르고 있었다.
지금 생각해보면 진짜 개발도 못 하였고 개발자가 아닌 공부하는 것처럼, 학생처럼 개발하게 되었다는 것에 너무 부끄러웠다...
구현 할 때 고려할 상황이면서 해결 방법
1) 드래그 할 때 순번 정렬 Solution1
그림과 같이 Sort 5를 Sort 1과 Sort 2에 사이에 뒀을 때 전체를 정렬을 해주었다.
하지만 내가 바꾼 요소의 이전 Sort 값과 바꿔서 들어간 새로운 Sort 값 사이만 정렬해주면 되는거 였다.
- Sort 2, Sort 3, Sort 4들은 각각 Sort + 1 을 해준다.
- Sort 5값은 Sort 2로 변경해준다. (현행화)
그럼 꼭 필요한 값들은 무엇일까?
드래그한 요소(Sort 5)의 ID값, 드래그 하기전에 이전 Sort 값 , 드래그 후 이동한 Sort값이 필요할 것이다.
서비스 로직이 아닌 DB에 있는 데이터를 어떻게 변경해야하는지 보겠다.
-- 드래그 하기전에 이전 Sort 값 = 5
-- 드래그 후 이동한 Sort값 = 2
UPDATE yourTable
SET sort = sort + 1
WHERE 2 <= sort AND sort < 5
-- 드래그한 요소(Sort 5)의 ID값 = 5
UPDATE yourTable
SET sort = 2
WHERE id = 5
이렇게 UPDATE 쿼리문 하나로 DB의 커넥션 영향도는 2번으로 줄였다.
2) 드래그할 때 순번정렬 Solution2
- Sort 3, Sort 4, Sort 5들은 각각 Sort - 1 을 해준다.
- Sort 2값은 Sort 5로 변경해준다. (현행화)
그럼 꼭 필요한 값들은 무엇일까?
드래그한 요소(Sort 2)의 ID값, 드래그 하기전에 이전 Sort 값 , 드래그 후 이동한 Sort값이 필요할 것이다.
-- 드래그 하기전에 이전 Sort 값 = 2
-- 드래그 후 이동한 Sort값 = 5
UPDATE yourTable
SET sort = sort - 1
WHERE 2 < sort AND sort <= 5
-- 드래그한 요소(Sort 2)의 ID값 = 2
UPDATE yourTable
SET sort = 5
WHERE id = 2
이렇게 UPDATE 쿼리문 하나로 DB의 커넥션 영향도는 2번으로 줄였다.
3) 중간에 삭제하면 정렬
그림과 같이 Sort 3을 삭제하게 된다면 그 이후에 있는 요소들만 Sort -1 를 해주면 된다.
그러곤 이후에 Sort 3에 있는 것을 use_Yn 칼럼이 있거나 Del_Yn 칼럼이 있으면 값을 변경해주거나
해당 칼럼이 없다면 아예 DELETE 처리해주면 드래그 했을 때 순서가 DB 상에서와 UI상에서 맞게 된다.
-- 삭제한 요소 Sort = 3
-- 삭제한 요소 ID = 3
-- 이후에 있는 Sort값을 하나씩 줄여서 값 현행화
UPDATE yourTable
SET sort = sort -1
WHERE 3 < sort
4) DB 커넥션 막 찌르지 않기!
아래는 절대 하지 말아야할 코드입니다.
설명을 조금하자면 그리드에 있는 데이터를 List로 조회 한 후 반복문을 돌리고 Sort값을 변경하여 새롭게 저장하는 방법이였습니다.
@Service
@Requiredargsconstructor
public class YourServiceImpl implements YourService {
@Autowired
private final YourRepository yourRepository;
public logic(Long oldSort, Long newSort, Long Id, Long groupId) {
// 드래그하는 그리그 그룹별로 있기 때문에 그룹을 통해 리스트로 가져오기
List<BoardEntity > list = yourRepository.findByGroupId(groupId);
// 반복문 돌리면서 Sort값 새롭게 해주고 저장
for(BoardEntity board : list) {
Long sort = board.getSort();
board.setSort(sort + 1);
yourRepository.save(board);
}
}
}
이렇게 되면 데이터가 1만건 10만건일 경우 DB를 막 찌를 뿐만 아니라 여러명에서 이 로직을 요청하게 된다면 너무 큰일 날 수 도 있습니다.
그래서 DB저장할 때는 한번에 저장할 수 있는 방법을 찾으시고 반복문도 조금 지양해주면 깔끔한 코드가 완성될 것같습니다.
그래서 저는 UPDATE를 사용하는 방법으로 하게 되었습니다.
감사합니다.
'백엔드 > 🎃세부 설계' 카테고리의 다른 글
[디자인패턴] Proxy 프록시 패턴 : 코드 보안과 성능 향상을 위한 패턴 (0) | 2024.05.30 |
---|---|
[디자인패턴] Strategy 전략 패턴 : 효율적인 코드 재사용을 위한 전략 패턴 (0) | 2024.05.23 |
[디자인패턴] Template Method 템플릿 메서드 : 모순없는 상태 보장하기 (0) | 2024.05.16 |
[Process] 더보기 : 컨텐츠 더 보기 기능을 구현할 때 고려해야할 것 (0) | 2024.03.14 |
[디자인패턴] Singleton 싱글톤 : 프로그래밍 세계의 유일무이한 인스턴스 (0) | 2024.02.21 |
- Total
- Today
- Yesterday
- 개발블로그
- Cors
- 프로세스
- 오라클
- java
- 개발
- 코딩테스트
- aws
- DBeaver
- Mac
- Spring Security
- Front
- 개발자
- spring
- 디자인패턴
- Fetch
- AJAX
- 데이터 베이스
- JavaScript
- 프론트
- 자바스크립트
- 비동기
- 템플릿
- git
- 개발환경
- 네트워크
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |