당니의 개발자 스토리
데이터베이스 스키마 자동 생성 본문
데이터베이스 스키마 자동 생성
자 그 다음에 갑자기 데이터베이스 스키마 자동 생성이 갑자기 나왔어요.

이걸 왜 먼저 설명 드리냐면, 사실 'id, name 같은 컬럼은 어떻게 매핑 해요?' 이걸 먼저 설명 드려야 되는데, 이거 하기 전에 지금 하려는 걸 먼저 설명 드려야 좀 편한게 있어서 먼저 설명드리겠습니다.

jpa가 사실 이 매핑 정보만 보면, 어떤 쿼리를 만들어야 될지, 어떤 테이블 인지 다 알 수 있잖아요. 그래서 jpa 에서는 뭘 지원하냐면 아예 애플리케이션 로딩 시점에 db 테이블을 생성하는 기능도 지원을 해줍니다.
물론 이런건 운영에서 쓰시면 안되구요. 내가 개발 단계나, 로컬 pc에서 개발하거나 이럴 때 좀 도움이 됩니다.

그래서 이 애플리케이션 실행 시점에 insert into 같은 테이블이 생성이 되게 해주고요. 이 기능을 사용하면 어떻게 되는지 설명드리겠습니다.

그래서 애플리케이션 로딩 시점에 create 문으로 DB를 일단 생성을 하고, 시작하게 할 수 있어요. 이렇게 하면 장점이 보통 우리가 개발할 때 테이블을 먼저 만들어 놓고 그 다음에 객체로 돌아가서 개발하잖아요. 근데 JPA는 그럴 필요가 없어요.
그냥 객체에서 할 거 해놓고 객체 매핑을 해놓으면 애플리케이션 뜰 때 필요하면 테이블을 다 만들어줍니다.
그리고 이게 중요한 건데요. 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL을 생성해줍니다.
DDL(Data Definition Language)은 데이터베이스 스키마를 정의하는 일련의 SQL 명령입니다. 단순히 데이터베이스 스키마에 대한 설명을 다루고 데이터베이스 개체의 구조를 만들고 수정하는 데 사용됩니다.


예를 들어서 가변 문자 같은 경우에 Oracle은 varchar2, MySQL은 varchar 이런 걸 쓰는데요. 이런 DDL이 생성될 때, 보시면

저번에 말씀드렸던 이 방언을 뭘로 생성했냐에 따라서 DDL문 자체를 적절하게 다 생성을 해줍니다.

그리고 이렇게 생성된 DDL은 꼭 개발에서만 쓰셔야 됩니다. 운영에서 쓰면 큰일 나겠죠. 이렇게 생성된 DDL을 또 볼 수 있어요. 좀 이따 보여드릴 텐데, 이거를 운영 서버에서는 사용하지 말고요. 이 생성된 DDL이 약간 불안할 수 있어요. 그래서 필요한 경우에는 좀 적절히 다듬은 후에 사용하시는 걸 권장드립니다. 이거는 운영 서버에 적용할 때구요. 좀 이따 보여드릴 텐데 딱 바로 dba에 넘기거나 내가 직접 운영에서 적용하기에는 조금은 다듬어야 돼요.

자 그리고 이 hibernate.hbm2ddl.auto 라는 옵션이 있는데요. 여기를 가보시면,

제가 주석으로 넣어놓은 걸 풀게요. hibernate.hbm2ddl.auto가 있고요. 이거를 create 라고 만들어 두시면 어떤 일이 벌어지는지 해보겠습니다.
한번 돌려볼게요.

실행을 하면 제일 먼저 drop table Member if exist, 그러니까 'member라는 테이블이 있으면 먼저 지워'

그리고 나서 create table 합니다. 그리고 이제 그 다음 로직이 돌죠.

애플리케이션 로딩 시점에 이 @Entity로 엔티티가 매핑된 애들은 JPA가 보고 테이블을 다 만들어 냅니다. 기존에 있던 테이블을 먼저 지우고요.
자 그래서 db에 가보면,

이 member가 있는데 데이터가 이제 없죠. 자 그럼 예를 들어서 하나 더 만들어 보죠.

private int age 라고 해볼게요. 실행을 해보면,

drop Table 해서 member를 지운 다음에 바로 Create Table 하면서 이 Age, 방금 제가 추가한 게 들어가 있죠? 새로운 테이블을 만듭니다.

그래서 db에 다시 가보셔서 다시 실행을 해보면, Id, Age, Name. Age가 추가가 되어있죠?
원래 보통 같은 경우에는 어떻게 개발을 해야 됩니까?

이걸 추가하고

또 여기 가서 Create Table 하거나 Alter로 해서 컬럼 추가하거나 해야죠. 그런데 이제 그런 거 있잖아요. 아 db에 가서 직접 create 문 치거나 alter 치고 와가지고, 또 여기서 뭐 하고 막 왔다 갔다 해야 되는데, 내 PC에서 빨리빨리 개발을 할 때는 사실 이게 막 계속 변화하는데 그럴 때는 되게 메리트가 있죠. 내가 db에 가서 직접 칠 필요 없이,

그냥 여기 안에서 하면 되니까요.
자 옵션을 간단하게 설명을 드리면,

create는 기존 테이블을 삭제한 후에 다시 생성합니다. drop 시키고 create합니다.
또 create-drop이라는 옵션이 있어요. 이거는 create랑 똑같은데 종료하는 시점에 테이블을 drop해버립니다.

자 먼저 create-drop해 볼게요. 실행해보면

drop, create하고 실행이 다 된 다음에,

애플리케이션 종료 시점에서 테이블을 drop해 버립니다.

db에 보시면 여기 위에 refresh 거든요. 이거를 눌러보면,

MEMBER가 없어졌죠. Select * From Member 하면,

없죠. 이런 create-drop 옵션은 사실 테스트 케이스 같은 걸 실행시킬 때, 마지막에 깔끔하게 다 날리고 싶을 때 보통 쓰는 거고요.

그 다음에 update가 있습니다. update가 이제 재밌는데 update는 변경분만 반영해 줍니다.
한번 해볼게요.

update 해놓고, 최초에는 id, name만 놔두고 실행해보겠습니다.

그러면 보시면 create table 해서 만들었죠. 그런데 제가 여기에서

age 라는 컬럼을 하나 추가하고 싶은데, 그러니까 이 필드를 하나 추가하고 싶은데 drop table을 하고 싶지는 않은 거예요. 그냥 alter table을 하고 싶어요.

그러면은 update 모드로 두시면 됩니다. 실행해 보겠습니다.

보시면 우리가 기대했던 대로 alter table에서 add Column Age 라고 들어가죠.

여기서 보면 age가 add Column으로 추가가 되어 있습니다.

그럼 age를 지우면 어떻게 될까요? 지우는 건 안됩니다. alter 쿼리가 나간다거나 하는 등의 아무 일도 일어나지 않죠? 그러니까 추가하는 것만 되는 겁니다. 왜냐하면 지우는 거는 잘못하다가 실수라도 진짜 table column이 날아가면 큰일나겠죠.

자 그 다음 validate는 뭐냐면 이 엔티티와 테이블이 정상 매핑 되었는지 확인해 줍니다.

예를 들어서 여기서 제가 새로운 컬럼을 하나 추가했습니다.

validate로 바꿔주고 실행을 하면,

그러면 에러가 나야 되겠죠. 지금 보시면 schema인 gogo2 라는 컬럼이 없다고 오류가 납니다.

그래서 엔티티와 테이블이 정상 매핑 되었는지 확인할 때 쓰는 겁니다.
그 다음에 이제 none 이라는 것은 '아 나 이 기능 싫어' 하면

이렇게 기능 자체를 주석처리 하셔도 되구요.

아니면 이거를 none 이라고 적으시면 됩니다. 사실 이 none 이라는 것은 없어요.

그냥 이렇게 아무거나 적는거랑 똑같은 거에요. 근데 이제 관례상 none 이라고 씁니다. 그러니까 아무것도 매칭 되는게 없으니까 실행이 안 되는 거죠.

그러면 이것을 쓸 때 조심해야 될 게 데이터베이스 방언 별로 달라지는 것을 확인해 드릴께요.

예를 들어서 제가 일단 create 라고 두고요. 방언을 Oracle로 바꿨어요. 그럼 오라클은 가변 문자 자체가 기본이 VARCHAR2이기 때문에 VARCHAR2로 생성이 되어야 됩니다.
실행해 보겠습니다.

create를 할 때 보시면 varchar2 라고 되어있죠. 방언에 따라서 이것들을 그 데이터베이스에 맞게 적절하게 해석을 해서 실행을 해줍니다.

다시 돌려 놓을게요.

이제 주의점을 보시면 이게 저도 참 여러가지 경험을 했는데, 운영장비에는 절대로 create나 create-drop이나 update를 사용하시면 안 돼요. 그럼 큰일 납니다. 제가 지금까지 큰 사고를 본 적이 있는데요. 일단 개발 초기 단계는 Create 또는 Update로 해서 그냥 자기 로컬과 개발 서버에서 쓰시면 돼요.
그러니까 개발 초기에는 테스트 서버에다가 create와 update를 해서 쓰면 되는데, 이제 어느정도 개발이 진행되고 나면, update 또는 validate를 쓰시면 되구요.
여기서 말하는 테스트 서버라는 것은 이제 개발 서버나 여러 명의 개발자가 함께 사용하는 어떤 중간 서버죠. 여기에다가는 create를 쓰시면 안돼요. 그러면은 테스트 해놨던 데이터가 다 날라가거든요. A라는 개발자가 테스트 서버에서 테스트를 했는데 B라는 개발자가 테스트를 실행할 때마다 막 drop으로 데이터를 날리고 다시 create로 생성하면, 데이터가 다 날라가니까 문제가 되겠죠. 그래서 이제 개발이나 이런 테스트 서버는 update나 validate 정도를 권장합니다.
그리고 스테이징과 운영 서버 같은 경우에는 update나 none.
제가 요즘 개발하면 할수록 많이 느끼는게 사실 테스트 서버, 개발 서버도 가급적이면 update를 쓰지 마세요. 특히 운영 서버에서는 더욱 쓰지 마시고, 개발 서버랑 스테이징 서버 정도는 validate 정도까지는 괜찮은 것 같긴 해요. 왜 쓰지 말라고 하냐면 개발 서버 같은게 update를 하면 편하기야 하겠죠. 자동으로 alter column 해주니까. 그런데 결국 운영 같은 경우에는 뭐 데이터 같은 게 몇 천만 건 있는 상태에서 alter를 잘못 치거나 하면 시스템이 중단 상태가 될 수도 있거든요. 잘 알고 치면 괜찮긴 한데, 이걸 애플리케이션 로딩 시점에 시스템이 자동으로 alter를 쳐준다는 게 굉장히 위험해요. 예를 들어서 5분 정도 시스템이 멈춰도 완전 대장애가 나는 거잖아요.
DDL에서의 Alter 문

그래서 가급적이면 그냥 내가 직접 만든 스크립트를 db 테스트 서버에서 그 스크립트가 잘 동작하는지 반영을 해봐야 돼요.
그래서 테스트 서버나 개발 서버에도 제가 권장드리는 건 그냥 본인이 직접 적용하시는 것, 직접 스크립트를 짜서 적용해보고 문제가 없으면 운영 서버에도 그걸 DBA 분한테 전달을 하든 해서 검수를 받고 그걸 적용하는 것을 권장드립니다. 결론은 자기 로컬 PC에서만 자유롭게 하시고 여러명이 쓰는 개발 서버나 스테이징이나 운영 서버에는 가급적이면 쓰지 않는다를 권장드립니다.
근데 이제 그건 있어요. 어쨌든 보시면,

