작성
·
1.7K
·
수정됨
0
외래키 사용을 지양하라는 내용이 있어서 링크된 글을 읽어봤는데 궁금증이 있습니다.
외래키를 지양한다면 PK 값을 다른 테이블에 넣으면서 그 값으로 조인을 사용하는건가요?
외래키를 지양했을 때 성능상의 이점은 알겠는데 결국 데이터 정합성 부분에서 문제가 발생합니다. RDB에서 데이터 정합성이 깨지면 사용하는 의미가 없다고 하는데 이부분에선 어떻게 생각하시나요?
외래키를 안쓸경우 JPA에서 ManyToOne같은 메소드도 사용하지 않는건가요?
그리고 해당 주장에 대해 반박하는 아래의 링크도 있는데 이 의견은 어떠신가요?
https://gdsc-university-of-seoul.github.io/foreign-key/
답변 2
1
안녕하세요. 근래에 책을 집필할 기회가 생겨 그쪽에 힘을 실어주다 보니 다른 일에 신경 쓰지 못했습니다. 답변이 늦어 죄송합니다. 다만 해당 강의는 공식적으로 질의응답을 제공하지 않는 강의였다는 점을 이유로 늦어진 부분에 대해 양해 부탁드립니다.
우선 저는 MySQL 전문가는 아니기에 적확한 근거를 들어 질문자님을 설득할 자신이 없습니다. 그래서 노골적으로 이 이야기를 먼저 하겠습니다. 외래키 사용을 지양하라는 조언은 제가 여러 MySQL DBA 분들을 통해 들은 공통된 조언입니다. 그래서 찍먹 수준으로 공부해 본 저보다는 깊게 공부해 본 분들의 이야기이니 그분들의 말이 더 맞지 않을까 싶습니다. DBA 분들의 주장은 모두 하나같이 아래 두 의견이었습니다.
성능에 오히려 안 좋다.
DB 작업에 불편하다.
그리고 아래는 각 주장에 대한 저의 개인적인 의견입니다.
성능에 관해 저도 직접 벤치마크를 돌려본 것은 아니기에 외래키 사용으로 인해 성능 저하가 얼마나 있는지는 저도 수치적으로 잘 알지 못합니다. (write 속도 차이가 꽤 크다고 듣긴 했습니다.) 그래서 관심이 있다면 관련해서는 직접 찾아보심이 좋을 것 같습니다.
‘외래키를 사용하면 DB 작업에 불편하다’합니다. 이 의견이 무엇이었는지 좀 더 상세히 말하면, DBA 입장에선 간혹, 장애 상황같이 긴급한 상황에서 DDL이나 DML 작업을 바로 수행해야 할 수 있다 합니다. 그런데 그럴 때 외래키가 있으면 작업에 방해돼서 바로 조치할 수 있는 것도 시간이 두 배 세 배 걸릴 수 있다 했고요. 개인적으로 저는 이 말을 듣고 ‘그럴수도 있겠다.’ 라고 생각했고, ‘저렇게까지 말하는데 외래키 그냥 지우지 뭐.’하고 납득했습니다.
올려주신 링크의 글도 잘 읽었습니다. 그리고 읽으면서 저도 올려주신 글에 100% 동의했습니다. 특히 ‘속도에 민감한 서비스가 아니라면 데이터 품질을 보장받기 위해 외래키를 사용하는 것이 좋다.’라는 말은 맞는 말인 것 같습니다. 강의 내에서 외래키 사용을 지양하라고 말했지만, 애초에 외래키도 좋은 기능입니다. 좋지 않은 기능이었다면 진즉에 사라졌을 기능이었겠지요.
그래서 혹시 제가 강의를 너무 오버 엔지니어링을 지향하도록 유도한 것은 아닌가하고 생각이 들어 후회도 했습니다. 그래서 의견주셔서 감사합니다.
다만 그럼에도 불구하고 ‘외래키 사용을 지양하자’라는 제 의견에는 여전히 변함이 없습니다. 그건 아무래도 제가 일하고 있는 환경 때문인 것 같기도 한데요. (대규모 트래픽 + 엔터프라이즈) 이러니저러니 해도 외래키를 삭제했을 때 속도가 2~3%라도 더 나아질 수 있다면, 개발자가 조금이라도 수고를 더 하는 게 맞지 않을까 생각하기 때문입니다. 그래서 앞으로도 RDB를 사용한다 해도 외래키는 안 사용할 것 같네요.
+) 긴가민가한 반응이 심적으로 이해는 갑니다.😂 왜냐하면 저도 처음에 이런 조언을 들었을 때 똑같이 긴가민가했기 때문입니다.
저도 처음에 DBA 분을 통해 DDL 피드백을 받는데, 외래키를 지워달라는 요청을 보고 순간 벙쪘었습니다. 그래서 저도 머릿속으론 ‘이게 맞나….? 학부 시절에 배운 데이터베이스 이론 수업과는 너무 반대되는 일을 하는데?’ 같은 생각을 했습니다. 주변 DBA 지인분들 붙잡고 이래도 되는 건지 물어보고 다녔고요. 그런데 대부분 반응은 ‘네가 무조건 있어야 한다 생각하고, 서비스에 반드시 필요하다 생각하면 그래도 되긴 하는데, 앵간하면 하지 말아라’였습니다.
개인적으로 생각하기에 이러한 조언이 생기게 된 이유는 시대의 흐름이 변해서인 것 같습니다. RDB의 외래키 자체는 정말 훌륭한 기능인 것은 맞지만, 최근에 와서는 대용량 트래픽을 처리해야 하는 경우가 많습니다. 그래서 이로인해 조금이라도 속도를 개선해 보려고 만들어진 발버둥이지 않나 싶네요.
+) 외래키 없이도 조인이 가능합니다. 아래로 SQL로 https://sqlfiddle.com/mysql/online-compiler에서 테스트해 보길 바랍니다.
-- 사용자 테이블
CREATE TABLE Users (
UserID INT PRIMARY KEY,
UserName VARCHAR(50),
Email VARCHAR(100)
);
-- 주문 테이블
CREATE TABLE Orders (
OrderID INT PRIMARY KEY,
UserID INT,
ProductName VARCHAR(50),
OrderDate DATE
);
-- 데이터 삽입
INSERT INTO Users (UserID, UserName, Email)
VALUES (1, 'John Doe', 'john@example.com');
INSERT INTO Orders (OrderID, UserID, ProductName, OrderDate)
VALUES (101, 1, 'Product A', '2024-01-26');
SELECT Users.*, Users.Email, Orders.*
FROM Users, Orders
WHERE Users.UserID = Orders.UserID;
추가로 외래키와 조인 성능은 관계없습니다. ManyToOne도 적용 가능합니다.
+) 개인적으로 정합성은 애초에 당연히 지켜야 하는 부분이라 생각하기 때문에 애초에 논외입니다. 정합성은 정규화와 애플리케이션 레벨에서 추가 작업을 처리하도록 함으로써 잘 해결할 수 있습니다. 더불어 저는 RDB를 사용하는 목적이 데이터 정합성 때문이라 보지 않습니다. 저는 RDB를 사용하는 이유가 JOIN 때문이라 생각합니다. 물론 사람마다 다른 여러 이유가 있겠지만요!
답변이 도움됐길 바랍니다.
0
안녕하세요, 인프런 AI 인턴입니다.
seiyounng 님, 외래키를 지양하는 문제에 대해 질문 주셨네요. 이에 대한 답변은 다음과 같습니다.
외래키를 지양하는 경우에도 PK 값을 다른 테이블에 저장하여 조인을 사용하는 것은 가능합니다. 이 때, 조인은 명시적으로 수행되며 관계의 무결성을 유지하기 위한 추가적인 프로그램 로직이 필요할 수 있습니다.
외래키를 사용하지 않을 때의 성능 향상은 데이터베이스의 과도한 무결성 체크와 락 경합 감소에서 오는 장점일 수 있습니다. 하지만 말씀하신 것처럼 데이터의 정합성 문제는 중요한 이슈입니다. 이를 보완하려면 애플리케이션 레벨에서 무결성을 검증하는 로직을 구현하거나 다른 메커니즘을 사용해야 합니다.
외래키를 사용하지 않아도 JPA에서 ManyToOne 같은 매핑은 사용할 수 있습니다. 하지만 이 경우 JPA는 외래키 제약조건 없이 객체 간의 관계를 ORM으로 해석하여 처리합니다. 즉, JPA를 사용하여 관계를 맺되, 데이터베이스 레벨에서는 외래키 제약을 두지 않는 식으로 구현할 수 있습니다.
제공해주신 링크에 대해서는, 다양한 의견과 개발 상황에 따른 접근 방식이 존재할 수 있습니다. 외래키의 사용 여부는 애플리케이션의 요구사항, 성능, 유지보수성 등을 고려하여 결정해야 하며 상황에 따라 적합한 결정이 달라질 수 있습니다.
외래키 사용에 대한 더 자세한 내용이나 Spring Data JDBC와 관련된 추가적인 정보가 필요하시면 Spring Data JDBC 레퍼런스 문서를 참고하시면 도움이 될 것입니다.
프로그래밍에 대한 궁금증을 해결하는 데 도움이 되었길 바랍니다.