최대 절전 모드가 내 경력을 거의 망친 방법
게시 됨: 2022-03-11당신이 Java 개발자이고 다음 큰 프로젝트를 시작하려고 한다고 상상해 보십시오. 나머지 프로젝트에 적용할 기본적인 결정을 내려야 합니다. 일반 SQL을 처리하고 싶지 않기 때문에 유연한 데이터 모델의 최상의 객체 지향 추상화를 선택하려고 합니다. 모든 종류의 데이터를 지원하고 모든 종류의 데이터베이스를 지원하는 것이 이상적입니다.
명백한 대답은 Hibernate 를 사용하는 것입니다. 맞습니까? Java 개발자의 90%가 귀하의 의견에 동의하지만 그것이 올바른 결정입니까?
Hibernate가 허용된 표준이라는 이유로 맹목적으로 Hibernate 를 사용하면 무엇이 잘못될 수 있는지 살펴보자.
Java 개발자인 Monica를 생각해 보십시오. Monica는 최근에 건축가로 승진했으며 현재 회사에서 신제품에 대한 기술 스택 배치를 책임지고 있습니다. 그녀는 Java 세계에서 데이터베이스 통신을 처리하기 위한 좋은 도구가 단 하나라는 것을 알고 있습니다. 바로 Hibernate 입니다. Hibernate 는 잘 알려져 있고 지원되는 JPA 표준입니다. 그러나 항상 프로젝트를 시작하기 전에 몇 가지 사항을 확인하는 것이 좋습니다. 다행히도 그녀의 동료인 Ben은 올바른 사람을 알고 있습니다.
최대 절전 모드는 은색 총알처럼 들립니다.
벤 - 안녕하세요 모니카, 존을 소개하고 싶습니다. 그는 Hibernate 전문가이고 당신을 도울 것입니다.
모니카 - 존, 시간을 내서 기쁩니다. 그래서 우리는 차세대 빅 씽(Next Big Thing)을 구축하고 있습니다. 우리는 다음 Facebook 또는 Google이 될 계획입니다. 바쁜 날들. 그것은 거대할 것이다. 절대적으로 환상적입니다! 다들 너무 신났어요! 저는 건축가의 역할로 승격되었으므로 이제 사용할 스택을 선택해야 합니다. 유일하게 부족한 부분은 끈기입니다 ...
존 - 최대 절전 모드 !
모니카 - 네! 정확히! 내가 생각했던 바로 그! 그것은 우리에게 완벽한 경기이자 진정한 거래처럼 보입니다. 시장과 오랜 역사를 통해 입증된 진정한 엔터프라이즈 문제에 대한 진정한 엔터프라이즈 솔루션입니다. 긍정적인 경험을 많이 들었습니다. 그러나 팀원 중 한 명과 문제가 있습니다. 그는 완전히 반대합니다. 그는 데이터베이스에 대해 많이 알고 있으며 우리 애플리케이션과 데이터베이스 사이에 다른 계층을 추가하는 것을 두려워합니다. 그는 매우 똑똑하고, 이것이 좋은 결정임을 그에게 확신시키기 위해 몇 가지 정말 좋은 논거가 필요합니다. 도와줄 수 있니?
존 - 물론이죠! 나는 기쁠 것이다. 최대 절전 모드 는 실제로 뛰어난 도구입니다. 은행과 같은 크고 진정한 엔터프라이즈 솔루션에서 널리 사용됩니다. 당신은 그것에 잘못 갈 수 없습니다. 지속성을 생각하십시오. Hibernate 를 선택하십시오. Java로 작성하는 경우 이는 절대적으로 올바른 선택이며 다른 언어에 대한 포트도 있습니다. 얼마나 많은 직업 설명이 그것을 요구하는지 보십시오!
모니카 - 전적으로 동의합니다! 나는 그것에 대해 같은 감정을 가지고 있습니다. 이전 프로젝트에서 우리는 평범한 오래된 JDBC를 통해 대부분 SQL을 사용했습니다. 말도 안되는! 알아요! 그러나 여기 문제가 있습니다. 우리 팀에는 정말 똑똑한 SQL 직원이 있으며 Hibernate 에서 생성된 SQL을 보고 긴장했습니다. 보기 흉하고 읽을 수 없었습니다. 이것이 앞으로 문제가 될까요?
존 - 봐. DBA는 관점이 다릅니다. 그들은 프로젝트에서 그들의 역할을 대체하는 것처럼 보이기 때문에 Hibernate 를 두려워합니다. 또한 데이터베이스에는 쿼리 최적화 프로그램이 내장되어 있으므로 이러한 쿼리가 실제로 어떻게 보일지 걱정할 필요가 없습니다. 데이터베이스가 최적화합니다. 이것은 SQL이 할 수 없는 빠른 개발에 관한 것입니다.
모니카 - 정말?! 더 이상 SQL을 다루지 않습니까? 놀라운! 마지막으로 DBA가 일부 쿼리를 최적화하는 데 몇 주를 보냈습니다. 주! 아, 이렇게 말씀드리니 너무 부끄럽지만... 저장 프로시저를 사용하고 있다는 사실을 알고 계셨나요?(웃음). 아, 정말 엉망이었습니다. 프로젝트가 여전히 그것을 사용하고 있다는 것을 믿을 수 있습니까? 밖에 있는 사람들에게 너무 미안합니다. 그들은 여전히 이 지루한 코드를 계속해서 작성해야 합니다. 여전히 Java 또는 SQL 프로젝트인지 궁금합니다.
John - 이것이 바로 객체 지향 접근 방식과 관계형 접근 방식의 차이점입니다. 이른바 객체 지향 임피던스 불일치입니다. 최대 절전 모드 는 이 격차를 줄일 수 있습니다. 개발자는 비즈니스 로직 구축에 집중할 수 있습니다. 푸시 기능은 이해 관계자와 전체 경영진을 기쁘게 합니다. 가장 중요한 일을 하십시오: 비즈니스! 많은 상용구 코드가 사라지고 논리와 데이터 사이에 마술적이고 보이지 않지만 안정적인 연결이 생깁니다.
모니카 - 상호 협력. 완전한 시너지. 데이터베이스가 처음부터 언어의 일부였던 것처럼. 이 기술적인 도약의 리더가 되어서 너무 기쁩니다. 소프트웨어 트랙의 워프 속도와 같습니다.
존 - 그래! 당신은 그것을 얻었다!
모니카 - 맙소사, 너무 흥분돼! 고마워, 존! 준비됐어!
유연하지 않은 솔루션으로 인한 성장통
모니카 - 존, 작년에 이야기했던 프로젝트 기억나?
존 - 물론이죠. 어떻게되고 있습니까?
모니카 - 곧 제작에 들어갈 예정입니다. 모든 것이 정상이지만 몇 가지 질문이 나타납니다.
존 - 물론이죠. 때려주세요.
Monica - 더 이상 데이터베이스 스키마를 처음부터 생성할 수 없습니다. 데이터 손실 없이 스키마 변경을 지원하는 가장 좋은 방법은 무엇입니까?
John - 첫째, Hibernate 는 프로덕션 마이그레이션 도구로 사용하기 위한 것이 아닙니다. FlywayDB 또는 Liquibase와 같은 것을 사용하십시오. 아주 간단합니다. 마이그레이션 스크립트를 작성한 다음 Hibernate 매핑과 함께 엔티티 모델을 업데이트하여 실제 데이터베이스 구조와 동기화를 유지합니다.
모니카 - 흠, 알겠습니다. 이전 프로젝트에서는 일반 SQL 마이그레이션만 사용했습니다.
존 - 그것도 좋습니다. 엔터티 모델과 스키마를 동기화 상태로 유지하는 한 원하는 방식으로 수행하십시오.
모니카 - 알겠습니다. 또 다른 것이 있습니다. 우리는 항상 게으른/열심히 가져오는 문제로 어려움을 겪고 있습니다. 어느 순간 우리는 모든 것을 열심히 하기로 결정했지만 차선책처럼 보이고 때로는 세션이 없기 때문에 일부 필드에 액세스할 수 없거나 이와 유사한 경우가 있습니다. 정상인가요?
John - Hibernate 에 대해 더 많이 알아야 합니다. 데이터베이스에서 매핑하는 것은 간단하지 않습니다. 기본적으로 여러 가지 방법이 있습니다. 자신에게 맞는 방법을 선택하기만 하면 됩니다. 지연 가져오기를 사용하면 요청 시 해당 개체를 로드할 수 있지만 활성 세션 내에서 작업해야 합니다.
Monica - 우리는 여전히 최종 배포에 사용할 데이터베이스 엔진을 고민하고 있습니다. Hibernate 가 이식 가능하다고 생각했지만 일부 MS SQL 마법을 사용하는 몇 가지 기본 쿼리가 있으며 실제로 프로덕션에서 MySQL을 사용하고 싶습니다.
John - Hibernate 는 분리된 기준 또는 HQL을 사용하는 한 유연성을 제공합니다. 모든 기본 쿼리는 솔루션을 데이터베이스에 바인딩합니다.
Monica - 그러면 MS SQL을 고수해야 할 것 같습니다. 마지막 질문: 제 팀원이 HQL에 "limit" 키워드가 없다고 말했습니다. 나는 그가 농담하는 줄 알았는데, 나도 찾을 수 없었다. 어리석은 질문 죄송합니다...
John - 실제로 HQL에는 "limit" 키워드가 없습니다. 데이터베이스 공급업체에 따라 다르므로 쿼리 개체를 통해 이를 제어할 수 있습니다.
Monica - 다른 모든 요소가 HQL에 있다는 것이 이상해 보입니다. 신경 쓰지 마. 시간 내 줘서 고마워!
우리는 이제 SQL의 솔루션을 다시 해킹하고 있습니다.
Monica - John, 처음에는 SQL을 다루지 않을 예정이었지만 이제는 해야 하는 것 같습니다. 우리의 요구 사항은 증가하고 있으며 이를 우회할 방법이 없는 것 같습니다. 잘못된 것 같지만 우리는 매일 SQL을 다시 사용하기 시작했습니다.

