1. 대시보드에서 나타내야 할 것

- 기간에 따른 사용자 수

- 인기글 리스트

- 유입 경로 및 채널

- 유입 키워드

- 유입자 현황 차트 (척도 : 기간, Refere URL, 컨텐츠, 디바이스)

 

 

2. 추가 구현하고 싶은 것

- 전날 유입자 통계를 카카오톡으로 알림 받기

- 현재 학습하고 있는 OAuth2.0을 이용하여 대시보드 사이트 인증

- 일일 평균 유입자 현황

- 현재 기능별로 레포지토리가 분리되어있고, kafka broker에 다양한 로그들을 수집할 예정이기 때문에 향후 kubernetes를 적용할 예정

 

 

3. 사용할 기술

- DB : DynamoDB or MongoDB (조회성이 많기 때문에 RDB보다 NOSQL이 낫다고 판단) with JPA

- Message Broker : Apache Kafka (Topic은 YYYYmmDD 형식 사용, content는 json형식의 로그데이터 / 일일 배치로 DB BulkUpdate)

- Framework : spring boot with jstl (다른 가벼운 것을 써도 되지만, 학습 차원에서 사용하도록 한다.)

- 언어 : Java1.8

- 인증 : Oauth2.0(Spring Security 사용 예정), jwt

 

 

4. 수집해야할 정보

- 블로그 유입자들이 클릭한 컨텐츠

- 유입 시간대

- 블로그를 조회한 Referer URL

 

 

 

5. 아키텍처 구성도

 

 

6. 참고 문헌

- KISA 고시 및 권고 : www.kisa.or.kr/public/laws/laws2.jsp

- Apache Kafka Documentation : www.kafka.apache.org/documentation/

- RFC6749 : www.tools.ietf.org/html/rfc6749

 

 

7. 수정 로그

2020.05.13 : 최초 작성

2020.05.20 : 아키텍처 다이어그램 추가 완료

2020.06.11 : 아키텍처를 AWS로 옮기는 중, 불필요한 로드밸런서 개수와 외부 노출 서비스의 도메인 연결로 인해 아키텍처 수정중.

2020.06.16 : 서비스별 로드밸런서 아키텍처 적용 및 향후 계획(kubernetes 적용 예정) 추가

2020.06.30 : 운영 환경을 생각하고 설계할 것이기 때문에 kafka와 zookeeper를 분리하는 아키텍처 적용 예정

2020.07.01 : Zookeeper Cluster 구성 완료

1. https://json.geoiplookup.io 오픈소스

   - 위 링크를 통해 가져 올 수 있는 데이터의 목록은 다음과 같다.

(
   {
      "ip":"-",
      "isp":"-",
      "org":"",
      "hostname":"-",
      "latitude":-,
      "longitude":-,
      "postal_code":"",
      "city":"-",
      "country_code":"KR",
      "country_name":"South Korea",
      "continent_code":"AS",
      "continent_name":"Asia",
      "region":"Seoul",
      "district":"-",
      "timezone_name":"Asia\/Seoul",
      "connection_type":"Corporate",
      "asn_number":3786,
      "asn_org":"-",
      "asn":"-",
      "currency_code":"KRW",
      "currency_name":"South Korean Won",
      "success":true,
      "premium":false
   }
);

  - 하지만, 개인정보 보호법에 따르면 특정인을 유추할 수 있는 정보를 수집하여서는 안되므로, ip address, 위도, 경도를 수집하지 않겠다.

  - 최종적으로 위 오픈소스를 통해 가져갈 정보는 "country code", "region"만 가져가겠다.

 

 

 

2. Javascript - document.referrer 

  - document객체의 referrer를 이용하면, 참조한 페이지를 알 수 있다.

  - 실험 결과, 주소창에 직접 친 경우 빈 string을 출력하였으며,

  - 블로그 내부에서 다른 글을 참조하였을 경우, 블로그 도메인을 포함한 url이 출력되었다.

  - 외부 링크를 타고 오는 경우, 그대로 외부 링크를 표시했다.

  - 이를 이용하여 실질적인 블로그 이용자를 추적할 수 있을 것으로 보인다.

 

 

 

 

3. Javascript - Date.now()

  - 티스토리 대시보드에는 어느 시간대에 사람들이 들어왔는지에 대한 정보가 없다.

  - 시간대까지 포함하면, 개발자들이 어느시간대에 가장 공부를 많이하고 참조를 하는지 알 수 있을거같다. (?)

  - 그래서 이 정보 또한 수집하기로 하였다......

 

 

 

 

4. 기타 필요한 정보

  - 블로그 컨텐츠 정보

  - 디바이스 정보

 

 

 

 

5. NOSQL Table 초안

   {
      "topic":"kafka broker topic - PK"
      "date":"내 블로그를 조회한 날짜 - SK",
      "content":"조회한 블로그 컨텐츠 정보",
      "referer":"블로그 참조 경로",
      "device":"참조한 디바이스 정보",
      "time":"블로그 글을 조회 한 시간",
      "country":"국가",
      "city":"지역 이름 (시 단위 까지만)"
   }

 

 

 

 

6. 작업 이력

  - 2020.06.09 : 초안 작성 완료.

  - 2020.06.10 : AWS DynamoDB 테이블 생성 완료

