aws에
cs-stu1
stu1/로그인해서
1: 우분투
2: 인스턴스 유형 선택 t4g
3:
4: 8G 그대로
5: Name, honux-db
6: 보안그룹 구성: 새 보안그룹 honux-db-sg
기본 SSH/22/000.0. 아래에
MysQl/quror 3306 위치무관 / 소스: 000/0 전세계 어디서나 /
만약 3306 아래에 안열어주면 db접속이 안되므로 꼭 열어줘야한다.
db는 3306 포트로 접속을한다.
소스 000.0 지정해주면 중국애들이 들어온다.
ssh 등은 웹서버 용도가 처음부터 모두 열어줄 것을 염두에 뒀기 때문에 보안이 강력한데, mysql은 000.0은 하면 안좋다. 처음부터 db를 세상에 오픈할것으로 가정하지 않았다. db는 웹서버만 접근할수있는 것이 정상적이고, dba만 접근할수있다. ssh로 한번 거쳐서 접근하거나 bastion 접속서버를 거쳐 들어가야지 다이렉트로는 절대 db 열어주지 않는다. 우리는 공부용이니까 쉽게하려고 mysql 000/0으로 소스 설정하자.
7: 키페어 선택
실행 후
cd temp-keys와 같이 찾아간다. (C: 와 같이?) (cd ~Downloads/)
public ip 주소 복붙해서 ssh -i honux-0315.pem ubuntu@public ip
chmod 400 honux-0315.pem
(pem파일은 비번 파일)
sudo apt update
sudo apt upgrade
~~ Lucas 따라가기
한글설정은 편하려고 하는 것이고 안해도 된다.
locale이란? 프로그램이 글로벌을 서포트하는 프로그램일 때,
로케일은 사용자의 언어/국가뿐만 아니라 사용자 인터페이스에서 사용자가 선호하는 사항을 지정한 매개변수의 모임이다.
나라마다 다른 것은 언어, 시간, 화폐, 날짜 표기법, 썸머타임 적용, 등을 세팅해두는 것을 로케일이라고 한다.
예전에는 로케일을 한국으로 설정하고 시간을 한국시간으로 세팅했었는데, 요새는 로케일을 한국으로 설정하고 시간은 utc를 그대로 사용한다. utc는 그리니치 천문대 기준?이라고 한다. utc를 사용하는 것의 장단점은? 로컬타임으로 변환을 계속해줘야하는 단점. 국제적으로 갔을 때 편하다는 장점.(타국 출시할만큼 성공하는 경우에) 그런데 국내용으로 출시된 것은 한국시간 기준으로 써도 되는데, 만약 해외 출시되면 바꾸는 것 아주 고생하기때문에 처음부터 utc로 많이 한다.
sudo locale-gen
로그아웃했다가 재로그인해서 시간 바뀐것 확인하고 나서!
sudo apt install mysql-server
sudo mysql -u root
하면 비번 없이 접근할수있따. 루트 사용자는 비번없이 바로 접근이 가능하다. 항상 이런것은 아니고 sudo를 넣으면 비번없이 루트패스워드 안넣어도 접근가능하다. mysql이 소켓으로 접근시 없어도 된다고
ssh와 마찬가지로 비번 없는 것이 더 가능하다.
sudo란 명령은 이 리눅스의 관리 사용자, 리눅스의 루트가 되는 것이다. (누군지는 whoami로 확인가능) 맥북은 Users아래 사용자 있고, 리눅스는 sudo의 루트가 된다.
db 사용자 루트(mysql -u root)은 그냥 sql 사용자 루트와 다르다. (???)
sudo mysql_secure_installation
루트패스워드없이(sudo) 함.
다시 sudo mysql -u root하면 mysql접속됨.
DB자체도 utf세팅해주기
mysql> status 입력시 확인 가능. 옛날엔
디폴트패키지에 8.0이 들어갔단 뜻은 실무에사용해도된다는 뜻이다.
utf8mb4면 이모지도 넣을수있다.
콜레이션: 학습키워드. db는 캐릭터셋뿐만 아니라 collation도 중요하다.
mysql> create user scott@'' identified by 'tiger';
()어디서나 사용할수잇는 scott이란 사용자이다. ro
db는 자기기술성이있어서 자신의 정보가 자기에 저장된다.
myszl>use mysql
안에 user이란 db가 있는데 사용자 정보가 여기 들어간다.
select User,Host from user
다른사용자는 host가 로컬호스트로 되어ㅣ있는데 scott만 에서 사용가능하다. 로컬호스트로저장되어있는 디비는(root) 루트는 외부 곳에서 접근할수없다.
mysql> create database tigerdb;
타이거디비란 이름으로 db 생성
grant all on tigerdb. to 'scott'@'' with grant option;
타이거 디비에 대한 모든 권한을 스콧에게 부여해준다.
mysql> Bye로 종료
우분투로 돌아와서
mysql -u scott -p
scott에 localhost를 추가해줬다. 외부접속유저랑 로컬유저를 따로 만들어야 접속이 된다.
mysql> show databases
use tigerdb
즉시응답이 오는 것은 포트 3306이 열려있을 때
즉시응답이 안오는 것은 포트가 안열려있을 때이다.
-보안그룹 honux-db 인바운드 규칙에 두번쨰 것을 지운다.
그러고 다시 접속을 하면 testing connection하며 응답이 없다. 포트가 막혀있으니까 그렇다. (테스트용으로 보여준 것이고 다시 mysql 3306 000/0 인바운드 규칙 추가해준다.)
db를 외부 접속이 디폴트로 막혀있다. bind설정이란 것으로 외부 접속자 허용해야한다.
루트로 가서 sudo -i
grep -r bind ./ 하고 검색하면 어떤 파일에 bind가 있는지 알려준다. 주소를 바인딩해서 외부 접속 안하겠다고 막는 것이다. 이것을 편집한다.
bind-address = 127.0.01되어있는 것을 주석처리해준다.
설정 바꾸면 서버 재시작해야한다. 통째로 재시작하기 싫으니
sudo service mysql restart
sudo service mysql status로 확인하기....
안돼서..
bind-address 127001 주석처리했던 것 주석해제하고
주석으로 bind-address =* 추가해준다.
결국 해결안돼서 도커로...
mysql 5.7 쓰기어렵고 서버에 깔아야하는데 다운그레이드해서 5.7해서 쓰는것도 좋다. 8.0쓰는 것 어렵다.
헬로월드 해결되고 나면 많이 어려운 것은 없다.
aws에 mysql을 셋팅했다고 치고, 이거랑 로컬 db중어느 것을 쓰는 것이 좋을까?
두개를 명확히 분리해서 개발할떄는 항상 로컬을 사용하고 배포할떄는 항상 서버를써야한다. 돈이 많음ㄴ aws에 db가 두대있으면 좋을것이다. 로컬은 로컬개발에 쓰고, 개발용 db, 테스트용 db, 실서버용 이 따로 있는 것이 좋다.
jpa를 사용하는 장점이 db가 없어도 개발할수있다는 ㄱ서이 스프링 db의 장점이다. 그렇다면 개발할때는 h2를 쓰는 것이 좋을까 mysql쓰는 것이 좋을까? mysql이다. 나중에 mysql 올렸을때 안되는 호환성 문제가 있을까봐 처음부터 mysql로 하는 것이다. 지금 h2쓰는 것은 교육용이다. 다음엔 로컬과 서버 모두 mysql로 하는게 삽질을 줄여줄수있다.
dba들이 rds를 싫어하는 이유는 섬세한 튜닝이 불가능하기 떄문이다.
도커에 mysql깔고 실행하기
안되는 db를 접속하는 제3의 방법:
탭을 tcp/ip에서 ssh로 넘어간다.
ssh로 한번 접속후 로컬로 접속하는 방법이다.
이것을 ssh터널링이라고 한다. 이것은 jdbc 테스트를 할수가 없다.
db 켜는 법
ssh -i ~~
JDBC
drop table하는것은 이미 테이블 있으면 삭제하는 것인데, 실제로 하면 절대 안되고 ㅏㄲㄹ끔하게 학습하기위한 것이다.
gradle 빌드에 의존성 추가하고 새로고침
테스트 클래스 추가
@Test @DisplayName
@Connection conn;(java.sql.Connection import한다.)
1)드라이버로딩 테스트
@BeforeEach
2)커넥션 생성 테스트
String url = "jdbc:mysql://honux-mysql/honuxdb";
String password = "tiger";
conn = DriverManager.getConnection(url,user,password);
assertThat(conn).isNotNull();
//Class.forName("com.mysql.jdbc.Driver"):
Driver은 인터페이스인데 구현체가 없어서 실행 못한다고 에러났었다. 그렇지만 지금은 "come.mysql.jdbc~Driver" deprecated되었다.
String query = "SELECT UID, NAME, START_DATE FROM USER";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while(rs.next()){
rs.getInt(1);
rs.getString(2);
rs.getDate(3);
//각 column에 들어간 값이 UID, NAME, START_DATE이기 때문에 1,2,3번째 get할 때 Int,String,Date를 get하도록했다.
ColumnLabel을 "UID"로 직접 쓸 수도, 1로 인덱스 쓸수도 있다. 전자처럼하는 것이 좋다. rs.getString("NAME");와 같이.
}
ResultSet인터페이스의 next() 메서드는 불리언이다. next갔는데 읽을거있을때 true, 마지막거 읽고 다음에 없으니까 false리턴한다.
rs는 센티넬이다.
맨 윗줄은 column들 있으니까 rs.next를 해줘야 첫번째 레코드에 도달한다. 만약 column만 있고 레코드 없으면 rs.next가 false가 되고, 있으면 rs.next가 true되며 다음 레코드인 1번 레코드를 가리키게 된다.
String getNameFromUser(int uid) throws SQLEXCEPTION{
String query = "SELECT NAME FROM USER WHERE UID="+uid;
Statement stmt = conn.createStatement();
ResutlSet rs = stmt.executeQUery(query);
-> 이렇게 하면 안된다. sql injection의 공격대상이 된다.
해킹해서 uid대신 다른 것을 넣을수도있다.
그렇다면 어떻게 해야할까?
//PreparedStatement: 우리가 이걸 쓸일은 없다.
int getIDFromUser(String name) throws SQLEXCEPTION{
String query = "SELECT UID FROM USER WHERE UID=?";
var pstmt : PreparedStatement = conn.prepareStatement(query);
pstmt.setString(1,query);
ResultSet rs = pstmt.executeQuery();
if(!rs.next()) return -1; (최악 코드)
return rs.getInt("UID");
아까는 statement를 만들고 나서 쿼리를 실행시켯는데, prepareparedstatement 를 사용하면sql
db를 넘겨주는 시점에 쿼리가 고정되어있따.
쿼리 자체는 캐싱하고 VALUES안 값을 값 바꿔치기한다. 매번 컴파일안해도되니까 성능이 좋아진다.
데이터베이스
(여기선 관계형 데이터베이스를 뜻한다.)
관계형모델을 표현하는 db인데, 관계형모델이란 테이블의 형태로 저장하는 (tabular structure?) db이다.
각 테이블과 테이블 사이에 관계가 있다. 왜 관계를 적용할까? user와 과목사이에 수강한다는 관계가 수강한다. 교수는 과목을 가르친다는 관계가 성립한다. 관계는 없어도 될텐데, 꼭 관계를 쓰는 이유는 무엇일까?
중복데이터가 많아지기 때문이다. 과목하나 들을때마다 계속
수강생1-과목1, 수강생1-과목2, 수강생1-과목3
하는 식으로 수강생1을 여러번 써야하는 중복이 발생한다.
데이터 수정할때마다 중복데이터 전부 수정해줘야한다.
관계를 사용하지 않으면 데이터 중복과 논리적 문제가 생기는 이상현상, anormally가 발생하기에 관계형데이터베이스는 테이블 형태로 저장한다.
db가 복잡하기 때문에
ORM을 사용한다. 자바 객체와 테이블매핑을 통해 db쿼리를 손쉽게 도와주느 ㄴ프레임워크이다. jpa구현체로 hibernate openjpa 등등 구현체가 여럿 존재한다. 그런데 jpa가 먼저가 아니라 hibernate가 먼저였다. 기술이 나오기 전에 표준이 나왔다는게 가능한 이유는, hibernate가 너무 좋게 나와서 사실상의 표준, 디팩토가 되었다.
(도커와 컨테이너의 관계)
우리가쓰는 것은 spring data jpa이다. 그냥 jpa가 어려우니 최고 쓰기 쉽게 만든 것이 spring data jpa이다. 자바에서 데이터베이서를 제어하는 가장 쉽다고, 완벽하다고 알려진 방법을 사용하는 것이고, 가장 나쁜방법은 방금 했던 jdbc가 가장 나쁜 방법이다.
옛날에는 더 나쁜 방법도 있었다. 적어도 우린 java안에 jdbc가 있는데, sql안에 자바 코드가 들어가는 경우도 옛날엔 있었다. 완전 최악이다.
제일 처음 jdbc를 사용했었다. jdbc의 단점은? 가장 큰 단점은 쿼리가 (천줄짜리) 자바 파일 안에 들어있다. 대기업이면 dba가 짜준다. 버전2에 마이바틱스 같은 친구들이 다른 방법으로 발전시켰다. 코드를 분리하고 싶은데 그런 생각을 못해서 버전2에서 프로시져를 사용한다.
dba가 sql을 스크립팅해서 함수로 만들면 개발자는 이걸 호출?한다. 쿼리를 한줄도 안짜도 된다.
프로시져의 문제는, 배포했다가 장애나면 유지버전이 서로 맞아야한다. 서로 버전 맞추는 툴이 없어 손으로 맞춰야한다. 프로시져 업데이트하는 경우에도 개발팀이 버전 맞춰줘야한다. 수동으로 롤백과 업데이트를 맞춰줘야하니 사용하다 묻혔다.
sql문이 우리가 원하는 클래스에 들어가는 것은 jpa와 비슷하다. sql문을 신경안쓴다. db가 객체로 들어간다. 마이바틱스는 우리가 이 쿼리를 짜는데, 별도의 xml파일에 짜기 때문에 jdbc보다 책임소재가 명확하다. 쿼리는 xml에서 읽으면 되고 개발자는 다른데서 읽으면 된다. 이것의 나쁜점은 xml, 특정 디비에 종속되어있다는 점, 쿼리 종속적으로 짤수밖에 없다는 점이다. (쿼리종속적이란 말의 뜻: mysql이면 mysql쿼리문에맞게만 작동하도록 되어있어서 다른 db로 변경하기 어렵다)
spring data jpa가 점유율 1등인데, 우리나라에선 직접 제어하는 마이바티스가 가장 많이 사용하는 방식이다.
jpa단점: 복잡한 쿼리 작성하는 것이 어렵기 때문에, 쿼리 dsl등을 사용하기도한다.
jpa는 마이바티스보다 훨씬 어려운 기술이다. 마이바티스는 누군가 디비 다른사람이 자바를 잘알면 되는데 jpa는 둘다 잘하는 사람이 한명있어야한다.
JPA기본설정
DDD..