inflearn logo
강의

講義

知識共有

6週間で完成!バックエンド職務経歴書の差別化戦略4選 - 似たり寄ったりの書類の中で目を引く方法

4-8. ロックの実習およびデッドロックの解決

데드락 발생 시, 외래 키를 제거하는 방법 관련 질문

解決済みの質問

87

cho766

投稿した質問数 26

0

1. 현재 학습 진도

 

2. 어려움을 겪는 부분

java spring mysql jpa

回答 2

0

dingcodingco

cho766님 좋은 질문 해주셔서 감사합니다!!

외래 키를 제거한 뒤 애플리케이션 레벨에서 무결성을 관리하는 방법, 그리고 기존 운영 중인 테이블에 적용 가능한지에 대해 같이 살펴보겠습니다.

말씀하신 방식이 거의 정확합니다. 예를 들어 event_participant에 INSERT 하기 전에, 연관된 event 테이블을 먼저 조회해서 해당 레코드가 존재하는지 확인하고, 없으면 예외를 던져서 트랜잭션을 롤백시키는 방식입니다.

실무에서는 보통 서비스 레이어에서 이런 검증 로직을 넣습니다. 코드로 표현하면 이런 흐름이 됩니다.

@Transactional
public void joinEvent(Long eventId, Long userId) {
    // 1. 참조 대상이 존재하는지 먼저 검증
    Event event = eventRepository.findById(eventId)
        .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이벤트입니다."));

    // 2. 검증 통과 후 INSERT 수행
    EventParticipant participant = new EventParticipant(eventId, userId);
    eventParticipantRepository.save(participant);

    // 3. 참가자 수 업데이트
    event.increaseParticipants();
}

이렇게 하면 DB 레벨의 FK 제약조건이 없어도 애플리케이션에서 "존재하지 않는 event_id로 INSERT 하는 것"을 막을 수 있습니다. 다만 이 방식의 한계도 인지하고 계시면 좋은데, DB에 직접 쿼리를 날리는 경우(예: 운영팀이 직접 SQL로 데이터를 수정하는 경우)에는 애플리케이션 검증을 우회하게 되기 때문에 데이터 정합성이 깨질 수 있습니다. 그래서 실무에서는 DB 직접 조작 시 별도의 검증 절차를 두거나, 주기적으로 정합성 체크 배치를 돌리는 팀도 있습니다.

현업에서 FK를 안 쓰는 이유는 교재에서도 언급했듯이 S-Lock 비용 절감 외에도, 테이블 간 의존성이 줄어들어서 스키마 변경이나 데이터 마이그레이션이 훨씬 유연해지기 때문입니다. 대신 그 트레이드오프로 애플리케이션 코드에서 무결성 검증을 빠짐없이 해줘야 하는 책임이 생기는 거죠.

Q. 이미 운영 중인 테이블에서 FK 제거가 가능한지

가능합니다. ALTER TABLE 명령으로 기존 테이블에서 FK 제약조건을 제거할 수 있습니다.

-- 외래 키 제약조건 이름 확인
SHOW CREATE TABLE event_participant;

-- 외래 키 제거
ALTER TABLE event_participant DROP FOREIGN KEY fk_event_participant_event;

이미 데이터가 들어있는 상태에서도 FK를 제거하는 것 자체는 문제가 없습니다. FK 제약조건은 "앞으로의 INSERT/UPDATE를 검증하겠다"는 규칙일 뿐이고, 제거한다고 기존 데이터가 변하거나 삭제되지는 않습니다.

다만 운영 환경에서 ALTER TABLE을 실행할 때는 테이블 크기가 크면 락이 걸리면서 서비스에 영향을 줄 수 있기 때문에, 트래픽이 적은 시간대에 수행하거나 pt-online-schema-change 같은 온라인 DDL 도구를 사용하는 것이 일반적입니다. Percona의 pt-online-schema-change 관련 문서를 참고해보시면 도움이 될 것 같습니다: https://docs.percona.com/percona-toolkit/pt-online-schema-change.html

그래서 "이미 테이블에 데이터가 있으니 첫 번째 방법은 못 쓰고 두 번째 방법만 써야 한다"는 아닙니다. 두 방법 모두 기존 운영 환경에서 적용 가능합니다. 다만 상황에 따라 선택이 달라지는데, FK 제거는 좀 더 근본적인 해결이고(S-Lock 자체를 없앰), 쿼리 순서 변경은 FK를 유지하면서도 데드락만 회피하는 방법이라 변경 범위가 작습니다. 프로젝트 상황에 맞게 선택하시면 됩니다 좋은 질문 감사합니다!!

0

communityai8509

안녕하세요, 인프런 AI 인턴입니다. cho766님.

외래 키 제약 조건과 관련된 데드락 문제 해결에 대한 질문을 주셨네요. 이와 관련하여 두 가지 핵심 질문에 대해 답변드리겠습니다.

