Skip to content

Readme ‐ 고민와 문제 해결

Nathan.LIU edited this page Oct 14, 2024 · 13 revisions

고민와 문제 해결

   1. serializers 사용에 대한 고민
  - 다양한 데이터 정보를 직렬화, 역직렬화해서 유지보수하기 쉽다.
  - 중복된 코딩 내용을 통일 시킬 필요가 있다.
  - 일관성 있는 응답 내용을 한곳에 정리하는 게 좋다.
  - 유효성 검사 도 serializer통해서 처리하는 게 좋다.
     의견: model를 통해 DB 접근하는 유효성 검사는 View에서 처리해주는게 맞다.
     결론: 모델의 필드 타입에 맞는지, 필수 필드가 누락되지 않았는지 등을 확인도 필요하다. 단 복잡한 유효성검사가 필요한 경우는 View에서 직접 처리하자. 

2. 테스트 대한 고민: 기능이 점점 많아지면서 테스트를 어디까지 해야하는지
  - 앱별로 테스트 추가해서 정리하자
  - 앱에 필요한 py 문서 별로 작성하자
     의견: 종복된 테스트가 많아져서 고민이다

사용자 관리(acounts.app)

1. 사용자의 권한 결정 방법
  - 모델: CustomUserManager
  - 관리자가 영상관련 정보를 조회가능한다
  - 학생은 영상관련 정보를 조회 할수 없다. 

2. 커스텀유저 필요한 이유
  - 모델: CustomUser
    - 사용자 식별 ID VS Email
	- 필수 필드 결정
	- 일부 필드 삭제

