프로젝트- 빙터뷰 개발 일지

Chan Young Jeong·2023년 4월 1일
0

프로젝트 빙터뷰

목록 보기
1/9
post-thumbnail

요구사항 수집 및 분석 (3월 28일 Updated)

면접 영상 업로드 및 피드백 기능

  1. 사용자는 면접 피드백을 위해 게시판에 면접 영상을 올릴 수 있다
    a. 영상을 올릴 때에는 어떤 질문에 대한 답변인지와 답변 영상이
    포함되어야 한다
    b. 답변 영상을 업로드하면 익명성 보호를 위해 버추얼 캐릭터 혹은 가상
    인간으로 얼굴이 변환된다
    c. 사용자는 질문을 선택하여 답변 영상을 올릴 수 있다
  2. 사용자는 다른 사람의 면접 영상을 보고 피드백을 남길 수 있다
  3. 사용자는 내 영상에 대한 피드백을 볼 수 있다
  4. 사용자는 내 영상에 피드백을 남긴 다른 사용자의 활동 내역을 확인할 수
    있다
    a. 활동내역은 사용자가 피드백을 신뢰할 수 있는 근거를 제공해준다
  5. 사용자는 질문별로 영상을 필터링해서 조회할 수 있다

면접 예상 질문 공유 기능

  1. 사용자는 면접 예상 질문을 올려서 공유할 수 있다
    a. 예상 질문에는 직군, 기업, 분류에 대한 태그를 달 수 있다
    b. 태그는 제공이 되고 사용자는 이 태그를 조합하여 사용한다
    c. 면접 예상 질문에는 스크랩 수, 조회수, 답변 영상 수가 표시된다
  2. 사용자는 면접 예상 질문을 확인할 수 있다
  3. 사용자는 관심 질문 목록에 질문을 스크랩할 수 있다
  4. 사용자는 질문에 담긴 태그별로 필터링하여 조회할 수 있다
  5. 사용자는 최신순, 조회수순, 스크랩순, 답변 영상순으로 정렬하여 질문을
    조회할 수 있다
  6. 스크랩이나 답변 영상이 많은 질문은 상위에 노출된다

실시간 모의 면접 연습 기능

  1. 사용자는 면접의 분야와 종류를 선택한 뒤 연습하고 싶은 질문을 등록하여
    매칭을 시작한다
    a. 유사한 조건으로 매칭을 시작한 사람들끼리 연결되어 면접 연습방이
    만들어진다
    b. 매칭 시 선택할 수 있는 조건으로는 분야, 직무, 기업 및 면접 종류
    등이 있다
    c. 매칭을 잡기 위해 등록해야 하는 질문의 경우 사용자가 직접 등록할
    수도 있고 질문 게시판의 질문 중에서 고를 수도 있다
    d. 사용자는 질문을 등록할 때 예상 답변 시간을 정한다
  2. 방에 입장한 사용자는 각각의 참여자가 등록한 질문을 연습할 수 있다
    a. 참여자들이 등록한 질문 중 하나가 랜덤하게 화면에 띄워지고 각
    참여자에게 답변 순서가 랜덤하게 부여된다
    b. 사용자는 본인의 순서가 되면 캠을 켜고 질문에 대한 답변을 진행한다
    c. 사용자가 답변 시 버추얼 캐릭터가 입혀진다
    d. 답변은 질문 등록자가 설정한 예상 답변 시간 동안 발언이 가능하다
    e. 답변 영상은 자동으로 저장되어 추후에 확인이 가능하다
    f. 만약 답변을 포기하고 싶으면 답변을 스킵 할 수 있고, 다음 순서로
    넘어간다
  3. 모든 질문에 대한 답변을 마치면 연습이 종료된다
    a. 연습이 종료되면 면접에서 자신을 제외한 사용자 중에서 가장 답변을
    잘했다고 생각하는 사용자를 고르고, 가장 많은 표를 받은 사용자는
    티어 상승을 위한 추가 내공을 받는다
    b. 연습이 종료되면 본인이 답변한 영상을 확인할 수 있고, 다른사람의
    피드백을 위해 면접영상 피드백 게시판에 등록할 수 있다
  4. 사용자는 자신과 티어가 비슷한 사람들과 매칭될 수 있도록 티어별 서버에
    입장할 수 있다

사용자 티어 기능

  • 멘토링 및 교수님과 면담 결과 티어를 이용해서 사용자에게 줄 메리트가 없다고 판단.
  • 기능 구현할 것이 많기에 티어는 조금 내려 놓고 다른 기능 구현에 초점을 맞추어 프로젝트 진행하는 것이 맞다고 판단.