1. 외래키 제거 후 어플리케이션 레벨에서 데이터 무결성 관리

외래키를 제거한 후 어플리케이션 레벨에서 데이터의 무결성을 관리하는 방법은 다음과 같습니다:

  • 사전 조회(Check Before Insert):

    • 어떤 데이터를 삽입하기 전에, 해당 데이터가 유효한지 확인하기 위해 관련 테이블을 미리 조회합니다. 예를 들어, 특정 외래키에 연결된 데이터가 존재하는지를 확인합니다. 이를 위해 직접적으로 SQL 조회(findXXX())를 먼저 수행한 다음, 관련 데이터가 없는 경우 예외를 던져서 트랜잭션을 롤백시킵니다.
  • 애플리케이션 로직으로 무결성 확보:

    • 이렇게 확인된 상태에서만 데이터 삽입이 이루어지도록 하여 외래 키 무결성을 응용 프로그램이 보장합니다.
    • 특정 라이브러리나 ORM(Object-Relational Mapping)을 사용하는 경우, 이러한 무결성 보장을 위해 추가적인 비즈니스 로직을 작성할 수 있습니다.

실제 예시: 스프링 프레임워크에서는 서비스 계층에서 이러한 검증 로직을 추가하여 외래키로 인해 발생할 수 있는 무결성 문제를 예방할 수 있습니다.

2. 외래키 제거 후 기존 테이블에 적용 가능 여부 및 쿼리 순서 변경 대안

  • 이미 생성된 테이블에서도 외래키 제거 가능:

    • 기존 테이블에서도 외래키를 제거하는 것이 가능하긴 합니다. 하지만 이 경우에는 데이터의 무결성을 우리가 직접 관리해야 하므로 더 복잡한 어플리케이션 로직이 필요합니다.
    • 테이블이 이미 존재하고 충분한 데이터가 있는 상태에서 외래키를 제거하면, 새로운 데이터 삽입 시 잘못된 데이터가 입력될 가능성이 있으므로 더욱 철저한 검증 및 관리가 필요합니다.
  • 쿼리 순서 변경:

    • 외래키를 제거하지 않고도 데드락을 피하고 싶다면 트랜잭션 내에서 쿼리 순서를 조절하여 외래키 제약조건에 걸리지 않도록 할 수 있습니다.
    • 즉, 데이터의 일관성이 깨지지 않도록 관련된 테이블에 대해 적절한 순서로 INSERT, UPDATE, DELETE 쿼리를 수행하거나, 잠금을 적절히 활용하여 문제가 되는 시점에 트랜잭션이 충돌나지 않도록 하는 방법입니다.

외래키 관리에 대한 더 많은 정보와 실전 적용 사례는 아래 링크를 참고해 보세요:
- 외래키 제거 후 관리 사례

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

조회속도 개선에서 더 개선하는 방법이 궁금합니다.

0

28

2

Build 관련 문제 (테스트 관련 문제)

0

43

2

인덱스 관련 질문 있습니다.

0

68

2

비관적 락 구현 방식 문의 건

0

70

2

외부 api 처리 방안에 대하여 궁금한 점이 있습니다.

0

90

2

네임드 락 사용 시 커넥션 풀을 분리하는 방법에 대한 질문

0

83

2

이벤트) 백엔드 기술면접 실전문제집

0

102

2

로컬에서 테스트 한 결과를 이력서에 써도 괜찮을까요?

0

131

2

Redis 캐싱을 도입하는데 db조회와 성능이 차이가 거의 없습니다.

0

112

2

k6 부하테스트 중인데 개선 전 성능이 너무 안나와서 고민

0

131

2

강의와 성능수치 비교

0

103

2

13강 강의 뒷부분의 과제 안내부분은 어디있나요?

0

51

2

이벤트 참가자 수 증가 후, save 메서드 호출 코드 질문

0

66

2

[수업 자료 질문] Cache Aside의 특징 문의

0

86

2

[수업자료 문의] RedisTemplate으로 SETNX 시 리턴값 문의

0

81

2

멀티스레드 상황인데 currentParticipants 가 AtomicInteger가 아닌 이유?

0

88

3

클라우드 환경 배포시 부하 테스트 방식에 대하여

0

137

2

k6 dashboad 안나오는 상

0

113

2

2-4 도커 빌드 에러가 계속 납니다.

0

297

2

AWS EC2에 도커 컨테이너가 동작하지 않을 때 확인 해야하는 것

0

115

2

성능 측정시

0

111

2

API 별 실행 쿼리 모니터링 구현 질문 있습니다.

0

85

2

트랜잭션 격리성 설계도 어필포인트로 가져갈 수 있을까요?

1

69

2

실무 레거시코드에 낙관적 락, 비관적 락 적용 시도

0

104

2