내일배움캠프 Node.js 본캠프 53일차

김선우·2024년 10월 24일
post-thumbnail

알고리즘 문제 풀어보기

예상 대진표

문제 설명

△△ 게임대회가 개최되었습니다. 이 대회는 N명이 참가하고, 토너먼트 형식으로 진행됩니다. N명의 참가자는 각각 1부터 N번을 차례대로 배정받습니다. 그리고, 1번↔2번, 3번↔4번, ... , N-1번↔N번의 참가자끼리 게임을 진행합니다. 각 게임에서 이긴 사람은 다음 라운드에 진출할 수 있습니다. 이때, 다음 라운드에 진출할 참가자의 번호는 다시 1번부터 N/2번을 차례대로 배정받습니다. 만약 1번↔2번 끼리 겨루는 게임에서 2번이 승리했다면 다음 라운드에서 1번을 부여받고, 3번↔4번에서 겨루는 게임에서 3번이 승리했다면 다음 라운드에서 2번을 부여받게 됩니다. 게임은 최종 한 명이 남을 때까지 진행됩니다.

이때, 처음 라운드에서 A번을 가진 참가자는 경쟁자로 생각하는 B번 참가자와 몇 번째 라운드에서 만나는지 궁금해졌습니다. 게임 참가자 수 N, 참가자 번호 A, 경쟁자 번호 B가 함수 solution의 매개변수로 주어질 때, 처음 라운드에서 A번을 가진 참가자는 경쟁자로 생각하는 B번 참가자와 몇 번째 라운드에서 만나는지 return 하는 solution 함수를 완성해 주세요. 단, A번 참가자와 B번 참가자는 서로 붙게 되기 전까지 항상 이긴다고 가정합니다.

제한사항

N : 21 이상 220 이하인 자연수 (2의 지수 승으로 주어지므로 부전승은 발생하지 않습니다.)
A, B : N 이하인 자연수 (단, A ≠ B 입니다.)

풀이 코드

function solution(n,a,b)
{
    var answer = 0;

    while(a !== b){
        a = Math.ceil(a / 2);
        b = Math.ceil(b / 2);
        answer++;
    }

    return answer;
}

풀이 과정

Math.ceil()은 해당 값을 올림해주는 함수이다. a값과 b값이 다를 때 계속 반복되는 반복문을 만들어준 후 a값과 b값에 대해 Math.ceil을 통해 2로나눴을때의 값을 구해준다.(짝수라면 그대로 앞번호와 붙지만 홀수라면 +1된 번호와 붙기 때문에 올림을 해줌.)
위의 2로 나눌때의 값이 같아지기 전까지 반복할때마다 answer값을 1씩 올려주고 return 해주면 몇번째 라운드에서 만나는지 알 수 있다.

게임서버개발 플러스

사용 라이브러리

dotenv

  • 환경 변수를 .env파일에 저장하고 이를 Node.js 애플리케이션에 로드
    => 개발자가 코드에서 직접 환경 변수를 설정하는 대신 별도의 파일로 관리하게 해줌.

lodash

  • 유틸리티 라이브러리.
  • 배열, 객체, 함수 등의 데이터 처리를 위한 다양한 기능 제공.
  • 성능이 뛰어나고 코드의 가독성을 높이는데 사용.

long

  • 64비트 정수를 지원하는 라이브러리
    => JS가 기본적으로 64비트 정수를 지원하지 않기 떄문에 long을 통해 64비트 정수를 다룰 수 있음.

mysql2

  • MySQL DB와 상호작용을 위한 Node.js 클라이언트 라이브러리.

protobufjs

  • Google의 Protocol Buffers를 사용해 데이터 직렬화 및 역직렬화를 지원하는 라이브러리.

    데이터 직렬화와 역직렬화

  • 직렬화 : 객체들의 데이터를 연속적인 데이터로 변형해 전송 가능한 형태로 만드는 것.
  • 역직렬화 : 직렬화된 데이터를 다시 객체의 형태로 만드는 것.
    ex)
class Person{
	private String name;
    
    public Sample(String name) {
        this.name = name;
    }
}

위와 같은 클래스가 있을 때, Person person = new Person("김철수"); 객체를 { "name" : "김철수"} 와 같은 방식으로 변경하는 것을 직렬화,