존 - 글쎄, 그건 틀리지 않아. 처음부터 데이터베이스에 집중할 필요가 없었습니다. 하지만 프로젝트가 커질수록 SQL을 사용하고 성능 최적화 작업을 하는 것이 좋다.
모니카 - 때때로 우리는 오류를 찾는 데 며칠을 보냅니다. Hibernate 에서 생성된 SQL이 예상대로 작동하지 않고 예기치 않은 결과를 생성하는 이유를 모르기 때문에 분석해야 하는 것 같습니다. 우리는 Hibernate 버그 추적기에서 잘 알려진 몇 가지 문제에 부딪쳤다. 또한 엔터티 모델을 동기화된 상태로 유지하면서 적절한 마이그레이션을 작성하기가 어렵습니다. Hibernate 내부에 대해 많이 배우고 이것이 어떻게 작동할지 예측해야 하기 때문에 시간이 많이 걸립니다.
John - 항상 학습 곡선이 있습니다. 많이 쓸 필요는 없지만 어떻게 작동하는지 알아야 합니다.
Monica - 더 큰 데이터 세트로 작업하는 것도 짜증납니다. 최근에 데이터베이스에 대한 대규모 가져오기를 수행했는데 속도가 매우 느렸습니다. 그런 다음 세션을 더 빠르게 만들기 위해 세션을 지워야 한다는 것을 알게 되었습니다. 그럼에도 불구하고 여전히 훨씬 느리므로 일반 SQL 문으로 다시 작성하기로 결정했습니다. 재미있는 점은 일반 SQL을 작성하는 것이 실제로 가장 빠른 방법이었다는 것입니다. 그래서 우리는 이것을 마지막 옵션으로 하기로 결정했습니다.
John - 가져오기는 객체 지향 프로세스가 아닙니다. Hibernate 는 객체 지향 설계에 중점을 둡니다. 항상 기본 쿼리를 사용할 수 있음을 기억하십시오.
Monica - Hibernate 캐시가 어떻게 작동하는지 이해하는 데 도움을 줄 수 있습니까? 이해가 안가네요. 일부 1차/2차 수준 캐시가 있습니다. 이게 다 뭐야?
존 - 물론이죠. 영구 데이터의 소위 트랜잭션 수준 캐시입니다. 클래스별 및 컬렉션별 기반으로 클러스터 또는 JVM 수준 캐시를 구성할 수 있습니다. 클러스터된 캐시를 연결할 수도 있습니다. 그러나 캐시는 다른 애플리케이션이 영구 저장소에 변경한 사항을 인식하지 못한다는 점을 기억하십시오. 그러나 만료된 캐시 데이터를 정기적으로 삭제하도록 구성할 수 있습니다.
모니카 - 죄송합니다. 오늘 하루가 좋지 않은 것 같습니다. 이것을 조금 더 설명할 수 있습니까?
존 - 물론이죠. save
, update
, saveOrUpdate
에 객체를 전달하거나 load
, get
, list
, iterate
또는 scroll
을 통해 객체를 검색할 때마다 해당 객체가 세션의 내부 캐시에 추가됩니다. 첫 번째 수준 캐시에서 개체와 해당 컬렉션을 제거할 수도 있습니다.
모니카 - 어…
John - 또한 캐시 모드를 제어할 수 있습니다. normal
모드를 사용하여 항목을 읽고 두 번째 수준 캐시에 쓸 수 있습니다. get
모드를 사용하여 두 번째 수준에서 읽지만 다시 쓸 수는 없습니다. get
과 동일하지만 두 번째 수준에서 읽을 수 없는 put
을 사용합니다. 두 번째 수준에 쓰지만 읽지 않고 use minimal puts
속성을 우회하여 데이터베이스에서 읽은 모든 항목에 대해 두 번째 수준 캐시를 강제로 새로 고치는 refresh
모드를 사용할 수도 있습니다.
모니카 - 알겠습니다. 확인. 이것에 대해 생각해 보겠습니다. 아 늦었네 가봐야겠다 시간 내 줘서 고마워!
존 - 천만에요!
최대 절전 모드 포기
Monica - John, 나는 우리가 소프트웨어 개발의 새로운 시대에 진입하고 있다고 생각했습니다. 나는 우리가 광년 점프를 하고 있다고 생각했다. 그러나 4년이 지난 지금 우리는 여전히 같은 문제를 다른 각도에서 다루고 있는 것 같습니다. 나는 Hibernate 아키텍처, 구성, 로깅, 명명 전략, 튜플라이저, 엔티티 이름 확인자, 향상된 식별자 생성기, 식별자 생성기 최적화, 공용체-서브클래스, XDoclet 마크업, 인덱싱된 컬렉션과의 양방향 연결, 삼항 연결, idbag, 암시적 다형성을 기타 상속 매핑, 두 개의 서로 다른 데이터 저장소 간 복제 개체, 분리된 개체 및 자동 버전 관리, 연결 해제 모드, 상태 비저장 세션 인터페이스, 컬렉션 지속성 분류, 캐시 수준, 지연 또는 열망 가져오기 등. 내가 아는 모든 것에도 불구하고 우리는 심하게 실패한 것 같습니다. 소프트웨어 실패입니다! 대실패! 재해! 아마겟돈!
존 - 잠깐! 무슨 일이에요?
모니카 - 막다른 골목에 도달했습니다. 애플리케이션 성능이 엄청나게 느립니다! 보고서를 받으려면 이틀을 기다려야 합니다! 실제로 고객을 위한 대시보드를 생성하는 데 이틀이 걸립니다. 이는 매일 계산 꼬리를 늘려야 하는 반면 대시보드는 점점 더 구식입니다. 우리 DBA 전문가는 일부 쿼리를 최적화하기 위해 2개월 동안 작업했지만 데이터베이스 구조는 완전히 엉망입니다. 그를 지원하는 개발자가 있지만 문제는 DBA가 SQL로 생각하고 개발자가 이것을 분리된 기준 또는 HQL 형식으로 변환하는 데 며칠을 보내고 있다는 것입니다. 현재로서는 성능이 중요하기 때문에 네이티브 SQL을 최대한 사용하려고 합니다. 어쨌든 데이터베이스 스키마가 잘못된 것 같기 때문에 우리는 많은 것을 할 수 없습니다. 객체지향 입장에서는 옳게 느껴지지만 관계적 입장에서는 우스꽝스러워 보인다. 나 자신에게 묻고 있습니다. 어떻게 이런 일이 일어났습니까? 개발자들은 엔티티 구조를 변경하는 것이 엄청난 노력이 될 것이라고 말하므로 우리는 그럴 여유가 없습니다. 나는 이전 프로젝트에서 엉망이었음을 기억하지만 우리는 그런 중요한 지점에서 끝내지 못했습니다. 데이터 작업을 위해 완전히 다른 애플리케이션을 작성할 수 있었습니다. 이제 엔터티 모델이 항상 올바르게 작동하는지 확인하기가 정말 어렵기 때문에 생성된 테이블을 수정하는 것은 위험합니다. 그리고 이것은 최악의 부분도 아닙니다! 성능을 높이려면 데이터베이스 문제뿐만 아니라 데이터베이스와 애플리케이션 사이의 전체 계층 문제도 해결해야 합니다. 압도적이다! 우리에게는 컨설턴트가 있습니다. 그들은 데이터를 추출하여 다른 저장소에 넣은 다음 외부에서 계산을 수행하려고 합니다. 시간이 너무 많이 걸립니다!
존 - 무슨 말을 해야 할지 모르겠어.
모니카 - 존이 보입니다. 당신을 비난하고 싶지 않습니다. 나는 이 모든 문제를 해결하기 위해 Hibernate 를 선택했지만 지금은 그것이 은총알이 아니라는 것을 배웠습니다. 피해를 입었고 되돌릴 수 없습니다. 사실, 한 가지 묻고 싶은 것이 있습니다. 저는 지난 4년 동안 Hibernate 를 다루면서 보냈습니다. 현재 회사에 미래가 없는 것 같습니다. 도와주세요?
그래서 배운 교훈은 무엇입니까?
존 - 피터, 모니카를 소개할게.
피터 - 이봐, 모니카! 우리는 당신이 알고 있는 새로운 차세대 제품을 만들고 있습니다. 엄청날거야! 우리는 Uber처럼 되고 싶습니다! 얼마나 끈기가 있는지 아십니까...
모니카 - 최대 절전 모드 가 아닙니다!
마무리
Monica는 최대 절전 모드 전문가입니다. 그러나 이 경우 Hibernate 는 잘못된 결정이었습니다. 그녀가 자신의 솔루션이 원래보다 더 큰 문제로 바뀌었다는 것을 발견한 순간, 그것은 전체 프로젝트에 가장 큰 위협이었습니다.
데이터는 애플리케이션의 중심 목적이며 좋든 싫든 전체 아키텍처에 영향을 미칩니다. 우리가 이야기에서 배웠듯이, 당신의 자바 애플리케이션이 데이터베이스를 사용하고 있다는 이유로 또는 사회적 증거 때문에 Hibernate 를 사용하지 마십시오 . 유연성을 수용하는 솔루션을 선택하십시오. JdbcTemplate 또는 Fluent JDBC Wrapper와 같은 강력한 JDBC 래퍼에 대한 많은 옵션이 있습니다. 또는 jOOQ와 같은 다른 강력한 솔루션이 있습니다.