Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #웹개발
- aws #아키텍트 #과정 #vpc #인프라 구축 #haproxy #고가용성 #테스트 #alb #application #load balancer #application
- aws #아키텍트 #과정 #vpc #인프라 구축 #amazon sns #server #less #architecture
- aws #아키텍트 #과정 #vpc #인프라 구축 #s3 #bucket #객체 #스토리지 #isci #이미지 #업로드
- aws #아키텍트 #과정 #vpc #인프라 구축
- aws #아키텍트 #과정 #vpc #인프라 구축 #ec2 #instance #launch #template #생성 #ami #amazone #machine #image
- 썸네일 #이미지
- aws #아키텍트 #과정 #vpc #인프라 구축 #sqs #message #queue #sns구독
- aws #아키텍트 #과정 #vpc #인프라 구축 #rds #endpoint #cloudwatch #monitoring
- aws #아키텍트 #과정 #vpc #인프라 구축 #sqs #trigger #python3.9 #패키지 #
- 프로세스 #CPU #시공유 #커널
- aws #아키텍트 #과정 #vpc #인프라 구축 #alb #load balancer #t.g #target #group #haproxy #high ability #db #replica #region
- aws #아키텍트 #과정 #vpc #인프라 구축 #rds #replica #복제본 #aurora #database #고가용성
- 공간복잡도 #공간자원 #캐시메모리 #SRAM #DRAM #시간복잡도
- aws #아키텍트 #과정 #vpc #인프라 구축 #auto scailling #lauch template #ec2 instace #private #subnet
- aws #아키텍트 #과정 #vpc #인프라 구축 #php #alb #application #load #balancer #security #group #igw #ec2 #vpc #virtual #private #cloud
- aws #아키텍트 #과정 #vpc #인프라 구축 #s3 #bucket #객체 스토리지 #objects storage #events #upload #알림
- aws #아키텍트 #과정 #vpc #인프라 구축 #db #장애조치 #reand only #replica #events
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- aws #아키텍트 #과정 #vpc #인프라 구축 #second nat #gateway #routing table #route53 #고가용성 #private subnet #
- 쓰레드 #쓰레드풀 #프로세스
- aws #아키텍트 #과정 #vpc #인프라 구축 #aurora #database #rds #rdbs #load #balancer #web #page #haproxy
- 업로드 #lambda #함수 #모바일 이미지 #썸네일 이미지
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #OSI #ISO #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- aws #아키텍트 #과정 #vpc #인프라 구축 #haproxy #round robin #process #high ability #auto scailling #app server #launch template
- aws #아키텍트 #과정 #vpc #인프라 구축 #t.g #target group #alb #application #load #balancer #web #server
- 비트 #바이트 #이진수
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #KDT #기본문법 #데이터베이스 #Computer #Science #CPU #메모리
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
Archives
- Today
- Total
요리사에서 IT개발자로
(Spring Boot) Sparta Kanban Board 프로젝트 기능 이슈 및 해결 본문
1. 칸반 보드의 특정 컬럼에 새로운 카드를 생성 후에 해당 카드의 Sequence가 자동으로 증가하는 메소드
메소드 시그니처:
@Override
@Transactional
public CommonResponseDto<?> createCardAtKanbanColumn(long kanbanColumnId, CreateCardRequestDto requestDto, UserDetailsImpl userDetails)
- kanbanColumnId: 카드를 생성할 칸반 컬럼의 ID
- requestDto: 카드 생성 요청 DTO
- userDetails: 사용자 정보
컬럼 조회:
KanbanColumn kanbanColumn = columnService.findById(kanbanColumnId);
ColumnResponseDto columnResponseDto = KanbanColumn.of(kanbanColumn);
- kanbanColumnId를 이용해 컬럼을 조회하고, ColumnResponseDto로 변환합니다.
사용자 검증 및 조회:
User user;
if (Objects.equals(requestDto.getUsername(), userDetails.getUsername())) {
user = userService.findByUserName(userDetails.getUsername());
} else {
throw new IllegalArgumentException("사용자 아이디가 일치하지 않습니다.");
}
- requestDto의 사용자명과 userDetails의 사용자명을 비교하여 일치하면 사용자를 조회합니다. 일치하지 않으면 예외를 발생시킵니다.
카드 생성:
Card card = Card.of(requestDto, user, kanbanColumn);
- 요청 DTO, 사용자, 칸반 컬럼 정보를 이용해 새로운 카드를 생성합니다.
시퀀스 설정:
int newSequence = 1;
Card maxSequenceCard = cardRepository.findTopByKanbanColumnIdOrderBySequenceDesc(kanbanColumnId);
if (maxSequenceCard != null) {
int currentSequence = maxSequenceCard.getSequence();
newSequence = currentSequence + 1;
}
card.setSequence(newSequence);
- 해당 컬럼에서 가장 큰 시퀀스 값을 가진 카드를 조회하여, 그 시퀀스 값보다 1 증가된 값을 새로운 카드의 시퀀스로 설정합니다. 해당 컬럼에 카드가 없으면 기본 시퀀스를 1로 설정합니다.
카드 저장:
cardRepository.save(card);
결과 반환:
CardResponseDto cardResponseDto = CardResponseDto.of(card);
KanbanColumnAndCardAndUserResponseDto kanbanColumnAndCardAndUserResponseDto = KanbanColumnAndCardAndUserResponseDto.builder()
.column(columnResponseDto)
.card(cardResponseDto)
.build();
return CommonResponseDto.builder()
.msg("카드 생성이 완료되었습니다.")
.data(kanbanColumnAndCardAndUserResponseDto)
.build();
- 생성된 카드 정보를 CardResponseDto로 변환합니다.
- 컬럼 정보와 카드 정보를 포함한 응답 객체를 생성하여 반환합니다.
- 성공 메시지와 함께 반환합니다.
2. 선택한 카드가 현재 컬럼에서 다른 컬럼으로 이동할 때 Sequence를 조정하는 문제를 해결하기 위한 로직이 구현된 메소드
주어진 컬럼 ID, 카드 ID, 대상 컬럼 ID, 이동할 목표 순서를 입력받아 해당 카드를 이동시키고, 나머지 카드들의 순서도 조정합니다.
메소드 시그니처:
public CommonResponseDto<?> moveLocationByColumnId(long kanbanColumnId, long cardId, long targetColumnId, int moveSequence)
- kanbanColumnId: 카드를 이동시킬 출발 컬럼의 ID
- cardId: 이동할 카드의 ID
- targetColumnId: 이동할 대상 컬럼의 ID
- moveSequence: 이동할 목표 순서
컬럼 조회:
columnService.findById(kanbanColumnId);
KanbanColumn targetColumn = columnService.findById(targetColumnId);
- 출발 컬럼과 대상 컬럼을 조회합니다.
카드 조회:
Card card = findById(cardId);
- cardId를 이용해 이동할 카드를 조회합니다.
카드 목록 조회:
List<Card> sourceCardList = cardRepository.findAllByKanbanColumnIdOrderBySequenceAsc(kanbanColumnId);
List<Card> targetCardList = cardRepository.findAllByKanbanColumnIdOrderBySequenceAsc(targetColumnId);
- 출발 컬럼과 대상 컬럼의 모든 카드를 시퀀스 순으로 조회합니다.
현재 시퀀스 값 저장:
int currentSequence = card.getSequence();
출발 칼럼의 시퀀스 조정:
for (Card c : sourceCardList) {
if (c.getSequence() > currentSequence) {
c.setSequence(c.getSequence() - 1);
}
}
- 출발 컬럼에서 이동할 카드보다 시퀀스가 큰 카드들의 시퀀스를 1 감소시킵니다.
- 성공 메시지와 함께 반환합니다.
대상 칼럼의 시퀀스 조정:
for (Card c : targetCardList) {
if (c.getSequence() >= moveSequence) {
c.setSequence(c.getSequence() + 1);
}
}
- 대상 컬럼에서 목표 시퀀스보다 크거나 같은 카드들의 시퀀스를 1 증가시킵니다.
카드를 대상 칼럼으로 이동:
card.setKanbanColumn(targetColumn);
card.setSequence(moveSequence);
변경된 카드 목록 저장:
cardRepository.saveAll(sourceCardList);
cardRepository.saveAll(targetCardList);
cardRepository.save(card);
결과 반환:
CardResponseDto cardResponseDto = CardResponseDto.of(card);
KanbanColumnAndCardAndUserResponseDto kanbanColumnAndCardAndUserResponseDto = KanbanColumnAndCardAndUserResponseDto.builder()
.column(KanbanColumn.of(targetColumn))
.card(cardResponseDto)
.build();
return CommonResponseDto.builder()
.msg("카드가 칼럼 사이로 이동되었습니다.")
.data(kanbanColumnAndCardAndUserResponseDto)
.build();
- 이동된 카드 정보를 CardResponseDto로 변환합니다.
- 컬럼 정보와 카드 정보를 포함한 응답 객체를 생성하여 반환합니다.
- 성공 메시지와 함께 반환합니다
3. 칸반 보드의 특정 컬럼에서 카드의 순서를 변경하는 문제를 해결하기 위한 로직이 구현된 메소드
메소드 시그니처:
public CommonResponseDto<?> moveCardByColumnId(
long kanbanColumnId, long cardId, int moveSequence)
- kanbanColumnId: 카드를 이동시킬 컬럼의 ID
- cardId: 이동할 카드의 ID
- moveSequence: 이동할 목표 순서
컬럼 조회
KanbanColumn kanbanColumn = columnService.findById(kanbanColumnId);
ColumnResponseDto columnResponseDto = KanbanColumn.of(kanbanColumn);
- kanbanColumnId를 이용해 컬럼을 조회하고, ColumnResponseDto로 변환합니다.
카드 조회
Card card = findById(cardId);
List<Card> cardList = cardRepository.findAllByKanbanColumnId(kanbanColumnId);
- cardId를 이용해 이동할 카드를 조회하고, kanbanColumnId를 이용해 해당 컬럼의 모든 카드를 조회합니다.
현재 순서와 이동할 순서 차이 계산:
int currentSequence = card.getSequence();
int difference = moveSequence - currentSequence;
- 현재 카드의 순서와 이동할 순서의 차이를 계산합니다.
순서 변경 로직:
if (difference != 0) {
for (Card c : cardList) {
int cSequence = c.getSequence();
if (!c.getId().equals(cardId) &&
(difference > 0 && cSequence > currentSequence && cSequence <= moveSequence)
||
(difference < 0 && cSequence < currentSequence && cSequence >= moveSequence)
) {
c.setSequence(cSequence + (difference > 0 ? -1 : 1));
}
}
card.setSequence(moveSequence);
cardRepository.saveAll(cardList);
}
- 순서 차이가 있을 때만 동작합니다.
- 모든 카드를 순회하며, 이동할 카드가 아닌 경우 순서 이동 범위 내에 있는 카드의 순서를 조정합니다.
- 이동 방향에 따라 해당 카드의 순서를 증가 또는 감소시킵니다.
- 이동할 카드의 순서를 목표 순서로 설정합니다.
- 변경된 카드 목록을 저장합니다.
결과 반환:
CardResponseDto cardResponseDto = CardResponseDto.of(card);
KanbanColumnAndCardAndUserResponseDto kanbanColumnAndCardAndUserResponseDto = KanbanColumnAndCardAndUserResponseDto.builder()
.column(columnResponseDto)
.card(cardResponseDto)
.build();
return CommonResponseDto.builder()
.msg("카드 순서 변경이 완료되었습니다.")
.data(kanbanColumnAndCardAndUserResponseDto)
.build();
- 이동된 카드 정보를 CardResponseDto로 변환합니다.
- 컬럼 정보와 카드 정보를 포함한 응답 객체를 생성하여 반환합니다.
- 성공 메시지와 함께 반환합니다.
4 . 칸반 보드의 특정 컬럼에서 카드를 삭제하면 나머지 카드들의 Sequence가 감소되는 메소드
입력된 컬럼 ID, 카드 ID, 사용자 정보를 받아 해당 카드를 삭제하고, 나머지 카드들의 시퀀스를 조정
주어진 정보를 기반으로 특정 카드를 삭제하고, 해당 카드의 시퀀스보다 큰 시퀀스를 가진 카드들의 시퀀스를 1씩 감소시켜 저장한 후, 결과를 사용자에게 반환합니다.
메소드 시그니처:
@Override
@Transactional
public CommonResponseDto<?> deleteFindByKanbanColumnIdAndCard(long kanbanColumnId, long cardId, UserDetailsImpl userDetails)
- kanbanColumnId: 카드를 삭제할 칸반 컬럼의 ID
- cardId: 삭제할 카드의 ID
- userDetails: 사용자 정보
카드 조회:
Card cardToDelete = findById(cardId);
사용자 검증:
if (!Objects.equals(cardToDelete.getUsername(), userDetails.getUsername())) {
throw new IllegalArgumentException("작성자가 일치하지 않습니다.");
}
- cardToDelete의 작성자와 userDetails의 사용자명이 일치하지 않으면 예외를 발생시킵니다.
삭제할 카드의 시퀀스 값 저장:
int deletedCardSequence = cardToDelete.getSequence();
시퀀스 조정할 카드 목록 조회:
List<Card> cardsToUpdateSequence = cardRepository.findAllByKanbanColumnIdAndSequenceGreaterThan(kanbanColumnId, deletedCardSequence);
- 삭제할 카드의 시퀀스 값보다 큰 시퀀스를 가진 카드들을 조회합니다.
카드들의 시퀀스 값 조정:
for (Card card : cardsToUpdateSequence) {
int currentSequence = card.getSequence();
card.setSequence(currentSequence - 1);
}
카드 목록과 삭제할 카드 저장:
cardRepository.saveAll(cardsToUpdateSequence);
cardRepository.delete(cardToDelete);
결과 반환:
return CommonResponseDto.builder()
.msg("카드 삭제가 완료되었습니다.")
.data("Deleted Card ID: " + cardToDelete.getId())
.build();
- 성공 메시지와 함께 삭제된 카드의 ID를 반환합니다.
칸반 보드 기능 메소드 구현 정리
1. 칸반 보드의 특정 컬럼에 새로운 카드를 생성 후에 해당 카드의 Sequence가 자동으로 증가하는 메소드
최종 코드:
@Override
@Transactional
public CommonResponseDto<?> createCardAtKanbanColumn(long kanbanColumnId,
CreateCardRequestDto requestDto, UserDetailsImpl userDetails
) {
KanbanColumn kanbanColumn = columnService.findById(kanbanColumnId);
ColumnResponseDto columnResponseDto = KanbanColumn.of(kanbanColumn);
User user;
if (Objects.equals(requestDto.getUsername(), userDetails.getUsername())) {
user = userService.findByUserName(userDetails.getUsername());
} else {
throw new IllegalArgumentException("사용자 아이디가 일치하지 않습니다.");
}
Card card = Card.of(requestDto, user, kanbanColumn);
int newSequence = 1;
Card maxSequenceCard = cardRepository.findTopByKanbanColumnIdOrderBySequenceDesc(
kanbanColumnId);
if (maxSequenceCard != null) {
int currentSequence = maxSequenceCard.getSequence();
newSequence = currentSequence + 1;
}
card.setSequence(newSequence);
cardRepository.save(card);
CardResponseDto cardResponseDto = CardResponseDto.of(card);
KanbanColumnAndCardAndUserResponseDto kanbanColumnAndCardAndUserResponseDto = KanbanColumnAndCardAndUserResponseDto.builder()
.column(columnResponseDto)
.card(cardResponseDto)
.build();
return CommonResponseDto.builder()
.msg("카드 생성이 완료되었습니다.")
.data(kanbanColumnAndCardAndUserResponseDto)
.build();
}
2. 선택한 카드가 현재 컬럼에서 다른 컬럼으로 이동할 때 Sequence를 조정하는 메소드
최종 코드:
@Override
@Transactional
public CommonResponseDto<?> moveLocationByColumnId(long kanbanColumnId, long cardId,
long targetColumnId, int moveSequence) {
columnService.findById(kanbanColumnId);
KanbanColumn targetColumn = columnService.findById(targetColumnId);
Card card = findById(cardId);
// 출발 칼럼의 카드 목록 가져오기
List<Card> sourceCardList = cardRepository.findAllByKanbanColumnIdOrderBySequenceAsc(
kanbanColumnId);
// 대상 칼럼의 카드 목록 가져오기
List<Card> targetCardList = cardRepository.findAllByKanbanColumnIdOrderBySequenceAsc(
targetColumnId);
int currentSequence = card.getSequence();
// 출발 칼럼의 시퀀스 조정
for (Card c : sourceCardList) {
if (c.getSequence() > currentSequence) {
c.setSequence(c.getSequence() - 1);
}
}
// 대상 칼럼의 시퀀스 조정
for (Card c : targetCardList) {
if (c.getSequence() >= moveSequence) {
c.setSequence(c.getSequence() + 1);
}
}
// 카드를 대상 칼럼으로 이동하고 새로운 시퀀스 설정
card.setKanbanColumn(targetColumn);
card.setSequence(moveSequence);
cardRepository.saveAll(sourceCardList);
cardRepository.saveAll(targetCardList);
cardRepository.save(card);
CardResponseDto cardResponseDto = CardResponseDto.of(card);
KanbanColumnAndCardAndUserResponseDto kanbanColumnAndCardAndUserResponseDto = KanbanColumnAndCardAndUserResponseDto.builder()
.column(KanbanColumn.of(targetColumn))
.card(cardResponseDto)
.build();
return CommonResponseDto.builder()
.msg("카드가 칼럼 사이로 이동되었습니다.")
.data(kanbanColumnAndCardAndUserResponseDto)
.build();
}
3. 칸반 보드의 특정 컬럼에서 카드의 순서를 변경하는 메소드
최종 코드:
@Override
@Transactional
public CommonResponseDto<?> moveCardByColumnId(long kanbanColumnId, long cardId,
int moveSequence
) {
KanbanColumn kanbanColumn = columnService.findById(kanbanColumnId);
ColumnResponseDto columnResponseDto = KanbanColumn.of(kanbanColumn);
Card card = findById(cardId);
List<Card> cardList = cardRepository.findAllByKanbanColumnId(kanbanColumnId);
int currentSequence = card.getSequence();
int difference = moveSequence - currentSequence;
if (difference != 0) {
for (Card c : cardList) {
int cSequence = c.getSequence();
if (!c.getId().equals(cardId) &&
(difference > 0 && cSequence > currentSequence && cSequence <= moveSequence)
||
(difference < 0 && cSequence < currentSequence && cSequence >= moveSequence)
) {
c.setSequence(cSequence + (difference > 0 ? -1 : 1));
}
}
card.setSequence(moveSequence);
cardRepository.saveAll(cardList);
}
CardResponseDto cardResponseDto = CardResponseDto.of(card);
KanbanColumnAndCardAndUserResponseDto kanbanColumnAndCardAndUserResponseDto = KanbanColumnAndCardAndUserResponseDto.builder()
.column(columnResponseDto)
.card(cardResponseDto)
.build();
return CommonResponseDto.builder()
.msg("카드 순서 변경이 완료되었습니다.")
.data(kanbanColumnAndCardAndUserResponseDto)
.build();
}
4. 칸반 보드의 특정 컬럼에서 카드를 삭제하면 나머지 카드들의 Sequence가 감소되는 메소드
최종 코드:
@Override
@Transactional
public CommonResponseDto<?> deleteFindByKanbanColumnIdAndCard(long kanbanColumnId,
long cardId, UserDetailsImpl userDetails
) {
Card cardToDelete = findById(cardId);
if (!Objects.equals(cardToDelete.getUsername(), userDetails.getUsername())) {
throw new IllegalArgumentException("작성자가 일치하지 않습니다.");
}
int deletedCardSequence = cardToDelete.getSequence();
List<Card> cardsToUpdateSequence = cardRepository.findAllByKanbanColumnIdAndSequenceGreaterThan(
kanbanColumnId, deletedCardSequence);
for (Card card : cardsToUpdateSequence) {
int currentSequence = card.getSequence();
card.setSequence(currentSequence - 1);
}
cardRepository.saveAll(cardsToUpdateSequence);
cardRepository.delete(cardToDelete);
return CommonResponseDto.builder()
.msg("카드 삭제가 완료되었습니다.")
.data("Deleted Card ID: " + cardToDelete.getId())
.build();
}
반응형
'프로젝트' 카테고리의 다른 글
(스파르타 코딩클럽) 최종 프로젝트 Challengers-BOD (0) | 2024.08.21 |
---|---|
스파르타 코딩클럽 부트캠프 NewsFeed 프로젝트 KPT회고 (0) | 2024.06.11 |
스파르타 코딩클럽 부트캠프 수강생관리프로그램 자료 (0) | 2024.05.09 |
스파르타 코딩클럽 부트캠프 미니프로젝트 관련 자료 (0) | 2024.04.19 |