데이터베이스 생성시 UTF-8 설정
CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
단방향 연관관계 매핑을 사용하면 insert 이후에, FK를 저장하기 위해 update 쿼리를 한 번더 실행하는 문제가 있다. @Entity public class Menu { //... @OneToMany(cascade = CascadeType.PERSIST) @JoinColumn(name = "menu_id") private final List<MenuProduct> menuProducts; //... } @Entity public class MenuProduct { //... } 위 상황의 경우 MenuProduct 엔티티의 menu_id라는 FK가 저장된다. 하지만 Menu 를 저장할 때, MenuProduct에 FK 값을 지정하기 위해서 update 쿼리가 한 번더 실행되기 때문에 성능상 좋지않다. 단방향 OneToMany를 사용하는 것 보다는 양방향 ManyToOne을 사용하는 것이 좋다....
5초동안 잠시 멈추려면 아래와 같이 작성하면 된다. setTimeout(function () { // 5초 뒤 실행할 코드 }, 5000); 참고 자료 https://stackoverflow.com/questions/14226803/wait-5-seconds-before-executing-next-linehttps://www.w3schools.com/jsref/met_win_settimeout.asp
매번 ip를 입력하기엔 너무 불편하다. vi /etc/hosts [서비스용IP] [별칭]
문제 상황 @EntityListeners(AuditingEntityListener.class) @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity public class Room { @OneToMany(mappedBy = "room") private final List<Session> sessions = new ArrayList<>(); //... } @EntityListeners(AuditingEntityListener.class) @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity public class Session { @Column(nullable = false) private boolean deleted = false; //... public void delete() { if (user.isLinkedSession(this)) { user.unLinkSession(this); } if (room.containsSession(this)) { room.exitSession(this); } deleted = true; } } Session은 논리적 삭제를 사용하고 있는데, Room의 sessions필드가 지연로딩 될 때, 논리적 삭제를 사용하고 있는 것을 모르기 때문에 모든 session을 가지고 오는 문제가 있었다....
@Temporal(TemporalType.DATE) private Date date; // date date 생성 @Temporal(TemporalType.TIME) private Date time; // time time 생성 @Temporal(TemporalType.TIMESTAMP) private Date timestamp; // timestamp timestamp 생성 @Temporal 를 생략할 경우 TIMESTAMP 로 컬럼을 만든다. Java 8의 경우에서 나온 LocalDate, LocalTime, LocalDateTime 등은 별도의 어노테이션을 붙일 필요가 없다. 참고 자료 https://www.baeldung.com/hibernate-date-time
웹과 네트워크의 기본에 대해 알아보자 웹은 HTTP로 나타낸다 웹 브라우저는 웹 브라우저 주소 입력란에 지정된 URL에 의지해서 웹 서버로부터 리소스라고 불리는 파일 등의 정보를 얻는다. 서버에 의뢰하는 웹 브라우저 등을 클라이언트라고 부른다. 클라이언트에서 서버까지 일련의 흐름을 결정하고 있는 것은 웹에서 HTTP라고 불리는 프로토콜이다. 프로토콜이라는 의미는 “약속”이다. HTTP는 이렇게 태어났고 성장했다 1989년에 CERN의 팀 비너스 리 박사는 멀리 떨어져 있는 동료 연구자와 지식을 공용하게 할 수 있도록 시스템을 고안하였다. 최초로 고안한 것은 여러 문서를 상호간에 관련 짓는 하이퍼텍스트에 의해 상호간에 참조할 수 있는 WWW의 기본 개념이 되었다....
배경 어떤 테이블에 대해서 컬럼 A 기준으로 group을 만들고 그룹 내에서 컬럼 B 기준으로 상위 n개를 가져와야 되는 목적이 생겼다. 해결 방법 예시를 들어 설명을 한다. 아래와 같이 테이블과 행이 존재한다. create table player ( user_id bigint auto_increment primary key, team_id bigint not null, score bigint not null ); 다음과 같이 데이터가 존재하고, team_id 별로 상위 2등까지 플레이어를 확인하고 싶다면 아래와 같이 작성하면된다. SELECT * FROM( SELECT *, RANK() OVER (PARTITION BY player....
n, m, k = map(int, input().split()) 위와 같이 구현할 수 있다. split()을 통해 공백 단위로 나누어 str의 리스트를 만들게 됩니다. 각 요소를 int형으로 변환하기 위해 map() 을 사용하게 되는데 map()의 리턴 타입은 map 이라는 클래스입니다. 참고 자료 https://www.programiz.com/python-programming/methods/built-in/map https://mjmjmj98.tistory.com/83
협력하는 개체들의 공통체 협력하는 사람들 역할과 책임 역할: 커피를 주문하는 손님, 주문을 받는 캐시어, 커피를 제조하느 바리스타 책임 손님: 커피를 주문할 책임 캐시어: 손님의 주문을 받는 책임 바리스타: 주문된 커피를 제조하는 책임 협력: 커피 주문 요청과 응답 커피주문이라는 협력은 손님이 커피를 제공해 줄 것을 캐시어에게 요청하는 것이다. 캐시어는 주문된 커피를 제조해줄 것을 요청한다. 바리스타는 커피를 제조한후 제조가 완료됐음을 캐시어에게 알려주는 것으로 캐시어의 요청에 응답한다. 캐시어는 진동벨을 울려 손님에엑 주문된 커피가 준비됐음을 알림으로써 손님의 주문에 응답한다....
운영체제마다 개행을 나타내는 특수 문자가 다르다. 리눅스, 유닉스, 맥은 , 윈도우는 \r 를 사용한다. 플랫폼에 독립적인 코드를 작성하고 싶다면 %n 을 사용하거나 System.lineSeparator() 메소드를 사용해야된다. 참고 자료 https://www.baeldung.com/java-string-newline
들어가기 지저분해지는 코드 단순한 if-else 블록의 복사 붙여넣기의 반복은 코드를 복잡하게 만들며, 개발자가 코드를 추가하거나 수정할 위치를 찾는데 점점 오랜 시간이 걸리게 된다. 심한 경우 코드를 추가하지 않고 눌가하는 경우도 발생한다. 수정하기 좋은 구조를 가진 코드 객체 지향 기법을 적용하면 소프트웨어를 더 쉽게 변경할 수 이쓴 유연함을 얻을 수 있게 되고 이는 곧 요구 사항의 변화를 더 빠르게 수용할 수 있다는 것을 뜻한다. 소프트웨어의 가치 새로운 요구 사항을 적용하기 어려우면 소프트웨어는 점점 뒤쳐지게 되는데, 이는 결곡 소프트웨어의 죽음으로 이어질 수 잇다....
직접 구현하려고 하는데, 이미 파이썬에서 제공하고 있었다. import itertools inp_list = [4, 5, 6] permutations = list(itertools.permutations(inp_list)) print(permutations) [(4, 5, 6), (4, 6, 5), (5, 4, 6), (5, 6, 4), (6, 4, 5), (6, 5, 4)] 순열 길이의 기본값은 입력 값의 길이가 된다. 만약 길이를 직접 지정하려면 파라미터를 추가하면 된다. import itertools inp_list = [1, 2, 3] permutations = list(itertools.permutations(inp_list, r=2)) print(permutations) [(4, 5), (4, 6), (5, 4), (5, 6), (6, 4), (6, 5)] 참고 자료 https://www....
XML 장점: 애플리케이션을 구성하는 빈과 의존관계, 설정 등을 통제하고 관리하기 쉽다. 단점: XML 문서를 관리하기 때문에 개발 속도가 느려진다. 어노테이션 장점: 복잡한 XML 문서 생성과 관리가 필요없이 개발속도를 향상 시킬 수 있다. 단점: XML처럼 상세한 메타정보 항목을 지정할 수 없고, 클래스당 한 개 이상의 빈을 등록할 수 없다.
기존에 존재하던 데이터베이스의 ERD Diagram 자동 생성하기 설명 Workbench의 Reverse Engineer 기능을 이용하면 된다. Database => Reverse Enginner 예시 만들어진 ERD Diagram을 최신화 하기 설명 Database => Synchronize model 예시 alter table `test`.`member` add column `phone_number` varchar(20); 참고 자료 https://medium.com/@tushar0618/how-to-create-er-diagram-of-a-database-in-mysql-workbench-209fbf63fd03 https://dba.stackexchange.com/questions/25900/mysql-workbench-how-to-refresh-eer-diagram
배경 테스트 코드를 보니 원래 알고있던 when()함수가 아니라 whenever()함수를 사용하고 있었다. Kotlin에서 when을 사용하면 문제점 Kotiln에는 이미 when이라는 예약어가 있기 때문에 백틱을 사용해서 호출해야된다. val mockBookService = Mockito.mock(BookService::class.java) Mockito.`when`(mockBookService. inStock(100)).thenReturn(true) mockito-kotlin 라이브러리에서 이것이 번거롭기 때문에 whenever라는 함수를 제공해주고 있다. whenever(mockBookService.inStock(100)).thenReturn(true) 참고 자료 https://www.baeldung.com/kotlin/mockito
문제가 되는 이유 수평적 확장 관점에서 REST API와 WebSocket의 가장 큰 차이점은 아무래도 상태 관리다. REST API는 서버에서 상태를 저장하지 않기 때문에 스케일 아웃을 하는데 문제가 없다. 하지만 WebSocket의 경우에는 서버에서 세션을 저장하고 가지고 있어야한다. 따라서 클라이언트가 기존에 세션을 저장해둔 서버(BACKEND #1)가 아닌 다른 서버(BACKEND #2)로 메시지를 보낸다면 세션을 저장하고 있지 않기 때문에 처리하지 못할 것이다. 처리 방법 #1: Sticky Session Sticky Session이란 클라이언트가 첫 요청을 보낸 시점에 로드 밸런서에서 특정 서버를 하나 지정해서 처리하게 해주고, 이 클라이언트는 이후의 요청들을 전부 이전에 처리해준 서버에게 보내도록 하는 기법이다....
http { map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream websocket { server 192.168.100.10:8010; } server { listen 8020; location / { proxy_pass http://websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; } } } 참고 자료 https://www.nginx.com/blog/websocket-nginx/
RTCPeerConnection.getStats() 메서드를 호출하면, 현재 커넥션의 통계 데이터와 트랙의 정보들을 받을 수 있다. 출력을 해보면 stream이나 codec, trasnport 등 다양항 type의 정보를 오는 것을 확인할 수 있다. 각 type의 의미들은 https://developer.mozilla.org/en-US/docs/Web/API/RTCStats/type에서 확인이 가능하다. {id: 'RTCMediaStreamTrack_receiver_1', timestamp: 1659319122459, type: 'track', trackIdentifier: '181e51a6-8bc6-4a88-8bc0-8d5019f6564c', remoteSource: true, …} {id: 'RTCMediaStreamTrack_receiver_2', timestamp: 1659319122459, type: 'track', trackIdentifier: '08aa011f-13c7-44e8-b8b8-3e2f1da4bad5', remoteSource: true, …} {id: 'RTCMediaStream_xANDdH976y0iJdwry5rJCIUjy5hVDVPInSSM', timestamp: 1659319122459, type: 'stream', streamIdentifier: 'xANDdH976y0iJdwry5rJCIUjy5hVDVPInSSM', trackIds: Array(2)} {id: 'RTCPeerConnection', timestamp: 1659319122459, type: 'peer-connection', dataChannelsOpened: 0, dataChannelsClosed: 0} {id: 'RTCRemoteOutboundRTPAudioStream_1158860338', timestamp: 1659319120593, type: 'remote-outbound-rtp', ssrc: 1158860338, kind: 'audio', …} {id: 'RTCTransport_0_1', timestamp: 1659319122459, type: 'transport', bytesSent: 60504, packetsSent: 1208, …} {id: 'RTCCodec_0_Inbound_0', timestamp: 1659319123459, type: 'codec', transportId: 'RTCTransport_0_1', payloadType: 0, …} {id: 'RTCCodec_0_Inbound_103', timestamp: 1659319123459, type: 'codec', transportId: 'RTCTransport_0_1', payloadType: 103, …} {id: 'RTCCodec_0_Inbound_105', timestamp: 1659319123459, type: 'codec', transportId: 'RTCTransport_0_1', payloadType: 105, …} 우리가 필요한 것은 전송받고 있는 비디오 코덱 정보이므로 아래와 같이 조건문을 작성할 수 있다....
WebRTC를 이용해 코덱 별 성능 테스트를 위해서, 사용할 코덱의 종류를 바꿨어야했다. RTCRtpTransceiver를 통해 사용할 코덱을 수정할 수 있다. RTCRtpTransceiver RTCRtpSender와 RTCRtpReceiver 쌍을 관리하는 인터페이스다. 각각은 트랙을 인코딩하고 remote peer에 전송하는 것을 관리하는 역할, 트랙을 디코딩하고 remote peer를 전송 받는 것을 관리하는 역할이 있다. codecPreferences setCodecPreferences() 메서드를 호출하면 Transceiver의 코덱을 설정할 수 있게된다. codecPreferences는 선호하는 순서대로 코덱을 나열해서 입력할 수 있다. 참고 자료 https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpTransceiver