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 |
Tags
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #KDT #기본문법 #데이터베이스 #Computer #Science #CPU #메모리
- 공간복잡도 #공간자원 #캐시메모리 #SRAM #DRAM #시간복잡도
- 챌린저스 #bod
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #get방식 #post방식 #http프로토콜 #클라이언트 #백엔드 #api
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #트랜잭션전파 #transaction
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #웹개발
- 쓰레드 #쓰레드풀 #프로세스
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #ci #cd
- 프로세스 #CPU #시공유 #커널
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #소셜로그인 #네이버 #기능구현 #vue.js #spring boot #네이버로그인 #연동하기
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #ci #ioc #의존성
- 보안 #이슈
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #tdd #테스트 주도개발 #테스트코드 #유닛테스트
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- spring security #jwt 토큰 #json web token #token #직렬화 #인증
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #딥러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #springmvc패턴 #model #view #controller
- ci/cd파이프라인
- 스파르타 코딩클럽 #내배캠 #최종프로젝트 #4개월삭제 #국비지원 #자바
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #대용량트래픽 #처리방법 #캐싱 #코드최적화 #db최적화 #트래픽 #로드밸런서
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #머신러닝 #AI #서버 #자동화 #SQL #기본문법 #데이터베이스
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #최종프로젝트 #aws s3 #프로필 이미지 수정 #자동삭제
- 스파르타 코딩클럽 #내배캠 #모의면접 #예상질문 #http 메서드 종류 #메서드 #post #put #get #patch #aop #관점지향프로그래밍 #유지보수
- 스파르타 코딩클럽 #내배캠 #최종프로젝트 #로그인 #인증인가 #jwt? #토큰인증 #액세스토큰 #리프레시토큰 #쿠키 #파싱 #서명키의 중요성 #security context holder
- 스파르타 코딩클럽 #인메모리db #h2 #연동이슈 #문제해결 #방법 #spring security #header #
- 인가 #
- java5기
- 스파르타코딩클럽 #부트캠프 #IT #백엔드 #OSI #ISO #AI #서버 #자동화 #SQL #기본문법 #데이터베이스 #DBMS #Oracle #MongoDB #아키텍쳐 #DB
- 스프링 #백엔드 #자바
- 비트 #바이트 #이진수
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 |