토이 프로젝트 설계시 간과 할 수 있는 부분은 약관에 대한 부분이다.
보통의 경우 회원가입시에 사용자로부터 데이터를 받고 관리하기 위해 동의를 구하게 된다. 따라서 동의를 하지 않는 다면 회원가입 자체가 불가능 하도록 한다. 추가적으로 광고성 이메일 수신 동의 같은 항목을 선택항목으로 두기도 한다.
회원가입 시에 사용자의 약관 동의 여부를 저장하기 위한 데이터베이스 스키마를 설계할 때는, 각 약관의 유형(필수, 선택)과 동의 여부를 저장하는 것이 중요하다. 이를 위해 아래와 같은 두 가지 테이블 구조를 생각했다.
CREATE TABLE Terms (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
content TEXT,
type ENUM('mandatory', 'optional') NOT NULL, # 의무, 필수 여부
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE UserTerms (
user_id INT NOT NULL,
term_id INT NOT NULL,
agreed TINYINT(1) NOT NULL,
agreed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, term_id),
FOREIGN KEY (user_id) REFERENCES Users(id),
FOREIGN KEY (term_id) REFERENCES Terms(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
UserTerms 테이블은 특정 사용자가 특정 약관에 동의했는지 여부를 저장한다. 이때 user_id와 term_id가 복합 기본 키로 설정되어, 한 사용자가 같은 약관에 대해 여러 번 동의할 수 없게 합니다.
기업은 사용자에게 동의를 받은 약관 내용에 변경사항이 생기면 사용자에게 알려야합니다.
약관 정보가 담겨있는 Terms 테이블의 1번 약관 내용이 변경되었다면 UserTerms 에서 1번 약관에 동의했던 모든 User 에게 개정에 대한 안내 메일을 보내면 됩니다.
UserTerms 에 약관번호, 동의여부에 대한 내용도 모두 있기 때문에 가능합니다.
만약 약관이 추가되거가, 혹은 변경한 약관 내용을 반.드.시 사용자가 인지해야하며 변경된 약관에 동의를 하지 않는 경우 서비스를 이용할 수 없도록 하는 경우를 생각해보자.
기존의 약관이 어떤 이유로 인해서 개정되어야하고, 사용자들에게 알려야한다고 가장하자.
기존의 약관을 1 Version 이라고 하면 개정된 약관은 1.1 혹은 2 Version 이런 식이다.
사용자에게 알려야하긴 하지만 명시적으로 동의를 받아야 하지 않아도 기존 Version 1 약관에 추가적인 동의 없이 서비스를 계속 이용할 수 있는 경우라면 1.1, 1.123 이렇게 앞 숫자를 versioning 하지 않도록 한다.
만약 명시적으로 동의를 받아야 한다면 2, 3 앞 숫자를 올리는 식으로 관리한다.
Version 을 관리할 수 있는 테이블을 하나 더 추가합니다.
Terms 와 TermVersions 는 일대다 관계를 유지하도록 합니다.
CREATE TABLE TermVersions (
id INT AUTO_INCREMENT PRIMARY KEY,
term_id INT NOT NULL,
version INT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (term_id) REFERENCES Terms(id)
);
약관이 변경되거나 추가되었을 경우 약관 변경(또는 추가했을 경우)에 대해 유저로부터 동의를 다시 받아야 서비스를 이용할 수 있다고 가정해보자.
동의 받지 않은 사람은 서비스를 이용하지 못하도록 어떻게 강제할 수 있을까?
API 요청할 때마다 약관 갱신 동의 여부 등을 확인한다.
do service {
if 동의여부 else 예외 // 추가
}
필수 동의 항목을 모두 받았는 지에 대해 확인하는 API 를 별도로 만든 후 로그인 후에 바로 요청할 수 있도록 한다. -> 이때 동의를 받아야하는 데 받지 않은 경우에는 적절한 메시지와 함께 사용자로 부터 변경된 약관 동의를 받을 수 있도록 한다.
JWT Claim 에 필수 최신 약관 동의여부 저장한다.
2번을 보완하기 위해 고안되었습니다.
로그인 시 발급하는 JWT 토큰에 변경 + 동의가 반드시 필요한 약관에 대해 동의를 했는 지 여부 혹은 어떤 Version 의 약관에 동의했는 지에 대해 version 을 JWT Claim 에 담은 후 토큰을 발급합니다.
{
"sub": "1234567890",
"name": "John Doe",
"agreed_terms_version" : "1"
"iat": 1516239022
}
agreed_terms_version 는 유저가 필수로 동의했던 이용약관 version 을 뜻합니다. token 파싱후 version 2 가 아닌 경우 서버는 해당 서비스를 이용하지 못하게 합니다.
장점 👍
1. Token 에 약관 관련 정보가 있기 때문에 추가적인 DB 조회를 하지 않아도 된다.
단점 👎
2.새롭게 동의 이후에는 토큰을 재발행 해야한다.