1. Create

  • URL : <domain>/<version>/user
  • Method : POST
  • Request Header
    • Content-Type: application/json
  • Request Body (format = JsonObject)
    • Userinfo(userid, username, password, email, phone_number, address,  ... ) - JsonObject
    • secretHash HMAC(signing_key(clientSecret, sha256)[clientId + username]) - String
  • Response

    • If success, 
    • If failed, response is HTTP status code with customed error message

 

2. Read

  • URL : <domain>/<version>/user/me
  • Method : GET or POST
  • Request Header :
    • Authorization: Bearer <YOUR_ACCESS_TOKEN>
  • Response
    • If success, response is HTTP status code with userinfo that matched with access token.
    • If failed, response is HTTP status code with customed error message.

2.1. Read by List

  • URL : <domain>/<version>/users
  • Method : GET or POST
  • Request Header : 
    • Authorization: Bearer <YOUR_ACCESS_TOKEN>
    • Content-Type: application/json
  • Request Body
    • Query Parameters - JsonObject

 

 

 

3. Update(덮어쓰기? 부분업데이트?)

  • URL : <domain>/<version>/user/me
  • Method : PUT
  • Request Header
    • Authorization: Bearer <YOUR_ACCESS_TOKEN>
    • Content-Type: application/json
  • Request Body
    • Updated UserInfo - JsonObject
  • Response
    • If Success, return requester's id
    • If failed, response is HTTP status code with customed error message.

 

 

 

4. Delete

  • URL : <domain>/<version>/user/me
  • Method : DELETE
  • Request Header
    • Authorization: Bearer <YOUR_ACCESS_TOKEN>
  • Response
    • If Success, return customed message that user delete is completed.
    • If failed, return HTTP status code with customed error message.

 

 

 

 

 

5. User Table

  • DB : mysql
  • Storage Engine : InnoDB (Transaction이 많이 일어나기 때문에 MyISAM보다 InnoDB가 유리)
  • Schema : portal_user 
  • 향후 잘못되었다 판단한 부분은 빨간색으로 표시

 

Column Type Nullable PK 설명
id varchar(255)    O 사용자 고유 식별자
name varchar(50)     사용자 이름
email varchar(100)     사용자 이메일
authorities varchar(255) → ????     권한 → 역할의 조합이므로, 테이블을 따로 빼서 관리한다.
password varchar(255)     암호화된 비밀번호
role varchar(30) → ????     역할 → 권한에 종속되는 개념이므로, 정규화가 필요함.
last_logined_date datetime     마지막 로그인된 날짜 및 시간
account_create_date datetime     계정 생성 날짜
account_last_update_date datetime     마지막 계정 정보 수정 날짜 → 로그성임. 
credential_last_update_date datetime     비밀번호 마지막 변경 날짜 → 바로 밑 항목과 비슷한 성격이다.
비밀번호 만료일을 가지고 계산할 수 있는 항목임.
credential_expire_date datetime     비밀번호 만료일 → last update를 이 컬럼으로 대체 할 수 있음.
is_account_enabled bit(1)     계정 활성화 여부
is_account_locked bit(1)     계정 잠금 여부
is_credential_expired bit(1)     비밀번호 만료 여부 → 이 컬럼이 필요한가?
is_account_expired bit(1)     계정 만료 여부 (spring security isEnabled()와 매칭되는 column)

 

 

 

5.1. DB Table 설계시, 참고자료

https://github.com/spring-projects/spring-security/blob/master/core/src/main/java/org/springframework/security/core/userdetails/UserDetails.java

 

 

5.2. 찾은 문제점

  • Spring Security의 Default UserDetails를 보고 필드를 설계를 하였으나, 설계한 필드들이 "왜"쓰이는 필드들인지 이해를 하지 못하였다.
  • 오버헤드가 걸리지 않는 선에서 충분히 credential expire date에 대해 판별할 수 있지만, credential_expire_date와 is_credential_expired와 같은 중복케이스가 첫 설계시 존재했다.
  • 데이터에 비해 불필요하게 크기를 잡았다. 불필요한 데이터 크기 설계는 자제하도록 하자.
  • mysql 데이터 타입을 잘 모르다 보니 효율적인 데이터 타입에 대한 선택을 하지 못했다.
  • 정규화를 하지 못했다.

 

 

 

6. 20200423 개선된 DB 설계

 

6.1. User Schema

Column Type Nullable PK 설명
id varchar(20)    O 사용자 고유 식별자
name varchar(10)     사용자 이름
email varchar(30)     사용자 이메일
password varchar(255)     암호화된 비밀번호
last_logined_date datetime O   마지막 로그인된 날짜 및 시간
account_create_date datetime     계정 생성 날짜
account_last_update_date datetime     마지막 계정 정보 수정 날짜
credential_expire_date datetime     비밀번호 만료일
is_account_enabled bit(1)     계정 활성화 여부
is_account_locked bit(1)     계정 잠금 여부
is_account_expired bit(1)     계정 만료 여부

 

 

6.2. Authority Schema(복합 PK)

Column Type Nullable PK FK 설명
id varchar(20)   O User.id User Table로부터의 외래키
role varchar(10)   O   User에게 부여된 역할

+ Recent posts