Skip to content

[팀회고] 3주차

wi-seong-cheol edited this page Dec 14, 2023 · 1 revision

🌀 프로젝트 진행 상황

  • CRDT 구현, 서버 측 웹소켓과 연결
  • VPC, CI/CD 설정 및 배포(https)

🌈 주요 기능

  • 동시편집

🤷🏻‍♂️ 협업 중 겪은 어려움

공통

  1. 동시 편집에서 서버 저장 주기
  2. 애플 로그인에서 PKCE 방식의 유저 시크릿을 누가 만들어야하는지..?

iOS

  1. UseCaseRepository를 어떻게 설계하는지 궁금합니다. 로그인 기능이 있다면 LoginUseCase로 하나로 묶어야하는지 아니면 VerifyIdUseCase, VerifyPasswordUseCase로 세부적으로 나눠야하는지 궁금합니다.

    RepositoryAPI 를 토대로 나누어도 되는지 궁금합니다.

  2. 재귀 호출되는 함수를 호출 할 때 데이터 전달을 어떻게 하는지가 궁금합니다. ex) Socket에서 Data를 Receive하기 위한 재귀 함수를 Repository에서 받아서 UseCase로 전달할 때

BE

  1. apple login에서 최초 로그인 시에만 이메일과 사용자의 이름을 받아올 수 있는데 이것을 DB에 저장하는 것이 좋을지

  2. create, update dto에서 보통 partial type이나 pick type으로 entity의 컬럼들을 가져오는게 일반적인지, 새로운 클래스를 생성하는지. (create에서 생성, update에서 pick)

  3. 로깅을 middleware에서 처리하는데, 이러면 불건전한 요청들 다 기록되는지(interceptor에서는 404같은 요청들은 처리되지 않는다)

  4. 지금 ssh 로그인 방식이 안전한지(0.0.0.0/0 비밀번호 로그인), 추가 보안 설정 고민할 점이 있는지, ip를 집주소로 하면 카공을 할 때 접속이 안되서 불편하지 않을까)

  5. type을 해당 파일에 저장하는지 아니면 한 곳에 저장하는지

  6. 소켓 문제

    • 원래는 ws://localhost:3000/share-checklist/:cid로 동적 url로 방을 구분하려고 함.

    • 네스트의 소켓은 놀랍게도 동적 url이 안됨.

    • 그래서 우선은 ws://localhost:3000/share-checklist?cid=2 쿼리로 구분을 함.

    • 즉 모든 유저가 한 소켓을 쓰지만 소켓 안에서 cid로만 구분을 함.

    • 추후에 동적 url로 방을 구분하는 로직을 구현하여 소켓 분산을 구현해야 함.

      // 각 checklist ID별로 연결된 클라이언트들을 추적하기 위한 맵
        private clients: Map<string, Set<WebSocket>> = new Map();
      
        /**
         * 클라이언트가 연결을 시도할 때 호출되는 메서드.
         * 연결된 클라이언트에 sharedChecklistId를 할당하고 관리한다.
         * @param client 연결된 클라이언트의 웹소켓 객체
         */
        handleConnection(@ConnectedSocket() client: WebSocket, ...args: any[]) {
          const request = args[0];
          const { query } = parse(request.url, true);
          const sharedChecklistId = query.cid as string;
      
          // 클라이언트에 할당된 sharedChecklistId를 바탕으로 클라이언트 관리
          if (sharedChecklistId) {
            client['sharedChecklistId'] = sharedChecklistId;
            if (!this.clients.has(sharedChecklistId)) {
              this.clients.set(sharedChecklistId, new Set());
            }
            this.clients.get(sharedChecklistId)?.add(client);
          }
        }
  7. 앱설치용 홈페이지와 nest서버가 같은 서버의 nginx상에 존재하는데 이를 분리해야 하는지

🙆🏻‍♂️ 해결 방법

✔️ 멘토링 내용

BE

서버 동기화 시간?

거래소에서도 소켓을 사용하는데 변화가 생길 때마다 db에 저장하고 있음. 따라서 바로바로 저장한다고 해서 크게 db쪽에서 부하가 클 것 같지는 않음.

변경이 일어날 때마다 db에 저장하고 병목이 일어나면 추가로 개선


로컬에서도 crdt를 저장해야하는가?

예외케이스가 존재한다. 로컬에 저장되어 있는거랑 서버에서 받아오는 거를 비교해서 동기화 로직 적용해서 저장해야할 것 같다.


유저 시크릿?

탈취는 애플리케이션 단에서 일어나가지고 서버를 속이는 것임.

서버쪽에서 시크릿을 만드는게 맞음.


리프레시 토큰 기한을 무제한?

앱에서는 보통 2주에 한번씩 액세스토큰이 만료되서 로그인을 시킨다.

apple login했으니까 같은 이메일로 다른 도메인으로 로그인이 안되게 제약을 걸 수 있고 통합되게 할 수 있고 구현하기 나름

extend를 많이 써서 오히려 연결이 많이 되서 다 수정해야하면 잘못 쓴거고, 다 연결해서 하나만 수정해도 다 반영이 될 정도로 생산성이 높아진다면 잘쓴거고.

trade off를 계산해서 생산성이 높아지도록 설계를 잘 해보자.

회사에서는 의도적으로 중복되는 코드를 쓰고 있다.

왜끝냈는지 필드 추가


로깅

interceptor 단 고려


서버 보안

프록시 서버 중간 레이어 두기

nginx에서 로드밸런싱

http 전용 통로

프록시라는 퍼블릭 서버 생성

이 키를 각각 컼뮤펕에 갖고 있기

비밀번호 대신 키를 갖고 로그인

고정 ip x로만 nestjs 서버에 접근할 수 있기

집에서는 접근할 수 없음

nest를 private으로 돌리기?


iOS

q: 웹 소켓이 무한 루프 형태로 리시브 메서드가 돌고 있는데 리시브한 메세지를 어떻게 비동기적으로 뷰에 넘길 수 있을지?!

a: 아키텍처를 꼭 준수해야하는 건 아니다. 웹 소켓을 뷰컨으로 빼야할 것 같다.

q: UseCaseRepository를 어떻게 설계하는지 궁금합니다. a: 유즈 케이스는 기능 단위로 가져가고, 레포지토리는 API 단위로 가져간다.

🐥 메디컬 체크

  • 동석: GOOD
  • 민성: 낫배드~
  • 성훈: 어제보다 조금 나음...
  • 성철: 졸리다..
  • 영균: 피곤쓰쓰

🐥 오리 수면시간

  • 동석: 02:30 ~ 09:20
  • 민성: 03:00 ~ 09:30
  • 성훈: 02:30 ~ 10:00
  • 성철: 02:00 ~ 08:00
  • 영균: 02:00 ~ 08:00

🐥 오리 저녁엔 뭐 했을까~!

  • 공통: 멘토링 회의 진행

🐥 오리 오늘 할 것!

  • 공통: 회의

오리들의 애자일한 개발 여정

📜 기획

💢 규칙

🐥 1주차 회의록, 회고

데일리 스크럼

회의록

회고

🐥 2주차 회의록, 회고

데일리 스크럼

회의록

회고

🐥 3주차 회의록, 회고

데일리 스크럼

회고

🐥 4주차 회의록, 회고

데일리 스크럼

회고

🐥 5주차 회의록, 회고

데일리 스크럼

회고

🐥 6주차 회의록, 회고

데일리 스크럼

회고

🍎 iOS

아키텍처 의사 결정 기록

Clone this wiki locally