DB 및 API 설계(4월 30일 Updated)

API 설계 document

2023년 6월 1일

  • ec2 p2.xlarge 인스턴스 생성하기 위해 vCPU 인스턴스 제한 증가 요청
  • docker 이용하여 deepfake flask server
    python 3.9
    requiremets.txt
$docker pull python:3.9-buster

# 컨테이너 생성 후 /bin/bash 실행
$ docker container run -it --name=flask_server -p 80:5000 python:3.9-buster /bin/bash


$ git clone <flask server git url>
$ apt-get update
$ apt-install vim
# config.py 생성
$ vim config.py 
# checkpoints copy
$ docker cp <host path>  <container path> 
$ pip install -r requirements.txt
$ pip install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html
$ pythoon app.py

2023년 5월 22일~30일

2023년 5월 21일

WebSocket HandshakeInterceptor 이용해서 클라이언트 식별

public class WebSocketAuthenticationInterceptor implements HandshakeInterceptor {

    private final MemberRepository memberRepository;

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        JwtUserDetails principal = (JwtUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Long memberId = principal.getId();
        Member member = memberRepository.findById(memberId).orElseThrow(() -> new EntityNotFoundException("찾을 수 없는 사용자입니다."));

        attributes.put("name", member.getName());
        attributes.put("imageUrl", member.getProfileImageUrl());
        return true;
    }

웹소켓에 보낼 프로필 이미지 인코딩 할 때 에러 발생시 기본 이미지로 인코딩 시도. 기본 이미지도 인코딩 실패 할 때는 빈 문자열로 지정.

 public void convertImageToBase64(String imageUrl) {
        URL url = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            url = new URL(imageUrl);
            is = url.openStream();
            baos = new ByteArrayOutputStream();

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }

            byte[] imageBytes = baos.toByteArray();
            String base64Image = Base64.getEncoder().encodeToString(imageBytes);

            is.close();
            baos.close();
            this.encodedImage = base64Image;

        }
        catch (Exception e) {
            log.error("Exception convertImageToBase64");
            if(imageUrl == "https://vingterview.s3.ap-northeast-2.amazonaws.com/image/ced77a75-31f1-47ce-82a0-6923b55cb7bb.png"){
                log.error("기본 이미지 인코딩 실패");
                this.encodedImage = "";
                return;
            }
            convertImageToBase64("https://vingterview.s3.ap-northeast-2.amazonaws.com/image/ced77a75-31f1-47ce-82a0-6923b55cb7bb.png");
        }
    }

2023년 5월 20일