사용자 인증(jwtauth.app)

   1. 인증 문제:
     - 세션인증 VS 토큰 인증

       ### **a. 세션 인증 (Session Authentication)**

       **세션 인증**은 서버가 사용자 로그인 시 인증 정보를 서버 메모리나 데이터베이스에 저장하고, 클라이언트와 서버 간의 모든 요청에서 이를 확인하는 방식입니다.

       #### **작동 방식**
       1. 사용자가 로그인하면 서버는 **세션 ID**를 생성하고, 이를 서버 측(예: 데이터베이스)에 저장합니다.
       2. 서버는 이 세션 ID를 **쿠키**에 담아 클라이언트에게 전달합니다.
       3. 이후 클라이언트는 각 요청마다 이 쿠키를 서버로 다시 전송합니다.
       4. 서버는 세션 ID를 확인하여 사용자 상태를 인증합니다.


       ### **b. JWT 토큰 인증 (JWT Authentication)**

       **JWT (JSON Web Token)**은 상태 비저장 인증 방식으로, 클라이언트가 로그인 후 서버에서 발급한 토큰을 클라이언트 측에 저장하고 요청마다 이를 서버로 보내어 인증하는 방식입니다.

       #### **작동 방식**
       1. 사용자가 로그인하면 서버는 **JWT 토큰**을 생성하고 클라이언트에게 전달합니다.
       2. 이 토큰은 클라이언트(주로 브라우저의 LocalStorage나 SessionStorage)에 저장됩니다.
       3. 이후 클라이언트는 요청 시마다 이 JWT를 **Authorization 헤더**에 담아 서버로 전송합니다.
       4. 서버는 토큰을 확인하여 사용자를 인증합니다. JWT는 **서명**되어 있으므로 서버는 토큰이 변조되지 않았는지 확인할 수 있습니다.

       | **구분**           | **세션 인증 (Session Authentication)**                                                      | **JWT 토큰 인증 (JWT Authentication)**                                          |
       |--------------------|-------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
       | **서버 상태 관리**  | 서버가 세션 데이터를 관리 (상태 유지)                                                         | 서버가 상태를 유지하지 않음 (상태 비저장)                                       |
       | **확장성**         | 서버 상태 동기화가 필요해 확장성 낮음                                                          | 여러 서버 간 세션 동기화 불필요해 확장성 높음                                   |
       | **보안성**         | 서버에 세션이 저장되므로 민감한 정보가 클라이언트에 노출되지 않음                               | 서명이 포함된 토큰으로 변조 방지, 그러나 클라이언트에 저장되므로 XSS에 취약      |
       | **서버 리소스**     | 각 사용자의 세션을 서버가 관리하므로 서버 메모리 및 리소스 소모                                | 상태를 유지하지 않아 서버 리소스 사용이 적음                                    |
       | **로그아웃 처리**  | 서버에서 세션을 바로 만료시킬 수 있음                                                          | 토큰 만료 관리가 필요하며, 즉각적인 로그아웃 처리 어려움                        |
       | **공격 취약성**    | CSRF 공격에 취약                                                                               | CSRF에 상대적으로 안전하지만 XSS에 취약                                         |
       | **토큰 크기**      | 세션 ID만 전송하므로 크기가 작음                                                               | JWT는 크기가 더 클 수 있고, 각 요청마다 토큰을 전송해야 함                      |
       | **네트워크 부하**   | 세션 ID만 전송하므로 네트워크 부하 적음                                                        | JWT 토큰을 요청마다 전송하므로 네트워크 부하 증가 가능                          |
       | **브라우저 호환성** | 대부분의 브라우저에서 기본적인 쿠키를 통해 쉽게 사용 가능                                      | 브라우저 호환성 높음, 그러나 LocalStorage나 SessionStorage 사용 시 XSS 위험 존재 |
       | **통합 가능성**     | 주로 단일 시스템에서 사용, 다른 서비스 간 통합 어려움                                           | 여러 서비스 간 통합 용이, 마이크로서비스 아키텍처에서 유리                      |



       ---

       ### **결정**
       - **JWT 토큰 인증** 방식을 사용하기로 결정

       #### 결정 이유:
       1. **서버 부하 최소화**: 상태를 유지하지 않아 서버 리소스 소모가 적습니다.
       2. **효율적인 네트워크 사용**: 인증에 필요한 정보의 양이 적고, 추가적인 부하 증가 우려가 크지 않습니다.
       3. **토큰 만료 관리**: 토큰 수명 설정과 Blacklist 모델을 통해 효과적으로 관리할 수 있습니다.
       4. **확장성**: 마이크로서비스 아키텍처에 적합하며, 이는 좋은 개발 경험을 제공할 수 있습니다.
       5. **보안 강화**: XSS와 같은 보안 위협에 대비하기 위해, 토큰은 **Cookies**에 저장하여 전송할 계획입니다.

       ---

   2.  토큰 만료 문제:

     - refresh 토큰 처리 방법 RTR
       **RTR(Refresh Token Rotation)**는 만료된 JWT 토큰을 처리하고 새 토큰을 발급하는 방식으로, 보안을 강화하는 데 중요한 방법 중 하나입니다. JWT 인증에서 **토큰 만료 처리**와 **토큰 갱신**이 중요한 이슈인데, 이 문제를 해결하는 하나의 전략이 **Refresh Token Rotation**입니다.

       ### **Refresh Token Rotation(RTR) 개념**
       RTR은 **갱신 토큰(Refresh Token)**를 한 번 사용할 때마다 새로운 갱신 토큰을 발급하고, 이전 갱신 토큰을 폐기하는 방식입니다. 이를 통해 만료된 토큰을 안전하게 관리할 수 있고, 보안을 강화할 수 있습니다.

       ### **기본 원리**
       1. **Access Token**: 만료 시간이 짧은 토큰으로, 사용자는 이 토큰을 통해 요청을 인증합니다.
       2. **Refresh Token**: 만료 시간이 긴 토큰으로, Access Token이 만료되었을 때 새로운 Access Token를 발급받는 데 사용됩니다.
       3. **토큰 순환**: 기존의 Refresh Token를 사용할 때마다 새로운 Refresh Token이 발급되며, 사용된 기존의 Refresh Token은 즉시 무효화됩니다.

       ### **작동 방식**
       1. **사용자 로그인 시**:
          - 서버는 Access Token과 Refresh Token를 함께 발급합니다.
          - Access Token은 클라이언트가 API 요청 시 인증하는 데 사용되고, Refresh Token은 클라이언트 측에 저장됩니다.

       2. **Access Token 만료 시**:
          - 클라이언트는 만료된 Access Token과 Refresh Token를 서버로 전송합니다.
          - 서버는 Refresh Token이 유효한지 확인하고, 유효하면 새로운 Access Token과 Refresh Token를 발급합니다.
          - 이때, **기존의 Refresh Token은 폐기**되고 **새로운 Refresh Token**이 발급됩니다.

       3. **Refresh Token 도난 방지**:
          - 이전에 발급된 Refresh Token이 노출되어 악의적인 사용자가 이를 사용하려고 할 때, 해당 토큰은 이미 무효화되었기 때문에 재사용이 불가능합니다. 이를 통해 보안을 강화할 수 있습니다.

       ### **RTR 사용 시 장점**
       1. **보안성 강화**: Refresh Token를 한 번 사용할 때마다 새로운 토큰을 발급하여, 도난된 토큰의 재사용을 방지할 수 있습니다.
       2. **토큰 탈취 위험 감소**: 누군가 Refresh Token를 탈취해도, 그 토큰은 이미 만료된 상태일 가능성이 크기 때문에 보안 위협을 줄일 수 있습니다.
       3. **긴 세션 유지**: 짧은 Access Token의 수명을 유지하면서도, Refresh Token를 통해 사용자가 지속적으로 인증 상태를 유지할 수 있습니다.


   3. 소셜 로그인
    - 구글 로그인
          - Google OAuth2를 사용해 사용자를 인증합니다
    - 카카오 로그인
          - 카카오 로그인 같은 방식으로 구현했지만, 인증 불가.

   4. 이슈
           -  module 'jwt' has no attribute 'encode'
           - 원인: jwt와 PyJWT 동시 설치시 오류 발생
           - 해결: jwt와 PyJWT 삭제후 PyJWT 재설치

영상, 이미지(materials.app)

모델1: Image
이슈: 이미지 업로드 문제
https://github.com/weaverse-techtide/weaverse-backend/issues/167

모델2: Video
모델3: VideoEventDate

모델 관계 고민
의견: 결제된 강의 영상만 영상 시청
  유저  : Video = 1 : N 
  Video : VideoEventDate = 1 : N
의견: 권한 설정와 별개로 유저와 Video 는 각각 독립 적인 관계
  - 유저  : VideoEventDate = 1 : N
  - Video : VideoEventDate = 1 : N

추가 - WatchHistory 모델 추가 고민
  - 목적: 유저가 Video 모델와 VideoEventDate 관리하자.
  - 의견: VideoEventDate와 WatchHistory의 역할이 겹친다.
  - 의견: 유지보수상 이벤트 발생시 수정하는 일 더많이 생긴다.

Course,Mission(courses.app)

모델1: Curriculum
모델2: Course
모델3: Lecture
모델4: Topic
모델5: MultipleChoiceQuestion
모델6: Assignment

payment(payments.app)

모델1: Cart
모델2: CartItem
모델3: Order
- 오더에서 Video 재생 여부를 결정하자.
모델4: OrderItem
모델5: UserBillingAddress
모델6: Payment
- materials에 UserVideo모델 추가해서, 결제여부 시청 가능한 영상 조회 하자.
Clone this wiki locally