ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenVidu 공식문서로 시작해보기
    프로젝트/WebRTC 화상통화 프로젝트 2022. 7. 9. 15:43
    728x90

    OpenVidu의 공식문서를 기반으로 OpenVidu를 시작해 보려고 합니다.

    OpenVidu 공식문서


    1단계 선택하기(OpenVidu vs  Kurento)

    OpenVidu라는 쿠렌토를 높은 레벨로 추상화시켜 사용하기 쉽게 제공하는 프레임워크가 있습니다.

    쿠렌토를 사용하면 더 많은 기능들을 활용할 수 있지만 복잡도가 증가하게 됩니다.

    하지만 간단하게 적용하기 위해서는 OpenVidu 또한 좋은 선택이 될 수 있습니다.

     

    쿠렌토의 공식문서에서도 Warning이라는 메시지로 OpenVidu가 더 추상화되고 사용하기 쉽다고 명시되어 있습니다.

    쿠렌토 공식문서에서 소개하는 OpenVidu

     

    OpenVidu란?

    OpenVidu는 Kurento를 기반으로 하는 프레임워크입니다.

     

    OpenVidu를 사용하는 애플리케이션 개발자는 일반적인 WebRTC 통신의 일부를 구성하는 모든 저수준 기술과 프로토콜에 대해 걱정할 필요가 없습니다. 

    이 프로젝트의 주요 목표는 더 간단한 API를 제공하는 것입니다. 

    OpenVidu는 클라이언트 측 라이브러리를 포함하고 미디어 흐름을 처리하기 위해 OpenVidu Server를 사용하면 완전한 기능을 갖춘 WebRTC 지원 애플리케이션을 갖게 됩니다.

     

    고급 요구 사항 또는 미디어 처리 파이프라인의 보다 다양한 관리가 필요한 응용 프로그램의 경우 Kurento는 여전히 최고의 솔루션입니다. 그러나 OpenVidu에서 다루는 단순화된 사용 사례 중 하나와 일치하는 서비스를 구축하려는 경우 해당 경로를 사용하는 것이 더 쉽고 저렴할 수 있으므로 확인하는 것이 좋습니다.

     

    OpenVidu의 특징

    1. 일대일, 일대다, 다대다 화상회의

    2. Apache License v2의 오픈소스(아파치 라이선스에 따르면 누구든 자유롭게 아파치 소프트웨어를 다운 받아 부분 혹은 전체를 개인적 혹은 상업적 목적으로 이용할 수 있음)

    3. Chorm, FireFox, Safari, Android, IOS 등 환경을 지원

    4. 사용하기 편리하다.

    5. 배포하기 편리하다.

    6. 튜토리얼/데모가 제공된다.

    7. 암호화가 되어 보안성이 있다.

    8. Javascript, TypeScript, React, Vue 등등 다양한 프론트 기술과 호환된다.

    9. Java, Node 등의 다양한 백엔드 기술과 호환되며 REST API를 제공한다.

    10. 사전 정의된 역할로 비디오를 구독, 게시 또는 중재할 수 있는 사용자를 지정할 수 있습니다.

    11. 몇줄의 코드로 채팅을 구현할 수 있습니다.

    12. 화상 통화를 녹화할 수 있습니다.

    13. 화면 공유 기능을 제공합니다.

    14. 오디오 및 비디오 필터를 적용할 수 있습니다. (크로마키 설정, 목소리 증폭)

    15. 감시카메라 기능을 제공합니다. (비디오 영역에서 움직임이 감지되면 알림을 받을 수 있음/ IP 카메라가 장착된 드론으로부터 영상을 수신하는 애플리케이션)

     

    OpenVidu 아키텍쳐

     

    OpenVidu Brower

    화상 통화 생성, 사용자 참여, 비디오 및 오디오 송수신 등을 수행할 수 있습니다.

    모든 작업은 브라우저를 통해 관리됩니다.

     

    OpenVidu Server

    Brower에서 작업을 수신하고 화상 통화를 설정하고 관리하는데 필요한 모든 작업을 수행합니다.

    명시적으로 사용할 필요는 없습니다.

     


    2단계 시작하기

    단계별로 다음과 같이 추천됩니다.

    1. OpenViodu Hello World 튜토리얼

    2. 클라이언트 측 OpenVidu 튜토리얼

    3. 클라이언트 측 + 서버 측 튜토리얼

    4. 앱을 배포하고 실제로 동작하는 것 확인 

    1. OpenVidu Hello World 튜토리얼

    OpenVidue Hello World 튜토리얼 공식문서

     

    우선 docker와 npm(Node.js Package Manager) 이 설치되어 있으며 git을 다룰 수 있어야 합니다.

    docker -v
    출력 : Docker version 20.10.16, build aa7e414
    
    npm -v
    출력 : 8.5.5
    
    git clone https://github.com/OpenVidu/openvidu-tutorials.git
    출력 : 'git'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는
    배치 파일이 아닙니다.
    
    소스트리를 통해 클론받았습니다. 
    또는 git repo에서 직접 다운받아도 됩니다.
    
    경로는 다음과 같습니다 
    C:\Users\babab\openvidu-tutorials
    
    npm install -g http-server
    g옵션은 global의 약자로 해당 패키지를 전역적으로 설치한다는 의미입니다.
    http-server를 설치합니다.
    
    http-server openvidu-tutorials/openvidu-webcomponent/web
    튜토리얼을 실행합니다.

     

     

    OpenVidu Server는 개발 머신에서 실행 중이어야 합니다.

    이때 가장 쉬운 방법으로 Docker 컨테이너를 실행하면 됩니다.

     

    docker run -p 4443:4443 --rm -e OPENVIDU_SECRET=MY_SECRET openvidu/openvidu-server-kms:2.22.0

    위의 명령어를 실행하면 최종적으로 다음과 같은 출력을 볼 수 있습니다.

    이때 주의할 점은 https로 접속해줘야 합니다.

     

    https://localhost:4443에 접속하게 되면 다음과 같은 화면을 볼 수 있습니다.

    이제 localhost:8080에 접속하게 되면 여러 명의 사용자가 세션에 참여할 수 있게 됩니다.

    이름 설정 및 디바이스 설정 후 참여

     

    여러 명의 사용자가 참여할 수 있는 모습 

    이렇게 되면 튜토리얼은 끝나게 됩니다.


    튜토리얼 1 코드 이해하기

    간단하게 4개의 파일로 구성되어 있습니다.

     

    openvidu-webcomponent-{VERSION}.js

    자바 스크립트 파일로 조작할 필요가 없습니다.

     

    openvidu-webcomponent-{VERSION}.css

    css 관련 파일로 조작할 필요가 없습니다.

     

    app.js

    샘플 애플리케이션의 기본 JavaScript 파일입니다.

    모든 이벤트에 대한 요소는 해당 문서에서 볼 수 있습니다.

    처리할 수 있는 여러 이벤트를 제공합니다.

     

    문서에서 원하는 이벤트 리스너들을 다음과 같이 사용할 수 있습니다.

    $(document).ready(() => {
        var webComponent = document.querySelector('openvidu-webcomponent');
    
        webComponent.addEventListener('onSessionCreated', (event) => {
             var session = event.detail;
         });
        webComponent.addEventListener('onJoinButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarLeaveButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarCameraButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarMicrophoneButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarScreenshareButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarParticipantsPanelButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarChatPanelButtonClicked', (event) => {});
        webComponent.addEventListener('onToolbarFullscreenButtonClicked', (event) => {});
        webComponent.addEventListener('onParticipantCreated', (event) => {});
    });


    joinSession 메서드는 webapp 조인 버튼을 클릭한 후 호출됩니다.

    - 회의에서 사용자가 가질 닉네임과 함께 양식 입력 값을 가져옵니다.

    - OpenVidu Server에서 두 개의 토큰을 가져옵니다.

    async function joinSession() {
        //Getting form inputvalue
        var sessionName = document.getElementById('sessionName').value;
        var participantName = document.getElementById('user').value;
    
        // Requesting tokens
        var tokens = {webcam: await getToken(sessionName), screen: await getToken(sessionName)};
    
        //Getting the webcomponent element
        var webComponent = document.querySelector('openvidu-webcomponent');
    
        hideForm();
    
        // Displaying webcomponent
        webComponent.style.display = 'block';
    
        // Setting up our name and tokens
        webComponent.participantName = participantName;
        webComponent.tokens = tokens;
    }

     

    OpenVidu 서버에서 토큰을 받아오는 과정

    애플리케이션을 개발하는 단계에서는 해당 프로세스가 REST API를 통해 OpenVidu Java Client 또는 OpenVidu Node Client에서 이루어져야 합니다.

    튜토리얼에서는 Server가 존재하지 않기 때문에 JavaScript 코드로 POST 작업을 수행합니다.

    getToken(sessionName).then((token) => {
        // Send the 'token' to OpenVidu web component
    });

     

     

     

    index.html

    애플리케이션의 HTML 코드입니다.

    헤더 부분에서는 app.js와 openvidu-webComponent 파일들을 참조합니다.

    <head>
    
        <!--... other imports ...-->
    
        <script src="app.js"></script>
        <script src='openvidu-webcomponent-{VERSION}.js'></script>
        <link rel="stylesheet" href="openvidu-webcomponent-{VERSION}.css">
    </head>

    바디 부분에서는 비디오 세션과 OpenVidu 웹 구성 요소에 연결하기 위한 형식이 있으며 숨겨진 채로 시작됩니다.

    <body>
    
        <!-- Form to connect to a video-session -->
        <div id="main" style="text-align: center;">
            <h1>Join a video session</h1>
            <form onsubmit="joinSession(); return false" style="padding: 80px; margin: auto">
                <p>
                    <label>Session:</label>
                    <input type="text" id="sessionName" value="SessionA" required>
                </p>
                <p>
                    <label>User:</label>
                    <input type="text" id="user" value="User1" required>
                </p>
                <p>
                    <input type="submit" value="JOIN">
                </p>
            </form>
        </div>
    
        <!-- OpenVidu Web Component -->
        <openvidu-webcomponent style="display: none;"></openvidu-webcomponent>
    
    </body>

     

    이외에도 버튼 커스터마이징 색 변경 등을 수행할 수 있습니다.

     

    2. 클라이언트 측 OpenVidu 튜토리얼

    React 문서 링크

     

    입력할 명령어들

    git clone https://github.com/OpenVidu/openvidu-tutorials.git -b v2.22.0
    
    cd openvidu-tutorials/openvidu-library-react
    npm install
    npm start
    
    docker run -p 4443:4443 --rm -e OPENVIDU_SECRET=MY_SECRET openvidu/openvidu-server-kms:2.22.0

     

     

    https://localhost:4443

    localhost:3000

     

     

    3. 클라이언트 측 + 서버 측 튜토리얼

    공식 문서 링크

     

    OpenVidu-java-clinet를 사용하여 OpenVidu 서버에 연결합니다.

    MVC 패턴으로 구성된 환경입니다.

     

    4가지로 구성되어 있습니다.

    openvidu-brower : Javascript라이브러리를 활용하여 고객과 직접 화상통화를 관리

    openvidu-java-client : Java용 서버 SDK로 REST API로 사용됩니다.

    openvidu-server : 미디어 서버를 제어하는 애플리케이션

    Kurento Media Server : 미디어 전송의 저수준 작업을 처리합니다.

     

    mvn, docker, git 환경이 필요합니다.

    mvn -v
    
    출력
    'mvn'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는
    배치 파일이 아닙니다.

     

    mvn을 설치하겠습니다.

    https://maven.apache.org/download.cgi

     

    Maven – Download Apache Maven

    Downloading Apache Maven 3.8.6 Apache Maven 3.8.6 is the latest release and recommended version for all users. The currently selected download mirror is https://dlcdn.apache.org/. If you encounter a problem with this mirror, please select another mirror. I

    maven.apache.org

    Files -> Binary zip archive -> apache-maven-3.8.6-bin.zip을 다운로드합니다.

     

    적당한 곳에 압축을 해제합니다.

    어느 경로에서든 명령어를 실행할 수 있도록 추가 설정이 필요합니다.

    Maven 프로그램 실행 파일은 설치된 폴더에 있는 bin에 있다. 이 폴더의 경로를 path 변수에 추가한다.

     

    윈도에서 시스템 환경 변수 편집으로 이동합니다.

    환경 변수 -> User에 대한 사용자 변수 -> Path (편집) -> 새로 만들기 -> maven bin 경로 추가

    예시) C:\Users\babab\Downloads\apache-maven-3.8.6-bin\apache-maven-3.8.6\bin

     

    mvn -v 명령어 실행 후

     

    git clone 받기

    git clone https://github.com/OpenVidu/openvidu-tutorials.git -b v2.22.0

     

    튜토리얼 실행

    cd openvidu-tutorials/openvidu-mvc-java
    mvn package exec:java

    한 1분 정도 명령들이 수행되며 스프링 부트가 뜨게 됩니다.

     

    도커로 openVidu server 실행

     

    docker run -p 4443:4443 --rm -e OPENVIDU_SECRET=MY_SECRET openvidu/openvidu-server-kms:2.22.0

     

    https://localhost:4443 접속

    https://localhost:5000 접속

    User , Pass에 아래의 정보로 로그인합니다.

     

    Publisher와 Subscriber라는 개념이 있으며 Publisher는 영상을 송출할 수 있으며 Subscriber는 영상을 송출하지 못하고 보기만 할 수 있습니다.

     

     

    코드 이해하기

    Thymeleaf라는 템플릿 엔진을 활용하여 MVC 접근 방식으로 HTML 파일을 제공하는 JS/ HTML / CSS로 구성된 Java Spring의 웹 애플리케이션입니다.

     

    사용자를 식별할 수 있으며 역할이 부여되며 영ㄱ할에 따라 원하는 작업을 수행할 수 있습니다.

     

    Backend: Spring Boot로 구성된 Java 앱

    App.java : 앱 진입점

    LoginController.java : 로그인과 로그아웃작업을 수행하는 컨트롤러

    SessionController.java : OpenVidu 토큰을 받는 컨트롤러 활성화된 회의와 이에 연결된 사용자를 저장합니다.

     

    FrontEnd : 순수한 JS/HTML/CSS로 이루어 졌으면 정적파일로 제공됨

    index.html : 로그인폼 제공

    dashboard.html : 화상회의에 들어가기 위한 템플릿 제공

    session.html : 화상회의 화면 제공

     

    FrontEnd 정적 파일

    openvidu-browser-VERSION.js : openvidu 브라우저 라이브러리, 조작할 필요 없음

    style.css : css 제공

     

    코드 설명을 위한 시나리오 

    1. 사용자가 앱에 로그인하고 화상 통화 TUTORIAL에 연결하여 웹캠을 게시

    2. 두 번째 사용자는 동일한 화상 통화에 연결하고 자체 웹캠을 게시

    3. 이후 둘다 전화를 끊음

     

    사용자가 앱에 로그인하면 login form이 제공됩니다.

    로그인을 클릭하면 POST 작업이 수행되며 사용자의 이름과 비밀번호가 전달됩니다.

    <form class="form-group jumbotron" action="/dashboard" method="post">
        <p>
            <label>User</label>
            <input class="form-control" type="text" name="user" required="true"></input>
        </p>
        <p>
            <label>Pass</label>
            <input class="form-control" type="password" name="pass" required="true"></input>
        </p>
        <p class="text-center">
            <button class="btn btn-lg btn-info" type="submit">Log in</button>
        </p>
    </form>

    LoginController는 사용자가 로그인되었는지 확인하고 로그인 되었다면 대시보드화면을 반환하고 그렇지 않으면 홈화면으로 redirect 시킵니다.

     

    또한 로그인한 사용자에 대해서 HttpSession을 설정합니다.

    @RequestMapping(value = "/dashboard", method = { RequestMethod.GET, RequestMethod.POST })
    public String login(@RequestParam(name = "user", required = false) String user,
                @RequestParam(name = "pass", required = false) String pass,
                Model model, HttpSession httpSession) {
    
        // 이미 로그인된 사용자 인지 확인
        String userName = (String) httpSession.getAttribute("loggedUser");
        if (userName != null) {
            // 이미 로그인된 사용자면 dashboard로 이동
            model.addAttribute("username", userName);
            return "dashboard";
        }
    
        //이미 로그인되지 않았다면 사용자가 유효한지 검사
        if (login(user, pass)) { // Correct user-pass
    
            //세션 부여하고 사용자 이름 설정
            httpSession.setAttribute("loggedUser", user);
            model.addAttribute("username", user);
    
            //dashboard.html으로 이동
            return "dashboard";
    
        } else { // 잘못된 유저(DB에 없는 유저)
            // session을 만료시키고 home 화면으로 redirect
            httpSession.invalidate();
            return "redirect:/";
        }
    }

     

    Aclice라는 사용자가 Tutorial이라는 화상회의에 접속합니다.

    Join을 누르는 순간 /session으로 이동합니다.

    <form class="form-group" action="/session" method="post">
        <p>
            <label>Participant</label>
            <input class="form-control" type="text" name="data" required="true"></input>
        </p>
        <p>
            <label>Session</label>
            <input class="form-control" type="text" name="session-name" required="true"></input>
        </p>
        <p class="text-center">
            <button class="btn btn-lg btn-success" type="submit">Join!</button>
        </p>
    </form>

    SessionController가 세션 경로에서 요청을 받으면 상황이 흥미로워집니다.

    이 클래스의 주요 속성은 다음과 같습니다.

    // OpenVidu object as entrypoint of the SDK
    private OpenVidu openVidu;
    
    // 세션이름과 세션객체 Map
    private Map<String, Session> mapSessions = new ConcurrentHashMap<>();
    // 세션이름과 토큰 Map (내부의 Map은 토큰과 역할)
    private Map<String, Map<String, OpenViduRole>> mapSessionNamesTokens = new ConcurrentHashMap<>();
    
    // OpenVidu 서버의 URL
    private String OPENVIDU_URL;
    
    // OpenvVidu server 암호화를 위한 키
    private String SECRET;

     

    Controller는 사용자가 설정한 별명과 sessionName("TUTORIAL")을 수신받습니다.

    connectionProperties에서 필요한 매개변수들을 세팅합니다.

    @RequestMapping(value = "/session", method = RequestMethod.POST)
    public String joinSession(@RequestParam(name = "data") String clientData,
                @RequestParam(name = "session-name") String sessionName,
                Model model, HttpSession httpSession) {
    
        // user가 로그인되었는지 확인
    
        // 사용자의 역할 확인
        OpenViduRole role = LoginController.users.get(httpSession.getAttribute("loggedUser")).role;
    
    	    
        // 사용자가 화상 통화에 연결할 때 다른 사용자에게 전달할 선택적 데이터
        // 이 경우에는 HttpSession객체에 저장된 JSON 전달
        String serverData = "{\"serverData\": \"" + httpSession.getAttribute("loggedUser") + "\"}";
       
        // serverDatd와 role을 connectionProperties 객체에 세팅
        ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC).data(serverData).role(role).build();

    이후에 "TUTORIAL"이라는 세션이 존재하는지 확인

    if (this.mapSessions.get(sessionName) != null) { ...

    첫번째 사용자이기 때문에 null이 반환됩니다.

    else {
        // 새로운 새션
        System.out.println("New session " + sessionName);
        try {
            
            //새로운 OpenVidu Session 만들기
            Session session = this.openVidu.createSession();        
            //이미 만들어진 connectionProperties사용하여 새로운 Connection을 만들기
            String token = this.mapSessions.get(sessionName).createConnection(connectionProperties).getToken();
            
            // 세션과 토큰을 mapSession에 저장
            this.mapSessions.put(sessionName, session);
            this.mapSessionNamesTokens.put(sessionName, new ConcurrentHashMap<>());
            this.mapSessionNamesTokens.get(sessionName).put(token, role);
    
            // 템플릿에 필요한 모든 속성들 추가 (템플릿엔진에 전달하기위한 값 세팅)
            model.addAttribute("sessionName", sessionName);
            model.addAttribute("token", token);
            model.addAttribute("nickName", clientData);
            model.addAttribute("userName", httpSession.getAttribute("loggedUser"));
    
            // session.html 반환
            return "session";
    
        } catch (Exception e) {
            // 에러난 경우에는 dashboard.html 반환
            model.addAttribute("username", httpSession.getAttribute("loggedUser"));
            return "dashboard";
        }
    }

    session.html의 Javascript 코드가 새로운 새션을 만들고 연결합니다.

    // Thymeleaf 스타일로 Controller에게 받은 속성들 세팅
    var sessionName = [[${ sessionName }]];
    var token = [[${ token }]];
    var nickName = [[${ nickName }]];
    var userName = [[${ userName }]];
    
    // --- 1) OpenVidu 객체 받기 ---
    
    OV = new OpenVidu();
    
    // --- 2) 세션 초기화
    
    session = OV.initSession();
    
    // --- 3) 세션에서 이벤트가 발생할 때의 작업 지정 ---
    
    // 새로운 스트림이 수신될 때마다
    session.on('streamCreated', (event) => {
    
        // 스트림을 구독하여 수신    
        // HTML 비디오는 'video-container' ID를 가진 요소에 추가됨
        var subscriber = session.subscribe(event.stream, 'video-container');
    
        // HTML 비디오가 DOM에 추가되었을 때
        subscriber.on('videoElementCreated', (event) => {
    
            // 동영상과 사용자 이름과 닉네임에 대한 새 HTML 요소를 추가합니다.
            appendUserData(event.element, subscriber.stream.connection);
        });
    });
    
    // 모든 스트림이 destryoed 될때마다
    session.on('streamDestroyed', (event) => {
        // 사용자 이름과 닉네임이 있는 HTML 요소 삭제
        removeUserData(event.stream.connection);
    });
    
    // 모든 비동기 예외에서
    session.on('exception', (exception) => {
        console.warn(exception);
    });
    
    // --- 4)클라이언트에서 가져온 토큰과 추가 데이터를 전달하는 세션에 연결합니다.
    // 사용자가 서낵한 닉네임의 JSON
    
    session.connect(token, { clientData: nickName })
        .then(() => {
    
            // --- 5) 호출에 대한 페이지 레이아웃 설정
    
            $('#session-title').text(sessionName);
            $('#join').hide();
            $('#session').show();
    
    
            // PUBLISHER 역할인지 확인하고 송출합니다.
            // 만약 중간에 클라이언트가 PUBLISHER로 변경한 경우에도 OpenVidu 서버에서 PUBLISHER로 인식되지 않습니다.
            if (isPublisher()) {
    
                // --- 6) 사용자의 카메라 스트림 가져오기
    
                var publisher = OV.initPublisher('video-container', {
                    audioSource: undefined, // The source of audio. If undefined default microphone
                    videoSource: undefined, // The source of video. If undefined default webcam
                    publishAudio: true,     // Whether you want to start publishing with your audio unmuted or not
                    publishVideo: true,     // Whether you want to start publishing with your video enabled or not
                    resolution: '640x480',  // The resolution of your video
                    frameRate: 30,          // The frame rate of your video
                    insertMode: 'APPEND',   // How the video is inserted in the target element 'video-container'
                    mirror: false           // Whether to mirror your local video or not
                });
    
                // --- 7) publisher를 하는 도중 이벤트가 발생할 때 작업 지정
    
                // 비디오가 DOM에 추가되었을 때 
                publisher.on('videoElementCreated', (event) => {
                    // Init the main video with ours and append our data
                    var userData = {
                        nickName: nickName,
                        userName: userName
                    };
                    initMainVideo(event.element, userData);
                    appendUserData(event.element, userData);
                    $(event.element).prop('muted', true); // Mute local video
                });
    
    
                // --- 8) user의 Stream을 송출
    
                session.publish(publisher);
    
            } else {
                console.warn('You don\'t have permissions to publish');
                initMainVideoThumbnail(); // Show SUBSCRIBER message in main video
            }
        })
        .catch(error => {
            console.warn('There was an error connecting to the session:', error.code, error.message);
        });

    이제 사용자는 자신의 비디오를 볼 수 있습니다.

     

    두번째 사용자가 통화에 참가하는 경우에는 위의 분기에서 "TUTORIAL"이 존재하는 분기로 빠지게 됩니다.

    if (this.mapSessions.get(sessionName) != null) {
        // 세션이 이미 존재
        System.out.println("Existing session " + sessionName);
        try {
    
            //connectionProperties으로 새로운 Connection 생성
            String token = this.mapSessions.get(sessionName).createConnection(connectionProperties).getToken();
    
            //새로운 토큰을 저장하여 collection 업데이트
            this.mapSessionNamesTokens.get(sessionName).put(token, role);
    
            // 템플릿에 필요한 속성을 지정
            model.addAttribute("sessionName", sessionName);
            model.addAttribute("token", token);
            model.addAttribute("nickName", clientData);
            model.addAttribute("userName", httpSession.getAttribute("loggedUser"));
    
            // session.html 페이지 반환
            return "session";
    
        } catch (Exception e) {
            // 에러가 발생한 경우 dashboard.html 페이지 반환
            model.addAttribute("username", httpSession.getAttribute("loggedUser"));
            return "dashboard";
        }
    }

     

    사용자가 연결을 끊는 경우

    session.disconnect()가 호출되며 백엔드에 특정 사용자가 세션을 떠났다는 것을 알려줍니다.

    이외에도 특정 사용자가 세션을 떠나갈때 POST 작업을 호출합니다.

    <form action="/leave-session" method="post">
        <input type="hidden" name="session-name" th:value="${sessionName}"></input>
        <input type="hidden" name="token" th:value="${token}"></input>
        <button id="buttonLeaveSession" class="btn btn-large btn-danger" type="submit" onclick="leaveSession()">
            Leave session</button>
    </form>

     

    SessionController.java 에서 컬렉션을 업데이트합니다.

    @RequestMapping(value = "/leave-session", method = RequestMethod.POST)
    public String removeUser(@RequestParam(name = "session-name") String sessionName,
                @RequestParam(name = "token") String token,
                Model model, HttpSession httpSession) throws Exception {
        
        // 사용자가 로그인되었는지 확인
    
        // 아직 Session에 사용자가 남아있는 경우 ("TUTORIAL" in this case)
        if (this.mapSessions.get(sessionName) != null && this.mapSessionNamesTokens.get(sessionName) != null) {
    
            // 토큰이 유효한 경우
            if (this.mapSessionNamesTokens.get(sessionName).remove(token) != null) {
                // 사용자가 session에서 제거됨
                if (this.mapSessionNamesTokens.get(sessionName).isEmpty()) {
                    // 마지막 사용자가 떠나면 Session이 제거됨
                    this.mapSessions.remove(sessionName);
                }
                return "redirect:/dashboard";
    
            } else {
                // 토큰이 유효하지 않음
                System.out.println("Problems in the app server: the TOKEN wasn't valid");
                return "redirect:/dashboard";
            }
    
        } else {
            // Session이 존재하지 않는 경우
            System.out.println("Problems in the app server: the SESSION does not exist");
            return "redirect:/dashboard";
        }
    }

    마지막 사용자가 세션을 떠날 때 세션은 비어있게 되고 모든 세션객체와 그와 관련된 토큰은 무효화됩니다.

     

     

     

     

    출처

    https://doc-kurento.readthedocs.io/en/stable/user/quickstart.html

     

    Getting Started — Kurento 6.16.0 documentation

    » Getting Started Edit on GitHub <!-- "admonition" is the class of Warning messages with the current RTD theme. Obtained by directly checking the HTML sources of an already existing block. --> Warning Kurento is a low-level platform to create WebRTC appli

    doc-kurento.readthedocs.io

    https://docs.openvidu.io/en/2.22.0/

     

    OpenVidu Docs

    From here you can search these documents. Enter your search terms below.

    docs.openvidu.io

    https://araikuma.tistory.com/444

     

    [Maven] Maven 준비

    먼저 Maven을 설치하고, 실제로 Maven에서 어떻게 개발을 할것인지 나갈 것인지 그 기본 단계를 설명한다. JDK와 빌드 도구 Java 개발은, JDK라는 도구로 한다. 이것은 아마도 Java 입문서 등에서 먼저

    araikuma.tistory.com

     

    댓글

Designed by Tistory.