게시글 혹은 댓글 수정 시 자신이 작성한 글이 아닐 경우 403 FORBIDDEN 응답 하도록 코드 수정. 과정에서 AccessDeniedAcception을 던지는데 에러를 각 컨트롤러 메서드에서 하나씩 받아서 처리할려고 하니 SRP , OCP를 위반하는 것 같아 ExceptionHandler 이용해서 처리하도록 함.

    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(AccessDeniedException.class)
    public ErrorResult accessDeniedExHandle(AccessDeniedException e) {
        log.error("[accessDeniedExHandle] ex", e);
        return new ErrorResult("403", e.getMessage());
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(EntityNotFoundException.class)
    public ErrorResult entityNotFoundExHandle(EntityNotFoundException e) {
        log.error("[entityNotFoundExHandle] ex", e);
        return new ErrorResult("404", e.getMessage());
    }


2023년 5월 18일

딥페이크 기술을 이용한 영상과 오디오를 합쳐서 최종 결과물 s3에 업로드 하는 파이프라인 구축

  1. ~8080/boards/video 로 원본 파일 업로드 요청 / 비동기로 s3 최종 주소 응답
  2. 임시 폴더에 원본 파일 저장 및 원본 파일에서 오디오 추출
  3. 플라스크 서버에서 모델을 이용하여 딥페이크 기술 적용한 영상 생성
  4. 추출한 오디오와 생성한 영상을 병합
  5. 최종적으로 병합한 파일을 s3에 업로드

-> 조금 더 빠르게 처리할 수 있는 방법은?

위에가 원본, 아래가 딥 페이크 기술 적용한 영상

FFMPEG

비디오 스케일링 : ffmpeg -i {input_video_path} -vf scale=360:360 {output_audio_path}

오디오 추출 : ffmpeg -y -i {input_video_path} {output_audio_path}

비디오 오디오 병합 : ffmpeg -y -i {input_video_path} -i {input_audio_path} -c:v copy
-map 0:v:0 -map 1:a:0 -shortest {output_video_path}

-c:v copy: 비디오 스트림을 원본과 동일하게 복사
-map 0:v:0: 첫 번째 입력 파일의 첫 번째 비디오 스트림을 선택
-map 1:a:0: 두 번째 입력 파일의 첫 번째 오디오 스트림을 선택

2023년 5월 17일

WebSocket 서버 개발 완료

  1. WebSocketConfig : WebSocket 설정 class
  2. SocketHandler : WebSocket 핸드러 클래스로 TextMessage, BinaryMessage를 중간에서 처리
  3. GameRoom : 게임 방
  4. GameRoomRepository : 게임 방 관리 저장소
  5. GameInfo : 게임 진행 정보
  6. GameMessage : WebSocket에서 왔다 갔다 할 메시지

2023년 5월 15일

WebSocket 통신 프로토콜 정의 및 통신 과정

2023년 5월 9일

  • 웹소켓 TextMessage 전송
  • 웹소켓 BinaryMessage 전송
  • BinaryMessage 이용해서 비디오 stream 전송
  • 서버에서 처리할 건 많이 없지만, 클라인어트 코드를 작성하는 것이 더 어려운듯,,

해야할 것: 1. WebSocket 이용해서 룸 만들기 2. 매칭 알고리즘 3. Flutter client코드 작성

2023년 5월 4일

  • AWS S3 버킷 생성해서 버킷에 프로필 업로드 할 수 있도록 변경

  • ACCESSKEY,SECRETKEY 관리 어떻게 할까?
    https://javabom.tistory.com/95
    -> EnvironmentVariableCredentialsProvider 자바 환경 변수로 등록
    -> 배포할 때는 InstanceProfileCredentialsProvider 방식 이용

  • 버킷 권한 설정? buckey policy and ACLs

https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-S3-%EB%B2%84%ED%82%B7-%EC%83%9D%EC%84%B1-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%8B%A4%EC%A0%84-%EA%B5%AC%EC%B6%95

https://stackoverflow.com/questions/47815526/s3-bucket-policy-vs-access-control-list

https://aws.amazon.com/ko/blogs/storage/understanding-s3-block-public-access/

2023년 4월 30일

  • 페이징 기능 추가
  • 필터링 기능 추가
  • Swagger 적용

스프링 부트 3.x 버전 이상 부터는 springdoc을 사용해야함
https://resilient-923.tistory.com/414

그리고 swagger 적용하니 다음과 같은 예외 발생 Error calling jakarta.validation.Validation#buildDefaultValidatorFactory
sprig-boot-starter-validation 추가하면됨.

https://stackoverflow.com/questions/74788826/error-calling-jakarta-validation-validationbuilddefaultvalidatorfactory

implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'

implementation 'org.springframework.boot:spring-boot-starter-validation'

그리고 Security를 적용하고 있어서 404에러는 발생하지 않으나 swagger url로 접속시 아무런 page도 나오지 않음. -> swagger 관련 url permit해야함.

("/v3/api-docs/\**", "/swagger-ui/\**").permitAll()

v3부분은 각 버전에 알맞게 변경

https://jong-bae.tistory.com/12

2023년 4월 27일

시험기간을 지나서 다시 개발 진행

  • 비동기로 응답을 먼저 보내는 방식으로 응답성 개선
  • 플라스크 서버 구축 완료

동영상 필터링 과정

현재 문제가 되는 부분은 응답을 먼저 보내는데 이때 동영상 처리과정에서 오류가 발생했을 때 클라이언트에 이를 알릴 수 있는 방법이 마땅히 없다.. 좀 더 찾아봐야 할 것 같음

또한 변환 성능을 높이기 위해 source video에 사람 얼굴이 정면에 제대로 잘 나와야함 -> client 단에서 video upload할 때 가이드 라인 제시하면 ? 좋을듯

2023년 4월 10,11일

질문: service->controller로 넘겨줄 때 Domain을 넘겨주는 것이 맞을까 DTO로 넘겨주는 것이 맞을까. TEST Case 작성하면서 궁금해짐. 밑에 글을 보면 도메인을 controller 단까지 전달하면 controller가 Model과 결합도가 증가하여 유지 보수 측면에서 좋지 않다고함.

  • BoardService, MemberService test case
  • 기본적인 happy case는 개발 완료
  • 추후에 edge case 관련해서 예외 처리 및 test code 작성 필요

멘토링 Q&A (4월 11일)

  1. 크기가 큰 파일(동영상)들은 어떻게 효율적으로 업로드 할 수 있을지?
    -> 클라이언트에서 파일을 분할하여 전송하면 -> 병렬적으로 처리
    -> 클라이언트 사용성 측면에서 비동기 개발 고려
    -> 동영상 압축, 용량 제한 정책 검토
    -> 인스타그램에서 동영상 게시물을 업로드 하는 걸 보면 게시글을 업로드한 후 status bar가 나옴-> 이를 도입하는 것도 괜찮을 것 같음.

  2. 로그인 기능
    -> 로그인 기능을 본격적으로 개발하기 위해서는 개인 정보 정책부터 인코딩 디코딩 등 관리해야할 게 너무 많음
    -> 현업에서는 소셜 로그인 기능을 이용해서 구글이나 카카오 측에 위임함
    -> 현재 짧은 시간안에 개발을 해야하는 상황에서 로그인보다는 다른 중심 기능을 개발하는 것이 우선적이라 판단해서 로그인 기능을 직접 개발보다 소셜 로그인 기능 혹은 간단한 사용자 인증만 할 예정

2023년 4월 8일

  • 백, 프론트 api 통신
  • api 문서를 이용해 협업했음에도 조금씩 변수가 달랐음-> 이 부분은 api문서 기준으로 맞추기로 통일
  • 다른 기능들은 잘 동작하는 것 같으나, 동영상을 업로드할 때 문제가 발생하는 것 같음. 클라이언트 단에서 파일을 업로드 하는 동안 일정 시간 검정색 화면이 뜬다? -> 일단 비동기로 파일 업로드하도록 코드 변경
  1. /boards/video 요청이 옴
  2. 저장 위치를 먼저 반환
  3. 비동기적으로 파일 저장
 @PostMapping("/video")
    public ResponseEntity<String> videoUpload(@ModelAttribute BoardVideoDTO boardVideoDTO) {
        if (!boardVideoDTO.getVideo().isEmpty() && boardVideoDTO.getVideo() != null) {
            String storeFileName = videoStore.createStoreFileName(boardVideoDTO.getVideo().getOriginalFilename());

            log.info("----------uploadFile----------start {} {}", LocalDateTime.now(),Thread.currentThread().getName());
            videoStore.uploadFile(boardVideoDTO.getVideo(),storeFileName);
            log.info("----------UploadFile----------returned {} {}", LocalDateTime.now(),Thread.currentThread().getName());

            return ResponseEntity.ok(storeFileName);

        }

        return ResponseEntity.badRequest()
                .body("잘못된 비디오 업로드 요청입니다.");
    }
    @Override
    @Async("threadPoolTaskExecutor")
    public void uploadFile(MultipartFile multipartFile, String storeFileName) {

        try {
            log.info("Started uploading file at {} {}", LocalDateTime.now(),Thread.currentThread().getName());
            multipartFile.transferTo(new File(getFullPath(storeFileName)));
            log.info("Ended uploading file at {} {}", LocalDateTime.now(),Thread.currentThread().getName());

        } catch (IOException e) {
            log.warn("업로드 폴더 생성 실패 {}", e.getMessage());
        }
    }

2023년 4월 7일

  • FileStore를 구현하는 두 개의 class 를 각 각 component로 등록하는 방법?
  1. @Qualifier 어노테이션을 사용하여 각각의 빈을 구분가능
public interface MyInterface {
    void doSomething();
}

@Component
@Qualifier("beanA")
public class MyBeanA implements MyInterface {
    public void doSomething() {
        // ...
    }
}

@Component
@Qualifier("beanB")
public class MyBeanB implements MyInterface {
    public void doSomething() {
   
        // ...
    }
}

@Service
public class MyService {

    @Autowired
    @Qualifier("beanA")
    private MyInterface beanA;

    @Autowired
    @Qualifier("beanB")
    private MyInterface beanB;

    // ...
}
  1. @Primary 어노테이션 사용하기
    @Primary 어노테이션을 사용하면 같은 타입의 빈이 여러 개 등록되어 있을 때, 우선적으로 주입할 빈을 선택할 수 있습니다.
@Component
@Primary
public class MyBeanA implements MyInterface {
    public void doSomething() {
        // ...
    }
}

@Component
public class MyBeanB implements MyInterface {
    public void doSomething() {
        // ...
    }
}

@Service
public class MyService {

    @Autowired
    private MyInterface myBean;

    // ...
}

두 가지 방법을 계속해서 적용해보았지만 에러가 해결 안됨.
UnsatisfiedDependencyException

에러 메시지를 봤을 때 VideoStore 빈의 의존성 주입이 실패했으므로,
1. VideoStore 빈의 설정이 올바른지 확인해 봐야함 -> 잘 되어 있음.

  1. VideoStore 빈이 의존하는 다른 빈이 존재하는지 -> NOPE

  2. FileStore 인터페이스를 정확하게 구현하고 있는지..? 아 아니네,,, 역시나.... 여기서 문제 였음.

  • BoadCreateDto 수정 BoardUpdateDto 수정
    videoUrl 추가

insert는 4번 delete는2번
insert할땐 boardmemberlike에 있는지 조회하고 member, board 조회하고 insert쿼리 -> 4번
delete할땐 boaedmemberlike 조회하고 삭제쿼리 -> 2번

status 추가하면
최초 boardmemberlike에 추가할 때만 4번 쿼리 나가고
이후에는 조회와 status를 update하는 쿼리만 나간다.
이렇게 해서 like를 계속 눌렀을 때 문제를 어느정도 해소.
-> 애초에 like요청을 1분에 몇번만 날릴 수 있도록 하는 게 맞을 듯

enum LikeType

public enum LikeType {
    LIKE,UNLIKE
}
  • filterByMember , filterByQuestion : board를 각각 member, question으로 필터링 . return은 BoardListDto : new List<BoardDto>
/**
* BoardDTO
*/
	private Long id;
    private Long questionId;
    private String questionContent;
    private Long memberId;
    private String memberNickname;
    private String profileImageUrl;
    private String content;
    private String videoUrl;
    private int likeCount;
    private int commentCount;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;

board와 member, question은 ManyToOne 관계 -> fetch join

like,comment는 OneToMany -> batchsize 조절해서 in 으로 batch로 가져 올 수 있도록함.

  • cascade 설정

2023년 4월 6일

1.예외처리

2.api 변경: member fatch -> 로그인 아이디는 뺴놓기

3.게시글 업로드/수정, 회원가입/회원정보수정에서 영상이나 이미지 업로드하는거를 따로 api를 파서 업로드하면 저장된 주소를 돌려주고, 게시글,회원 post/put할때 요 경로 담아서 요청하는 방향으로

by impala

4.1+n쿼리 문제

2023년 4월 4일

  • MemberController , MemberService 개발
    MemberService-> 멀티파트로 이미지 파일 저장
  1. 적절한 Dto 설계에 대해 공부

  2. 프로필 이미지는 s3에 저장할 예정
    -> 일단 지금 당장은 s3를 사용하지 않기 때문에
    FileStore 인터페이스 만들어서 나중에 구현할 수 있도록, 지금은 ImgStoreMemory 구현 객체로 개발 진행.

  3. TestCode를 작성하면서 UnexpectedRollbackException 발생
    https://techblog.woowahan.com/2606/
    https://skyblue300a.tistory.com/15

2023년 4월 3일

  • api 수정
    프로필 이미지, 동영상 업로드 하는 url을 각각 따로 팠는데, update하는 url로 통합
  • dto 추가
  • data jpa 기반으로 기본 repository 생성
  • api 문서 바탕으로 기본 controller 생성
  • putMapping 이냐 patchMapping 이냐?
    update할 때 두가지 방식을 고민함, 원래는 patch를 사용할려고 했으나 그렇게 되면 service단에서 null인지 아닌지 검사하는 조건문이 많이 사용되고 코드가 더러워질 것이라고 판단. -> putMapping으로 가자
    영한님 왈

2023년 4월 2일

spring data jpa 정리

2023년 4월 1일

    1. InitDb() 코드 작성.
      -> 개발 초기에 개발할 때 db에 어느정도 데이터가 있으면 좋겠다고 판단.
      -> db 스키마에 맞게 데이터를 db에 넣을 수 있도록 코드 작성
      -> 반복되는 코드는 최대한 함수화 함.

+) 기능 설계할 때 MEMBER가 여러 TAG를 적용할 수 있도록 할지에 대한 이야기가 부족했던 것 같음 -> 팀원들과 이야기 해본 결과 여러 TAG 적용할 수 있도록 함.

    1. Spring Secure & JWT 에 대한 강의 및 자료 조사
      -> 생각보다 해야할 것이 많다고 느꼈음. 이제 곧 해야 하는 유저 로그인 부분인데, 지금부터 JWT를 적용해서 코드를 작성해야 하나 싶음.
      -> 어느정도 개발이 진행되고 적용해도 괜찮을 것 같음