여기서 스크립트를 만들어 주잖아요. 그러면은 저같은 경우에 주로 어떤 식으로 하냐면 운영 서버에 반영할 때도 이 스크립트를 가급적이면 여기서 좀 다듬어 가지고 넘깁니다. 막 직접 치는거 너무 귀찮으니까 그래도 이걸 다 일일이 꼼꼼히 따져보고 이제 좀 필요한 것들을 회사 룰에 맞춰서 바꾸고서 이렇게 넘기는 식으로 합니다.

암튼 결론은 운영 장비에는 절대 create, create-drop, update 같은 걸 쓰시면 안 된다는 겁니다.
update도 잘못되면 alter column이 나가거든요. 그럼 그 순간 데이터베이스 테이블에 락이 걸려요. 락이 걸려서 몇 분 동안 서비스가 중단된 것도 본 적이 있어요. 사실 아실 분들 다 아시겠지만 제일 중요한 것은 결국 이런 웹 어플리케이션 계정은 alter나 drop을 못하도록 근본적으로 계정 자체를 분리하는 게 맞죠. 아무튼 운영장비에는 절대 이걸 사용하면 안 된다 라는 것을 꼭 말씀드리고 싶었습니다.
자 그 다음에 이제 ddl 생성 기능에 대해서 설명 드릴게요.

여기에 보면 jpa에서 좀 재밌는 기능인데

@Column 이라는 걸 적을 수가 있거든요. 그래서 뭐 내가 이름을 원하는 걸로 해서

이런 식으로 바꿀 수 있어요. '데이터베이스 컬럼 명은 USERNAME이야' 라고 매핑 해! 라고 해서 바꾸고 할 수 있거든요. 그런데 이것보다는 이런게 또 있어요.

'이게 unique야? true, 그 다음에 얘가 length가 10짜리야' 이런 거를 줄 수가 있어요.
@Column 에서의 unique 제약 조건

이렇게 하고 한번 실행해 볼게요.

잘 보시면 varchar(10) 들어가고, alter table 해가지고 unique 제약 조건이 하나 생긴거 보이시죠.
이 unique 제약 조건 같은 경우에는 생각해보시면, 이 제약 조건이 애플리케이션에 영향을 주지는 않아요. 데이터베이스에 영향을 주는 거거든요. 그러니까 JPA의 어떤 실행 메커니즘 자체에 영향을 주는 게 아니에요. 그냥 alter table 이라는 스크립트가 이렇게 생성되는 거에 차이만 있을 뿐이에요.
JPA가 실행될 때 이 @Column(unique = true, length = 10) 어노테이션을 보고 런타임이 막 바뀌지 않아요. 그냥 alter table DDL 생성해주는 것만 딱 도와주는 거예요.

이런 거를 DDL 생성 기능이라고 합니다.
예를 들어서 전에 말씀드린 @Table 해가지고 테이블 명을 바꾸는 건 insert 쿼리나 update 쿼리가 새로 나가니까, 런타임에 영향을 주잖아요. 그런데 이런 unique 제약 조건을 넣거나 하는 것들은 실행 자체에 영향을 주지 않고, 단순하게 ddl을 생성하는 데만 영향을 줍니다.

그래서 이런 것을 ddl 생성 기능이라고 하고요. ddl 생성 기능은 ddl을 자동 생성할 때만 사용되고 jpa의 실행 로직에는 영향을 주지 않습니다.

length 같은 경우도 사실 ddl 생성 기능인데 이런 것을 약간 validation 하는 경우도 있더라고요.
아무튼 자 넘어가고요.

그러면 다음 시간에는 필드와 컬럼 매핑에 대해서 알아보겠습니다.
'스프링 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
| 실전 예제 1 - 요구사항 분석과 기본 매핑 (0) | 2024.06.08 |
|---|---|
| 기본 키 매핑 (0) | 2024.06.08 |
| 객체와 테이블 매핑 (0) | 2024.05.27 |
| 정리 (0) | 2024.05.26 |
| 준영속 상태 (0) | 2024.05.26 |