{ "name" : "김철수"} 데이터를 받아서 Person이라는 객체의 name 필드에 "김철수" 를 할당하고 객체를 생성하는 것을 역직렬화라고 할 수 있다.

  • 자바에서 제공하는 직렬화 기능은 추가적인 라이브러리 설치 없이 객체 데이터를 영속화시킬 수 있다는 장점이 있지만, 직렬화 결과물 용량이 상대적으로 커서 비효율 적인 문제를 갖고 있고, 자주 변경될 수 있는 데이터를 직렬화해서 보관하게 되면 나중에 변경이 생겼을 때 역직렬화가 불가능해지므로 쓸모없는 데이터가 될 수 있다는 단점이 있다.

uuid

  • 고유 식별자 생성을 위한 라이브러리
  • 다양한 버전의 UUID지원

중앙 집중식 환경변수 관리

  • 모든 환경 변수와 상수를 한 곳에서 관리, 다른 파일에서 동일한 값을 사용해도 일관성을 유지
  • 장점 : 변경이 필요할 대 한 곳 에서만 수정하면 되고 환경 변수와 상수의 직접 사용이 아니므로 코드가 명확해지는 효과가 있음.
  • 필요에 따라 개발, 테스트, 프로덕션 환경별로 다른 설정 사용 가능.

커링(Currying)

  • 여러 인수를 받는 함수를 인수가 하나인 함수들의 연속으로 반환하는 기법.
export const onData = (socket) => (data) => {
  console.log(data);
};

onData보다 상위인 onConnection 함수가 가진 socket도 쓰고 onData의 인자로 오는 data도 쓰는 것 = 커링.

프로토 파일 로드

protobufjs 사용법

  • 1) 프로토콜 버퍼 정의 파일 작성
syntax = "proto3";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
}
  • 2) 프로토콜 파일 로드
import protobuf from 'protobufjs';

protobuf.load("person.proto").then(root => {
  // 'person.proto' 파일을 로드합니다.

  const Person = root.lookupType("Person");
  // 'Person' 메시지 타입을 'root' 객체에서 찾습니다. 이는 person.proto 파일에서 정의한 메시지 타입입니다.

  const message = Person.create({ name: "John Doe", id: 123, email: "johndoe@example.com" });
  // 'Person' 메시지 타입을 사용하여 새로운 메시지 객체를 생성합니다. 여기서는 name, id, email 필드를 설정합니다.

  const buffer = Person.encode(message).finish();
  // 생성된 메시지 객체를 바이너리 형식으로 인코딩합니다. 'finish' 메서드는 최종 인코딩된 버퍼를 반환합니다.

  const decodedMessage = Person.decode(buffer);
  // 인코딩된 버퍼를 다시 메시지 객체로 디코딩합니다.

  console.log("Original message:", message);
  // 원래 생성된 메시지 객체를 콘솔에 출력합니다.

  console.log("Encoded buffer:", buffer);
  // 인코딩된 바이너리 버퍼를 콘솔에 출력합니다.

  console.log("Decoded message:", decodedMessage);
  // 디코딩된 메시지 객체를 콘솔에 출력합니다.

})

DB 연동

게임서버에서의 DB 사용

커넥션 풀(Connection Pool)

  • 데이터베이스와의 연결을 미리 여러 개 생성하여 풀에 저장
  • 필요할 때마다 재사용하여 성능을 향상
  • 미리 생성된 연결을 사용함으로써 응답 시간 감소
    => 장점 : 더 많은 연결이 더 많은 처리를 동시에 진행해 동시 처리 능력이 향상되고 동접자가 많은 환경에서 유리함. 여러개의 연결을 유지하는 것으로 갑작스러운 트래픽 증가에 고가성용성을 제공.
    => 단점 : 사용하지 않는 커넥션으로 자원이 낭비 되고 데이터베이스 서버에 과도한 부하를 줘서 성능이 저하될 수 있다. 대역폭 사용 증가로 인해 네트워크 성능에도 영향을 미칠 수 있다.

DB 마이그레이션

  • 새로운 기능 추가로 이냏 스키마 변경이 필요할 때.
  • 데이터베이스 성능 향상을 위해 구조를 최적화할 때.
  • 데이터베이스 시스템을 교체할 때.(EX) MYSQL -> PostgreSQL)

0개의 댓글