3월 마지막 주

파일 업로드를 어떻게 처리해야 할까?
아무래도 동영상을 업로드해야하는데 네트워크 사용량이나 비정상적인 요청들을 고려하지 않을 수가 없음

  • http이용한 mutipart/form-data
  • http기반으로 하는 오픈 소프 tus 프로토콜
  • 서버리스를 이용하여 Amazon S3에 직접 파일 업로드 하기

일단 우리 서비스는 동영상 크기가 커봤자 1GB 안 쪽일 것이라고 판단. 1개의 질문에 대한 면접 영상은 길어봤자 2분 정도일 것이고 4K - 60fps 라도 800MB일 것임.

질문

  • 네트워크에 어떻게 파일이 전달이 되는 건지 , multipart로 전달시 여러 패킷으로 ? 전달 될 텐데 inputstream 사용하면 모든 데이터가 전달될 때까지 기다린 다음 저장하는 건가?
  • 동시에 많은 업로드 요청이 오면? -> 일단 WAS에서 정해진 쓰레드 풀만큼 요청을 받을텐데, 그러다 메모리가 꽉 차서 죽으면 어떻하지? 조금 더 네트워크에서 서버에 저장되는 과정을 찾아볼 필요가 있음.

많은 사용자가 갑자기 많이 요청을 보내면?
-> 직접 여러개 브라우저 켜서 보내봤다..
-> 괜찮은듯, 스레드 풀안에서 하니까?

