본문 바로가기

전체 글241

[WebRTC] 1:N Peer To Peer 연결 구현 니꼴라스 선생님이 작성해준 1:1 Peer To Peer 예제 소스에서 크게 벗어나진 않는다. https://github.com/Yumin2019/WebRTC-P2P-Implement/tree/p2p-one-to-one 1:1 코드와 달라진 부분) 1:1 코드에서는 미리 PeerConnection을 생성하는 것이 가능했다. 왜냐면 Room에 들어올 인원이 2명으로 한정되어 있었기에 Id값이 없더라도 그냥 Room에 Socket 이벤트를 주는 방식으로 개발되어 있었기 때문이다. 1:N의 방식에서는 새로운 유저가 들어온 시점에 Offer를 만드는 부분과 Answer을 만드는 시점(다른 클라이언트)에 각각 서로의 Id를 key로하는 PeerConnection을 만들어 주는 것이 핵심이다. 1:N을 구현하는 순.. 2023. 9. 16.
[WebRTC] WebRTC 미디어 서버와 활용 방안 WebRTC 개발에 사용되는 서버 컴포넌트 Application Server: 만드는 프로그램에서 사용하는 서버, WebRTC와 직접적인 연관성은 없다. Signaling Server: 유저간 통신을 연결하는 데 사용된다. (WebRTC는 자체적인 Signaling Protocol을 소유하지 않음) TURN (and STUN) servers: 방화벽이나 NAT을 통해 미디어를 라우팅하기 위해 사용된다. WebRTC media servers: WebRTC 미디어 패킷을 인프라 구조에서 처리하고 전송하기 위해 사용된다. Media Server의 역할과 Mesh 백엔드 인프라를 통해 미디어 패킷을 전송하는 역할을 한다. 만약 여러 명의 유저가 함께 P2P연결을 해야 한다고 가정해보자. 미디어 서버가 없이 구현.. 2023. 9. 16.
[WebRTC] WebRTC 기본 개념과 Peer to Peer WebRTC(Web Realtime Commnunication)란? WebRTC는 브라우저간 Peer to Peer 통신을 가능하게 하는 기술이다. 음성 통화, 영상 통화, P2P 파일 공유 등으로 활용될 수 있다. SDP(Session Description Protocol)란? Peer 서로간의 미디어와 네트워크에 관한 정보를 이해하기 위해 사용되는 프로토콜이다. 코텍, 소스 주소, 오디오와 비디오의 타이밍 정보가 포함된다. ICE(Interactive Connectivity Establishment)란? WebRTC에서 Peer간 연결을 위해 사용하는 프레임워크이다. 공인 IP 주소를 갖지 않은 기기들에 대한 유일한 주소를 부여한다거나 방화벽을 통과 하는 등의 문제들을 해결하기 위해 사용된다. ICE.. 2023. 9. 16.
WebSocket과 Socket.io 차이 HTTP request를 보내면 server가 처리하고 response을 보낸다. Stateless 상태를 저장하지 못하기 때문에 '쿠키' 정보를 클라에서 보낸다. 실시간 X WebSocket 브라우저가 연결을 보내면, 받든 거절하든 한다. 한번 연결된 이후에는 지속적인 연결 Stateful 양방향 통신, 실시간 브라우저마다 지원하는 WebSocket API가 존재한다. HTTP와 WebSocket은 서로 다른 프로토콜이며 같은 포트로 접속할 수 있도록 구성할 수 있다. Socket.io와 WebSocket의 차이는? Socket.io는 웹소켓을 사용하여 구현되기도 하지만, 웹 소켓을 사용할 수 없는 경우에는 다른 기술을 이용한다. (HTTP long polling) 자동으로 재연결 시도 socket.i.. 2023. 9. 10.
[React] 이미지 업로드 및 미리보기 초기 이미지 태그의 src에 넣을 state값을 정의하고 onChange 함수를 만든다. (이미지 데이터 변경시 사용) const [preview, setPreview] = useState("img/book3.jpg"); const onChange = (e) => { const img = e.target.files[0]; console.log(img); var reader = new FileReader(); reader.readAsDataURL(img); reader.onload = function (e) { setPreview(e.target.result); }; }; 사용하는 곳에 preview로 연결하면 된다. CSS 부분(정사각형 모양) /* image wrapper */ .profile-img-.. 2023. 9. 9.
[React] 페이지 이동하기 Next.js에서는 pages 폴더를 통해 접근하는 주소별 컴포넌트(페이지)를 넘겨준다. (SSR 방식) router 변수를 이용하여 이동할 경로를 처리한다. 반면 기본 React에서는 폴더 구조와는 상관없이 네이게이션을 정의해서 사용한다. npm i react-router-dom BrowserRouter를 App루트에 감싸준다. import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import { BrowserRouter } from "react-router-dom"; ReactDOM.createRoot(document.getElementById("root")).render( ); 그리고 A.. 2023. 9. 6.
[TypeORM] Using Validation https://orkhan.gitbook.io/typeorm/docs/validation class-validator를 사용하는 예시 import { Entity, PrimaryGeneratedColumn, Column } from "typeorm" import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate, Min, Max, } from "class-validator" @Entity() export class Post { @PrimaryGeneratedColumn() id: number @Column() @Length(10, 20) title: string @Column() @Contains("hello") text: string @Column() @IsIn.. 2023. 9. 4.
[TypeORM] Relations https://orkhan.gitbook.io/typeorm/docs/relations What are relations 1. @OneToOne 2. @ManyToOne 3. @OneToMany 4. @ManyToMany Relation options 관계 설정을 위해 처리하는 옵션 eager: booleam - true로 처리되면 메인 엔티티를 로드할 때 연관된 엔티티가 같이 로드 된다. QueryBuilder나 find* 메소드 사용시. casecade: boolean | ("insert | "update")[] - true로 처리되면 연관된 엔티티가 DB에 추가되고 업데이트 된다. 배열을 통해 옵션을 넘기는 것도 가능하다. onDelete: "RESTRICT" | "CASCADE" | "SET NU.. 2023. 9. 4.
[TypeORM] Many-to-one / one-to-many relations https://orkhan.gitbook.io/typeorm/docs/many-to-one-one-to-many-relations 예시를 보자 user는 다수의 photos를 가질 수 있다. 하지만 각 포토는 하나의 싱글 유저에게 귀속된다. import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm" import { User } from "./User" @Entity() export class Photo { @PrimaryGeneratedColumn() id: number @Column() url: string @ManyToOne(() => User, (user) => user.photos) user: User } import {.. 2023. 9. 4.
[TypeORM] One-to-one relations https://orkhan.gitbook.io/typeorm/docs/one-to-one-relations OneToOne 관계는 A가 오직 하나의 B 인스턴스를 가진다. 그리고 B는 오직 하나의 A 인스턴스를 가진다. 다음 예시는 User와 Profile의 관계이다. User는 하나의 Profile을 가지고 하나의 Profile은 하나의 User를 가진다. import { Entity, PrimaryGeneratedColumn, Column } from "typeorm" @Entity() export class Profile { @PrimaryGeneratedColumn() id: number @Column() gender: string @Column() photo: string } import { E.. 2023. 9. 3.
[TypeORM] Find Options - Advanced options https://orkhan.gitbook.io/typeorm/docs/find-options TypeORM은 많은 build in 연산자를 지원한다. - Not import { Not } from "typeorm" const loadedPosts = await dataSource.getRepository(Post).findBy({ title: Not("About #1"), }) SELECT * FROM "post" WHERE "title" != 'About #1' - LessThan import { LessThan } from "typeorm" const loadedPosts = await dataSource.getRepository(Post).findBy({ likes: LessThan(10), }) .. 2023. 9. 2.
[TypeORM] Find Options - Basic Options https://orkhan.gitbook.io/typeorm/docs/find-options Basic options 모든 레포지토리와 manager .find* 메소드는 데이터 쿼리를 위한 특별한 옵션을 받는다. select - 선택되어야 하는 메인 객체를 지정하는 속성 userRepository.find({ select: { firstName: true, lastName: true, }, }) SELECT "firstName", "lastName" FROM "user" relations - 메인 엔티티와 같이 로드되어야 한다. 서브 릴레이션 또한 사용될 수 있다. (join과 leftJoinAndSelect의 약어이다.) userRepository.find({ relations: { profile: .. 2023. 9. 2.
[TypeORM] EntityManager API https://orkhan.gitbook.io/typeorm/docs/entity-manager-api dataSource - EntityManager에 의해 사용된다. const dataSource = manager.dataSource queryRunner - EntityManager에 의해 사용된다. EntityManager의 트랜잭션 인스턴스에서만 사용된다. const queryRunner = manager.queryRunner transaction - 많은 데이터베이스 요청이 처리되는 곳에 트랜잭션을 제공한다. await manager.transaction(async (manager) => { // NOTE: you must perform all database operations using th.. 2023. 9. 2.
[TypeORM] Delete using Query Builder https://orkhan.gitbook.io/typeorm/docs/delete-query-builder QueryBuilder를 이용한 삭제 1. Delete (물리삭제) - DB 상의 삭제 2. Soft-Delete (논리 삭제) - 삭제 여부 컬럼 변경 3. Restore-Soft-Delete Delete QueryBuilder를 사용하여 Delete 쿼리를 작성할 수 있다. await myDataSource .createQueryBuilder('users') .delete() .from(User) .where("id = :id", { id: 1 }) .execute() 성능의 측면에서 가장 효과적으로 데이터를 삭제하는 방식이다. Soft-Delete QueryBuilder에 Soft-Delete.. 2023. 9. 2.
[TypeORM] Insert using Query Builder https://orkhan.gitbook.io/typeorm/docs/insert-query-builder 쿼리 빌더를 통해 데이터를 추가할 수 있다. await dataSource .createQueryBuilder() .insert() .into(User) .values([ { firstName: "Timber", lastName: "Saw" }, { firstName: "Phantom", lastName: "Lancer" }, ]) .execute() 성능면에서 가장 효율적인 방법이다. 대량으로 데이터를 추가할 수도 있다. Raw SQL support SQL쿼리가 필요할 때, 함수 스타일로 작성할 수 있다. await dataSource .createQueryBuilder() .insert() .i.. 2023. 9. 2.
[TypeORM] Transactions https://orkhan.gitbook.io/typeorm/docs/transactions Creating and using transactions 트랜잭션은 DataSource 또는 EntityManager를 사용하여 생성된다. 예시 await myDataSource.transaction(async (transactionalEntityManager) => { // execute queries using transactionalEntityManager }) await myDataSource.manager.transaction(async (transactionalEntityManager) => { // execute queries using transactionalEntityManager }) 트랜잭션에.. 2023. 8. 31.
[TypeORM] Caching queries https://orkhan.gitbook.io/typeorm/docs/caching QueryBuilder메소드(getMany, getOne, getRawMany, getRawOne, getCount)의 메소드 결과를 캐시할 수 있다. EntityManager나 Repository의 find*, count* 메소드의 결과 또한 캐시할 수 있다. data source의 옵션에서 명시적으로 캐싱을 활성화한다. { type: "mysql", host: "localhost", username: "test", ... cache: true } 한번 캐시를 활성화하면 데이터베이스 스키마를 다시 동기화해야 한다. CL를 사용하여 migration 또는 synchronize 데이터 소스 옵션을 처리한다. 이후에 Quer.. 2023. 8. 31.
[TypeORM] Active Record vs Data Mapper https://orkhan.gitbook.io/typeorm/docs/active-record-data-mapper What is the Active Record pattern? 액티브 레코드 패턴은 모델 내에 모든 쿼리를 작성한다. 그리고 이를 이용하여 모델을 저장하고 삭제하는 처리를 진행한다. 단순히 말해 모델 내에서 데이터베이스에 접근하는 것이다. import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from "typeorm" @Entity() export class User extends BaseEntity { @PrimaryGeneratedColumn() id: number @Column() firstName: string @Column(.. 2023. 8. 31.
[TypeORM] Entity Inheritance https://orkhan.gitbook.io/typeorm/docs/entity-inheritance 엔티티 상속 방식 1. 구체적인 테이블 상속 2. 싱글 테이블 상속 3. 임베디드 사용 Concrete Table Inheritance 엔티티 상속 패턴을 통해 코드를 줄일 수 있다. 가장 쉽고 효과적인 방법은 구체적 테이블 상속이다. 예를 들어 Photo, Question, Post 엔티티가 있다고 해보자. @Entity() export class Photo { @PrimaryGeneratedColumn() id: number @Column() title: string @Column() description: string @Column() size: string } @Entity() export cl.. 2023. 8. 31.
[TypeORM] Embedded Entities 임베디드 컬럼을 사용하여 중복을 줄일 수 있다. 자신의 컬럼을 가진 클래스를 받아들이는 컬럼이다. 그리고 이러한 컬럼을 현재 엔티티 테이블에 합친다. User, Employee 그리고 Student 엔티티가 있다고 해보자. 일반적인 컬럼이 존재한다. first name 과 last name import { Entity, PrimaryGeneratedColumn, Column } from "typeorm" @Entity() export class User { @PrimaryGeneratedColumn() id: string @Column() firstName: string @Column() lastName: string @Column() isActive: boolean } import { Entity, P.. 2023. 8. 31.