반응형
Viewset을 사용하면 관련된 view들을 하나의 클래스로 묶을 수 있다.

class UserViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving users.
    """
    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)
from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
위의 예시는 아래의 URL 패턴을 만든다
  • URL pattern: ^users/$ Name: 'user-list'
  • URL pattern: ^users/{pk}/$ Name: 'user-detail'
  • URL pattern: ^accounts/$ Name: 'account-list'
  • URL pattern: ^accounts/{pk}/$ Name: 'account-detail'

Viewset에서 사용하는 self.action은 router가 자동으로 변환한 것이다.
URL StyleHTTP MethodActionURL Name
{prefix}/GETlist{basename}-list
POSTcreate
{prefix}/{url_path}/GET, or as specified by `methods` argument`@action(detail=False)` decorated method{basename}-{url_name}
{prefix}/{lookup}/GETretrieve{basename}-detail
PUTupdate
PATCHpartial_update
DELETEdestroy
{prefix}/{lookup}/{url_path}/GET, or as specified by `methods` argument`@action(detail=True)` decorated method{basename}-{url_name}
위에 표는 URL Style + HTTP Method가 어떻게 Action으로 변환되는지를 보여준다.
만약 POST users/라고 쿼리를 보내면 {prefix}/ + POST로 action은 list가 된다.
만약 GET users/123라고 쿼리를 보내면 {prefix}/{lookup}/ + GET으로 action은 retrieve가 된다.

perform_create()는 create()가 호출된 과정에서 serializer를 사용하여 serializer.save()를 하기 위해 호출된다.
perform_create()와 create()를 구분해서 사용하는법
추가1
추가2

serializer.save()는 객체가 이미 존재하면 update를, 없다면 create를 해준다





반응형
블로그 이미지

개발자_무형

,
반응형
Django REST Framework의 ModelViewSet과 create() 관련 찾아보고 공부한 내용을 정리해보려고 한다.

기본적으로 ModelViewSet은 GenericAPIView라는 클래스를 상속받기 때문에 .list(), .create()  .list(), .create() 등을 기본으로 내장하고 있다. 따라서 이 중에서 기본 내장되어 있는 메소드 중 동작을 변경하고 싶은 것들만 overriding해서 수정하면 된다.

그리고 ModelViewSet은 GenericAPIView를 상속받고 있기 때문에 최소한 queryset와 serializer_class는 세팅해주어야 한다.

from rest_framework import status
from rest_framework.response import Response


def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

def perform_create(self, serializer):
    serializer.save()
위의 코드를 보면 이해가 조금 더 쉬울 것 같다. perform_create()은 create()의 동작 중 일부분을 overriding한다고 생각하면 되는데, serializer.save()가 호출될 때 perform_create()가 호출된다고 생각하면 된다. 위의 경우 명시적으로 perform_create()를 호출했지만, django에서는 개발자의 짐을 덜어주기위해 mixin으로 앞에서 설명한 list(), create()등을 제공하는 데, 이때 자동으로 save()대신 perform_create()를 호출하는 것이다. 

만약 perform_create()가 없었다면, create()의 전체적인 로직은 변경할 필요가 없어 작성하지는 않고 mixin이 기본 제공하는 메소드를 사용할 때,  save()가 될 때의 행동을 부분적으로 재정의를 하고 싶더라도 create()전체를 재작성해야될 것이다.



반응형
블로그 이미지

개발자_무형

,
반응형

Scope란 connection의 정보를 뜻한다. remote IP, username, lifetime of connection등의 정보를 가지고 있다. Application은 한번의 scope당 한번씩 instantiate된다. HTTP에서는 각 request마다, socket에서는 각 WebSocket connection마다이다.

Consumer

각각의 프로토콜은 각자 다른 event들이 발생하며 이 event들은 메소드로 표현된다. 개발자는 각각의 event들을 어떻게 처리할지 코드만 작성하면 Django의 Channel이 스케쥴링과 병렬적으로 실행시켜준다.

 

 

class LogConsumer(WebsocketConsumer): def connect(self, message): Log.objects.create( type="connected", client=self.scope["client"], )

Channel은 asynchronous event loop을 기반으로 돌아간다.  하지만 위처럼 코드를 작성하면 synchronous thread에서 실행이 된다. 따라서 위의 코드처럼 blocking operation도 문제없이 잘 작동한다.

class PingConsumer(AsyncConsumer): async def websocket_connect(self, message): await self.send({ "type": "websocket.accept", }) async def websocket_receive(self, message): await asyncio.sleep(1) await self.send({ "type": "websocket.send", "text": "pong", })

위처럼 작성하면 asynchronous하게 작동한다.

 

 

Cross-Process Communication

Application내에서 통신하는 것은 각 application바다 존재하는 application instance를 통해서 하면 되지만, application끼리 통신하는 것은 이야기가 달라진다. 데이터베이스 polling을 통해서 할 수도 있지만 Channels는 channel layer라는 개념을 도입했다. 각각의 application instance는 unique channel name을 가지고 있으며, group에 join할 수 있다.

 

# In a consumer self.channel_layer.send( "myproject.thumbnail_notifications", { "type": "thumbnail.generate", "id": 90902949, }, )

위의 코드처럼 다른 process에게 broadcasting해줄 수 있다.

 

 

 

반응형
블로그 이미지

개발자_무형

,
반응형

Consumer하는 일 중 몇가지:

    - 이벤트가 발생했을 때 사용할 함수를 작성하기만 하면 된다. event loop전체를 다 쓸 필요가 없다.

    - synchronous / asynchronous 코드를 작성하기만 하면 threading을 포함한 나머지를 다 처리해준다.

 

Consumer Events

from channels.consumer import SyncConsumer class EchoConsumer(SyncConsumer): def websocket_connect(self, event): self.send({ "type": "websocket.accept", }) def websocket_receive(self, event): self.send({ "type": "websocket.send", "text": event["text"], })

 

Consumer는 type과 매칭되는 몇가지의 메소드들로 구성되어 있다. type에서 .를 _로 바꾼것이 메소드 이름이다. 즉 위의 예시에서

"type": "websocket.accpet" 는 websocket_accept()를 호출하고

"type": "websocket.send"는 websocket_send()를 호출한다.

 

그렇다면 위의 예시에서 websocket_receive(self, event)는 event["text"]를 접근하고 있는데 websocket_receive의 event안에 text가 있다는 것은 어떻게 알았을까? 이는 ASGI에서 정해진 규약을 따른다.

 

AsyncConsumer vs SyncConsumer

AsyncConsumer와 SyncConsumer의 사용처에 대해서는 쉽게 정리하자면 asynchronous 코드들만 실행될 경우에는 AsyncConsumer를, ORM처럼 Synchronous 코드는 SyncConsumer에서 호출하도록 한다.

 

 

Closing Consumers

Socket이나 Connection이 끊기면 보통은 서버에 event(http.disconnect or websocket.disconnect)가 보내진다. disconnect에 관련된 작업을 마치면 channels.exceptions.StopConsumer를 발생시켜 ASGI application을 정상적으로 중지시켜야된다. 따로 중지시키지 않는다면, server는 timeout시간이 되면 자동종료시키고 warning을 띄운다.

 

 

Channel Layers

from channels.consumer import SyncConsumer class EchoConsumer(SyncConsumer): channel_layer_alias = "echo_alias"

위의 코드처럼 channel_layer_alias를 별도로 명시해주지 않는다면 Consumer는 default channel layer를 사용한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
블로그 이미지

개발자_무형

,
반응형

 

설치하는 과정을 편하게 Dockerfile로 만들었다.

 

기존에 다른사람이 올려놓은 Dockerfile은 최신 janus와 안맞아서 패키지들을 최신가이드에 맞게 바꿔주었다.
이미지 빌드와 실행은 repository의 readme에 나와있다.
https://github.com/cjsjyh/janus_server

 

=========================

 

Official Repository: https://github.com/meetecho/janus-gateway

 

ReadMe를 따라서 진행하다가 안되서 추가된 부분들이 있다.

 

aptitude install libmicrohttpd-dev libjansson-dev \ libssl-dev libsrtp-dev libsofia-sip-ua-dev libglib2.0-dev \ libopus-dev libogg-dev libcurl4-openssl-dev liblua5.3-dev \ libconfig-dev pkg-config gengetopt libtool automake

 

Readme에는 없지만 libnice를 설치하기 위해 추가로 패키지를 설치해야된다

brew install gtk-doc  // macOS
apt-get install gtk-doc-tools // Ubuntu

 

libnice 설치:

git clone https://gitlab.freedesktop.org/libnice/libnice
cd libnice
./autogen.sh
./configure --prefix=/usr
make && sudo make install

 

libsrtp 설치:
Readme에 써진대로 1.5.4를 설치하면 최신버전의 openssl을 지원하지 않아 ./configure --prefix=/usr --enable-openssl에서 에러가 난다. 아래처럼 버전을 작성일 기준 가장 최신버전인 2.3.0버전으로 바꿔주었다.

wget https://github.com/cisco/libsrtp/archive/v2.3.0.tar.gz
tar xfv v2.3.0.tar.gz
cd libsrtp-2.3.0
./configure --prefix=/usr --enable-openssl
make shared_library && sudo make install

저는 http를 사용하여 janus서버와 통신할 것이기 때문에 기타 연결방법을 위한 패키지 설치는 건너뛰도록 하겠습니다.

documentation 빌드를 위한 패키지 설치:

aptitude install graphviz

 

doxygen을 그냥 설치하면 가장 최신버전이 깔리는데 그럼 janus에서 에러를 낸다. 에러를 내지 않는 1.8.11버전으로 다운로드를 한다

wget https://svwh.dl.sourceforge.net/project/doxygen/rel-1.8.11/doxygen-1.8.11.src.tar.gz

 

실제 janus패키지 설치:

git clone https://github.com/meetecho/janus-gateway.git
cd janus-gateway
sh autogen.sh

./configure --prefix=/opt/janus
make
make install

make configs

 

websocket과 data channel은 사용할 수도 있을 것 같아서 제외한 나머지는 비활성화 시켰습니다.

./configure --disable-rabbitmq --disable-mqtt

 

--여기서부터 Dockerfile로 넘어가서 작업함--

반응형

'개발 > 프론트엔드' 카테고리의 다른 글

WebRTC 기본 개념 정리  (0) 2020.12.24
Janus screen sharing 만들기  (1) 2020.03.19
Intel Open WebRTC Toolkit 클라이언트 삽질기  (0) 2020.03.13
8. GraphQL Introspection  (0) 2019.12.26
7. GraphQL Subscription  (0) 2019.12.26
블로그 이미지

개발자_무형

,
반응형

Client코드를 작성하기 앞서, Intel에서 제공한 샘플코드를 참고하여 사용하는 법을 익히려고 합니다.

모든 코드는 아래의 참고자료의 owt-client-javascript repo를 기준으로 합니다

src/samples/conference/public/scripts/index.js를 보면 기본적인 conference를 생성/접속하는 법이 나와있는 것 같다.
134번째 줄부터 시작하는 window.onload에 createToken을 하고, 만들어진 tokenString을 callback함수에 넘겨 conference에 입장한다.

createToken()src/samples/conference/public/scripts/rest-sample.js에 있다. 이 부분은 자신의 필요에 맞게 바꾸면 될것 같다.

그리고 조금 더 내려가면 가장 중요한 conference.join(token).then( ....이 있는데 여기서 token이 어떤정보를 가지고 있어야되는지를 알아야한다. src/sdk/conference/client.js를 보면 ConferenceClient 클래스 안에 this.join이 있다.

Custom signaling

custom signaling을 사용하려면 conference = new Owt.Conference.ConferenceClient();로 ConferenceClient를 생성할 때 두번째 인자로 넣어주면된다. 이 객체는 .send(), .connect(), .disconnect()를 가지고 있어야하며 disconnect했을때와 참여자, 스트림 등이 바뀌었을때 처리할 수 있도록 disconnectdata 이벤트를 발생시켜야한다. 실제 스트림 등 데이터를 전달하고 싶으면 data 이벤트를 발생시켜 처리힌다. 그러면 ConferenceClient는 onSignalingMessage()를 호출해 처리한다.

new Owt.Conference.ConferenceClient(config, signalImp)

두번째인자는 앞에서 언급한대로 자신만의 signaling을 구현하고 싶을때 넘겨주고, config는 sdk > conference > client.js의 createPeerConnectionChannel()에서 new ConferencePeerConnectionChannel(config, signalingForChannel)에서 인자로 넘어간다. 그러므로 config의 host에는 media server로 연결되는 host가 있어야되는 것 같다.

conference.join(tokenString)

join을 살펴보면 처음에 tokenString을 Base64.decodeBase64로 복호화를 한다. 따라서 toikenString은 base64로 암호화되어있어야한다.
그리고 아래 나오는 코드를 보면 join에서 token.securetoken.host를 접근하는데 token.secure은 정의되지않아도 (token.secure === true)에 의해 false로 바뀌어 isSecure에 저장되므로 괜찮다. token.host는 http 프로토콜을 붙이지 않으면 isSecure를 검사해서 http나 https를 붙여주는데 만약 자신의 서버가 https://인데 token.secure를 true로 하지도 않고 host에도 붙이지 않으면 잘못된 host로 접근할 것이다.

signalingState는 READY, CONNECTING, CONNECTED가 있으며 접속하는 중이거나 이미 접속된 상태에서 join을 호출하면 더 이상 진행하지않고 종료한다. 아무와도 연결되지않은 READY상태라면 CONNECTING으로 바꾸고 계속 진행한다.

아직 이해되지 않는점:
conference.join(tokenString)을 호출하면 tokenString을 decode하고, token에서 host를 signaling.connect(host)로 넘겨준다. 그렇다면 coference.join(token)의 host는 signaling 서버의 url이라는 뜻인데.. 이전에 연결할때는 wss프로토콜을 사용하였었다. 그런데 conference.join에서는 wss가 아니라 https 혹은 http를 붙여서 보내주는데 음.. 뭔가 잘못이해한건가

참고자료:
https://software.intel.com/sites/products/documentation/webrtc/js/index.html

https://github.com/open-webrtc-toolkit

https://github.com/open-webrtc-toolkit/owt-client-javascript

반응형

'개발 > 프론트엔드' 카테고리의 다른 글

Janus screen sharing 만들기  (1) 2020.03.19
Janus media server 설치하기  (4) 2020.03.17
8. GraphQL Introspection  (0) 2019.12.26
7. GraphQL Subscription  (0) 2019.12.26
6. GraphQL Mutations  (0) 2019.12.26
블로그 이미지

개발자_무형

,
반응형

[...작성중...]

 

- 서론

 

- 설치하기

    - Visual Studio Code 설치하기

    - NodeJS 설치하기

 

- 기초 문법

    - 출력하기

    - 변수의 종류

    - 연산자

    - 제어문

        - if문

        - while문

        - for문

    - 함수

 

- 계산기 만들기

    - 출력하기

    - 변수 세팅하기

(세미콜론 찍기 / NodeJS란?)

    - 더하기

    - 빼기

    - 곱하기

    - 나누기(몫)

    - 나머지

 

- 주식게임 만들기 (React)

    - 레이아웃 만들기

    - 시간마다 변하는 가격만들기

    - 주식 사고 팔기

    - 현재 잔고 계산하기

 

- 크롤러 만들기 (NodeJS)

    - 패키지 설치하기

    - 긁어오기

 

- 블로그 만들기 (React + NodeJS)

    - 레이아웃 만들기

    - 글 보기

    - 글 작성하기

    - 글 삭제하기

    - 글 수정하기

반응형
블로그 이미지

개발자_무형

,
반응형

[...작성중...]

 

서론 -

 

필자는 컴퓨터공학과를 전공한 사람이지만 주변에 코딩을 아예 접해보지 못했지만 막연하게 시작하는것을 무서워하거나, 최근에는 대학들에서 코딩과목을

 

이 책은 프로그램에 대한 지식이 전무하신 분들을 위한 책입니다. 정확하고 많은 정보를 전달하려고 하기보다는 처음 코딩을 접하시는 분들이 재미있게 입문하실 수 있도록 기본을 이해할 수 있는 수준으로 풀어쓰는 것을 목표로 하였습니다. 독자들의 이해를 최우선 목표로 하다보니 책에 기재된 내용이 엄밀하게는 틀릴 수도 있습니다. 따라서 이 책을 읽고 따라해보신 후, 코딩에 관심이 생기신다면 조금 더 전문적으로 깊이있게 다루는 책이나 강의를 참조하시길 바랍니다.

 

 

 

 

 

이 책의 구성은 다음과 같습니다:

 

첫번째 챕터에서는 프로그래밍의 기본이 되는 문법을 배웁니다. 그리고 이를 활용하여 계산기를 만들어봅니다.

 

두번째 챕터에서는 React를 사용하여 랜덤하게 가격이 변하는 주식게임을 만들어봅니다.

 

세번째 챕터에서는 NodeJS를 사용하여 페이지의 정보를 수집하는 크롤러를 만들어봅니다.

 

마지막 네번째 챕터에서는 React와 NodeJS를 모두 사용하여 블로그를 만들어봅니다.

 

 

 

 

 

반응형
블로그 이미지

개발자_무형

,