멀티파트로 사이즈가 큰 데이터 업로드 시 메모리 오류가 안나는 이유는? InputStream 이 memory에 모든 데이터를 올려 놓은 다음에 IO하는 것이 아니라 버퍼링 해서 사용하는 듯 -> 실제 확인 결과 disk,cpu 사용량 거의 100%까지 증가하나 메모리는 크게 변동 사항 없음. 네트웤 사용량은 당연하게 증가

https://pwdd.github.io/post/improving-memory-usage-of-a-java-server

https://www.baeldung.com/java-read-lines-large-file

2023년 3월 24일

  • deep fake 모델 간단하게 적용해서 성능 테스트 및 실제로 서비스 가능할지에 대해 논의함

MobileFaceSwap: A Lightweight Framework for Video Face Swapping (AAAI 2022)
해당 논문에서 제시하는 방식으로 deep fake 적용해봄
-> 22초 동영상 처리하는데 GPU 없이 평균적으로 1분 20초 정도 걸림
-> GPU 이용하면 훨씬 단축 할 수 있을 것 같음
-> 적용 결과 나쁘지 않은 결과. 하지만 실제로 서비스하기엔 2% 부족함.

2023년 3월 23일

  • 본격적으로 요구사항 바탕으로 DB 및 API 설계

  • DB에서 태그 TABLE을 어떻게 구성해야할지 고민을 많이함.
    우리 서비스 같은 경우는 일단 인스타 태그와는 달리 계층화된 태그이기 때문에 이런 경우에는 어떻게 DB를 구성해야할지 고민을 많이 함.
    -> 네이버 쇼핑에서는 태그를 어떻게 다는지 참고함. -> 네이버 쇼핑 태그는 각 계층 태그가 의존적이지 않아서 우리 서비스 태그와는 조금 결이 다르다고 판단.
    -> 다른 테이블에서 태그를 FK로 가지고 있는 경우가 많아서 조회 방식 또한 생각을 안 할 수가 없었음

첫 번째 방식
대TAG - 중TAG - 소TAG 이런 식으로 TAG TABLE을 3개 만들어서 하는 방안
-> 하지만 이 방식은 조회할 때 DB를 3개 DB를 조인해야 하고 ,확장성이 부족하다고 판단함. 예를 들어. TAG 분류가 소 TAG 말고 그 밑에 더 필요하다면?

선택한 방식
1개의 TAG 테이블을 사용하고 TAG_ID, PARENT_TAG_ID를 두어 내 부모 TAG정보를 함께 저장하는 방식을 사용.
-> STACKOVERFLOW나 다른 개발자 커뮤니티에서 계층 태그를 설계할 때 PARENT_TAG_ID를 둔다고 함. 우리 서비스랑도 잘 맞아서 이 방식을 채택함.

0개의 댓글

관련 채용 정보