PK와 FK와 마찬가지로 index 또한 막연하게 사용하면 쿼리 속도가 빨라진다 라는 생각만 가지고 있던 내용이기 때문에 index란 무엇인지 알아보려고 한다.
INDEX란?
RDBMS에서 검색 속도를 높이기 위한 데이터베이스 객체입니다. INDEX는 색인입니다. 특정 TABLE의 칼럼을 색인화 하여 검색할 때 TABLE의 레코드를 전부 다 확인하는 것이 아니라 색인화 되어있는 INDEX파일을 검색하여 검색 속도를 빠르게 합니다.
INDEX 사용 이유는?
데이터 저장 영역에서는 인덱스가 없는 테이블의 데이터를 찾을 때 무조건 전체 데이터 베이스를 처음부터 끝까지 다 읽어서 검색조건에 맞게 찾게됩니다. 이런 식의 검색 방법을 Full Scan이라고 하는데, 양이 엄청나게 많은 테이블에서 데이터를 불러올 때 Full Scan을 하게 되면 처리 성능이 떨어집니다. 고로 Index는 데이터를 검색할 때 빠르게 찾기 위해 사용된다.
장점
무조건은 아니지만 검색 속도를 향상할 수 있습니다. - 인덱스를 생성 시에는 where절과 join, order by 등과 관련된 칼럼 중 사용빈도가 높고 키값의 선별도가 좋은 칼럼에 사용해야 합니다. 반대로 사용빈도가 낮고 칼럼의 선별도가 좋지 않은 (값이 True /False 같은 것들) 칼럼의 경우에는 인덱스를 사용하지 않는 것이 좋습니다 - 테이블이 작거나 자주 갱신이 필요한 칼럼들에도 사용하지 않는 것이 좋습니다.
MSSQL을 사용함에 있어 중요한 Stored Procedure를 왜 사용하는 것이고, 어떠한 장단점이 있는지 알아보려고 한다.
스토어드 프로시저란?
쿼리를 함수처럼 실행하기 위한 쿼리의 집합
스토어드 프로시져는 저장 프로시저라는 뜻을 가지고 있다.
DB에 있는 데이터를 조회하기 위해서는 짧은 쿼리문 뿐만 아니라 100줄이 넘어가는 긴 쿼리를 작성해야 하는 경우가 생기는데,
작성된 쿼리문을 프로시저에 저장, 필요할 때에 프로시저를 호출 하여 효율적으로 프로그래밍 하기 위해 사용된다.
또한 IF문이나 반복문을 사용하여 프로시저를 호출 할 수 있는 것도 큰 장점이라고 생각된다.
*알고보니 프로시저는 MSSQL뿐만 아니라 MySQL에서도 사용이 되고 있었다.
장점
하나의 요청으로 여러 SQL문을 실행 할 수 있다. - 하나의 sp안에 IF문과 반복문을 사용하여 여러 형태의 쿼리문을 작성한다.
네트워크 소요 시간을 줄일 수 있다. - 동일한 쿼리를 1000번 2000번 호출하는 것보다 SP를 이용해서 구현한다면 SP를 호출할 때 한 번만 네트워크를 경유하기 때문에 네트워크 소요시간을 줄이고 성능을 개선할 수 있다.
개발 업무를 구분해 개발 할 수 있습니다. - 순수한 애플리케이션만 개발하는 조직과 DBMS 관련 코드를 개발하는 조직이 따로 있다면, DBMS 개발하는 조직에서는 데이터베이스 관련 처리하는 SP를 만들어 API처럼 제공하고 애플리케이션 개발자는 SP를 호출해서 사용하는 형식으로 역할을 구분하여 개발이 가능
단점
처리 성능이 낮다. - 문자나 숫자 연산에 저장 프로시저를 사용한다면 오히려 C나 JAVA보다 성능이 느리다.
디버깅이 어렵다. - 너무 공감하는 부분이다.. 실제 프로시저를 작성하여 개발하면서 어떤 부분에 오류가 나고 있는지 자세하게 알려주지 않기 때문에, 프로시저 자체를 호출하면서 중간중간 실행되고 있는 결과를 찍어보면서 디버깅을 해야한다.(php처럼 디버깅 해야했던 기억이 난다)
DB 확장이 매우 힘들다. - 서비스 사용자가 많아져 서버수를 늘려야할 때, DB 수를 늘리는 것이 더 어렵다.
서비스 확장을 위해 서버수를 늘릴경우 DB 수를 늘리는 것보다 WAS의 수를 늘리는 것이 더 효율적이기 때문에 대부분의 개발에서 DB에는 최소의 부담만 주고 대부분의 로직은 WAS에서 처리할 수 있게 합니다. (아마도 api를 호출하는 서버를 분할하여 늘리는 것을 얘기하는 것 같다..)
데이터베이스를 다루면 가장 기본적으로 pk와 fk에 대해서 '당연하게 사용해야 하는 것' 이라는 것만 알고 있지 어떤 의미이며 왜 사용해야 하는지에 대해서 모르고 있었기 때문에 정리를 하려 한다.
KEY란?
데이터베이스에서 조건에 만족하는 튜플을 찾거나 순서대로 정렬할 때 튜플들을 서로 구분할 수 있는 기준이 되는 어트리뷰트를 말한다.
즉 테이블에서 데이터를 구분하여 쉽게 찾기 위해 설정 하는 것 이라는 의미로 생각 된다.
1. PK
1.기본키는 후보키 중에서 선택한 주키(Main Key)이다.
2.한 릴레이션(테이블인것 같다)에서 특정 튜플을 유일하게 구별할 수 있는 속성이다.
3.Null값을 가질 수 없다.
4.기본키로 정의된 속성에는 동일한 값이 중복되어 저장될 수 없다.
(중복되지 않고 유일하게 구별 가능한 속성)
후보키란? 릴레이션을 구성하는 속성들 중에서 튜플을 유일하게 식별하기 위해 사용하는 속성들의 부분집합, 즉 기본키로 사용할 수 있는 속성들을 말한다. 하나의 릴레이션내에서는 중복된 튜플들이 있을 수 없으므로 모든 릴레이션에는 반드시 하나 이상의 후보키가 존재한다. 후보키는 릴레이션에 있는 모든 튜플에 대해서 유일성과 최소성을 만족시켜야 한다.
유일성 : 하나의 키값으로 하나의 튜플만을 유일하게 식별할 수 있어야한다. 최소성 : 모든 레코드들을 유일하게 식별하는데 꼭 필요한 속성만으로 구성되어 있어야한다.
2. FK
1.관계를 맺고 있는 릴레이션 R1,R2에서 릴레이션 R1이 참조하고 있는 릴레이션 R2의 기본키와 같은 R1 릴레이션의 속성을 외래키라고 한다.
2.외래키는 참조되는 릴레이션의 기본키와 대응되어 릴레이션 간에 참조관계를 표현하는데 중요한 도구이다.
foreign key를 사용하는 이유는 참조 무결성을 위해서이다. 연관관계에 있는 테이블에서, 외래키로 지정된 컬럼 데이터가 부모의 기본키 외 다른 값을 가질 수 없게 하여 외래키 컬럼에 저장될 수 있는 데이터를 제어하게 된다. 예를 들어, 유저, 주문 테이블이 있고 주문 테이블에 foreign key로 유저의 primary key를 갖고 있다 하면, 아직 가입 안된 유저 id로 주문테이블에 데이터를 넣으려하면 에러를 발생시켜 해당 데이터 삽입을 막는다. 이를 통해 주문 테이블 내에서 참조하는 값이 존재한다는 것을 보장할 수 있다. 즉 참조하는 테이블의 무결성을 높여주게 된다.
실무에서 FK를 사용 안하는 이유
DB설계를 할 때에 FK를 미리 설정 할 수 있다. 그치만 실제 테이블을 생성할 때에는 FK를 설정하지 않고 PK만 설정하고 테이블을 생성하는 경우가 많았다.
관리포인트 증가
테스트 등 진행시에 부모 row없이 자식 테이블 테스트만 하는 것이 불가능하다.
트랜잭션 안에서 부모-자식 테이블 관계에 따라 작업 순서가 필요하다.
규모가 증가함에 따라 데이터베이스의 설계도 조금씩 달라지는데 이 경우 참조무결성으로 인해 더 큰 수정개발을 불러 일으킬 수도 있다.
▶ exp : 토큰 만료 시간 [ NumericDate 형식으로 되어 있어야 한다. ex) 1480859147370 ]
* 초로 환산되어야되다는 얘기 같다.
▶ nbf : 토큰 활성 시간 [ 해당 날짜가 지나기 전의 토큰은 활성화 되지 않는다 ]
▶ iat : 토큰 발급 시간
▶ jti : JWT토큰 식별자, 중복방지를 위해 사용하며, 일회용 토큰 등에 사용된다.
② 공개 클레임
- 사용자 정의 클레임으로 공개용 정보를 위해 사용된다.
- 충돌 방지를 위해 URI포맷을 이용한다
예시)
{"https://www.admin.com/admin" : true}
③ 비공개 클레임
- 사용자 정의 클레임으로 서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다.
예시)
{"token_type" : access}
3. SIGNATURE
- 토큰을 인코딩하거나 유효성을 검증 할 때 사용되는 고유한 암호화 코드이다.
- 위에서 만든 HEADER와 PAYLOAD의 값을 각각 BASE64로 인코딩 하고, 그 값을 Secret Key(비밀키 기법)를 이용해 Header에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.
*비밀키는 오직 서버만 알고있어야 하기 때문에 서버에 저장해둔다.
[인코딩을 ✌번 ]
JWT는 세션을 대체 할 수 없다?
JWT는 세션처럼 모든 사용자들의 상태를 기억하고 있지 않다. 따라서 기억하는 대상들의 상태를 언제든지 제어할 수가 없다.
예시로 세션을 이용한 경우는 한 기기에서만 로그인 가능한 서비스를 만들고 싶을 때에, PC에서 로그인하면 핸드폰에서의 세션값은 사용하지 못하고도록 제어가 가능하지만, JWT는 이미 제공한 토큰에 대해서 수정이 불가하고, 해커에게 토큰을 빼앗겼을 경우 토큰을 무효화 할 수 없다고 한다.
대응방법은 로그인시에 accessToken, refreshToken 두개의 토큰을 부여한다.
accessToken: 매번 인가를 받을 때 사용하는 토큰. (보통 수명이 짧음)
refreshToken: accessToken의 수명이 다했을 때 accessToken을 재발행 받기 위한 토큰 보통 2주정도 기간이 길게 잡힘 (누군가를 로그아웃시키려면 refeshToken을 db에서 지워버리면 되는데 그래도 accessToken의 수명 동안은 바로 차단할 방법은 없음)