All
20 posts
클라이언트 콘솔 입력 스레드 분리하기

클라이언트 스레드 관리 요약 클라이언트에서 전투 시작 시 콘솔 입력 + 패킷 처리가 동시에 실행이 되지 않았던 이유는 콘솔 입력 작업을 중복으로 큐에 추가하여, 모든 스레드가 블로킹 됐기 때문이다. 문제 상황 boost asio를 이용해 소켓 프로그래밍을 구축했습니다. 클라이언트의 스레드 구조는 아래와 같습니다. 4개의 작업스레드를 생성하고, io_context에 post된 작업을 스레드가 가져가서 작업을 하는 형태입니다. post 되는 작업은 Send() : 콘솔 입력 + 패킷 전송 Receive() : 패킷 수신 + 콘솔 출력 2개의 작업뿐입니다. 이해도 부족 처음 문제에 대해 다뤘던 문서 (읽어보지 않아도 됩니다..!) 요약 : 콘솔 입력 작업 / 패킷 수신 작업 2개의 작업이 존재하는데, 패킷 수신 작업이 1초마다 반복될 때, 두 작업이 동시에 진행되지 않았습니다. 정리했던 문서의 결과는 다음과 같습니다. getline() 함수는 블로킹 함수이고, 이로 인해 다른 스레드에서…

May 01, 2024
C++
Boost
Boost Work란?

Boost asio::io_service::work 란? Boost asio를 사용해 소켓 서버를 생성하면, 항상 io_service(지금은 io_context로 대체)를 사용하게 된다. 링크에선 work를 사용해야 하는 이유를 다루고 있다. 두 코드를 보면, 1. thread 생성, 2. 작업 post, 두 개의 작업이 존재하고 1번 코드는 1 → 2 (work 객체와 함께) 2번 코드는 2 → 1 의 순서로 코드 흐름이 이어진다. post는 IO Execution Context(여기선 io_service)에서 실행하겠다는 의미이다. 모든 context는 run을 실행해줘야 하는데, 여기선 thread를 생성하고 작업을 실행한다. 즉, 1번 코드는 IO Context run 이후 post 2번 코드는 post 이후 IO Context를 run 한다. 즉, 남은 작업이 존재하지 않아도 io_service가 run을 반환하지 않도록 도와주는 것이 work의 역할이다. ps. De…

March 23, 2024
C++
Boost
메모리 사이클 관리

메모리 사이클 기존 코드를 보면 아래와 같습니다. ProtocolPtr은 패킷을 주고 받을 때 사용하는 encode, decode가 구현된 객체입니다. 여기서 temp 변수는 Send() 함수에서 선언한 지역 변수이고, Send() 함수의 종료와 함께 소멸됩니다. Send() 함수는 비동기 함수인 boost::asio::async_write_some()을 호출합니다. 이때 Send() 함수가 종료된 이후 비동기 함수가 실행되고, 실행 후 SendHandle() 함수가 호출됩니다. 문제는 여기서 발생할 수 있습니다. 비동기함수는 temp->encode()를 매개변수로 전달받는데, temp는 Send() 함수가 종료되면 소멸됩니다. Send()의 종료 이후, 비동기함수가 실행될 때 temp의 메모리 안정성은 보장되지 않습니다. 때문에 메모리 이슈가 발생할 수 있고, 우리는 이 메모리를 관리해줄 필요가 있습니다. 람다에 캡쳐 비동기 함수에서 temp를 사용하기 위해 람다에 캡쳐를 사용합…

March 19, 2024
C++
소켓 통신 오류 디버깅 (패킷 처리 오류)

오류 발생 과정 Server ↔ Client 간의 소켓 통신 과정은 아래와 같습니다. Client: 를 통해 ID 설정 Server: 해당 Client의 ID를 설정하고 “set $ID Success”를 해당 Client에게 전송 () “$ID 님이 입장하셨습니다”를 모든 Client에게 전송 () Client: 를 통해 수신 이 과정에서 아래 에러가 발생했습니다. libc++abi: terminating due to uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument (해당 오류는 10번 시도 중 9번 정도로 발생했습니다) 오류 디버깅 Client와 Server의 핵심 코드는 아래와 같습니다 Thread 생성 시에 lock을 사용한 부분은 문제가 없었고, Receive 함수의 lock 호출과는 실행 시점이 분리되어 있습니다. 때문에 lock 관련 에러는 Receive …

March 07, 2024
C++
Deque push_front는 O(1)일까?

deque의 push_front 시간복잡도 list는 Node로 구성되어, 삽입 삭제에 유리하지만 operator [] 를 사용할 수 없다. vector는 데이터가 선형으로 이어져야 하기 때문에 삽입/삭제 시 불리하지만, operator []가 가능하다. c++ 표준 라이브러리가 제공하는 Deque는 이 둘을 섞은 느낌이다. Deque는 block의 형태로 구현되어 있다. operator [], *를 보면 Block과 Map이 나온다. Deque는 내부적으로 block으로 이루어져 있다. 이 block이 하나의 vector(배열)이고, 이 block들이 여러개로 구성되어 있다. 때문에 원소의 삽입,삭제는 빠르게 이루어진다. vector처럼 원소를 재정렬할 필요가 없기 때문이다. 또 vector와 같이 []도 사용가능하다. 여기서 의문이 생겼는데, push_front를 실행할 경우, 새로운 block이 필요할 수 있다. 이 경우 새로운 block을 어떻게 관리하면 시간복잡도가 O(1…

January 30, 2024
C++
c++의 가상 함수란!

가상 함수 가상 함수 vs 순수 가상 함수 가상 함수 한글자료 가상 함수 런타임 가상 함수 가상 함수는 클래스 멤버 변수에 선언할 수 있고, 함수 호출에 사용된 타입(포인터)에 관계없이 실제 객체의 함수가 호출되도록 한다. 몇 가지 특징, 규칙은 아래와 같다. 런타임 다형성을 구현할 수 있다. 이를 위해 상위 클래스 타입을 사용해야한다. 가상 함수는 하위 클래스에서 꼭 override 해야하는 것은 아니다. 가상 함수의 시그니처는 동일해야한다. 가상 생성자는 불가능하다. 소멸자는 가능 어떻게 이런 동작을 할까? RTTI(RunTime Type Information)을 활용한다. 클래스와 객체를 생성할 때 각각 VTable, VPtr이 생성된다. 아래 예시를 보자. 각 에서 실제 derived 객체를 생성하고, 타입은 base 포인터이다. 이때 derived 객체는 멤버 변수로만 이뤄지지 않고, VPtr이라는 주소값이 할당된다. 이 VPtr은 실제 이 객체의 가상 함수 테이블(VT…

January 30, 2024
C++
Mac Parallels에서 Visual Studio Extension 설치하기

💻 Mac Parallels 맥북에서 parallels를 이용해, Window를 설치했다. Window 환경에서 개발을 진행하기 위해서 설치했고, 가상머신 위에서 얼마나 쾌적할지 걱정했지만 사용성이 괜찮았다. 물론 아직 규모 있는 프로젝트를 진행하진 않아서 문제가 없었지만, 성능이 더 요구되면 어려울 수도 있다. 문제는 Parallels 위에서 Visual Studio 2022를 사용할 때 발생했다. VS도 Extension이 있는데, 대부분의 extension을 설치할 수 없었다. 여러 시도를 한 끝에 이런 환경에서 설치하는 방법을 남겨 놓는다! VSIX 파일 수정 vs marketplace에 들어가보면 다양한 extension을 볼 수 있다. vsix 파일을 설치해서 실행하면, 설치 할 수 있는 버전을 찾을 수 없다고 나온다. 이상하게 IDE 내에서 검색되는 extension과 웹에 있는게 달랐는데, 결과적으로 각 extension마다 지원하는 버전과 프로세서가 다르기 때문이다…

January 16, 2024
IDE
Jenkins를 통해 CI/CD를 하던 중..

베스트라빈스 프로젝트를 진행하며 Jenkins를 사용했다. 서버 아키텍쳐는 아래와 같다. Jenkins로 CI / CD를 구축한건 처음이었는데, 그 과정에서 만났던 문제들을 남겨두고자 한다. Jenkins의 설정 방법 등은 간단히만 적어보겠다. Jenkins 설정 Jenkins 서버는 Naver Cloud Platform(NCP)를 사용했다. micro 버전은 무료이기 때문에 사용했는데, 이후 Compact로 업그레이드했다. NCP의 서버는 선택한 Jenkins 버전의 이미지를 통해 배포된다. 때문에 18080포트 접근 권한 설정을 하면 웹사이트에서 접근이 가능하다. JenkinsFile을 통해 관리하는 것과 웹페이지에서 FreeStyle로 프로젝트를 설정하는 방식이 있다. 나는 후자를 택했고 장단을 비교하자면 버전관리 JenkinsFile은 git을 통해 관리될 수 있어, 버전 관리에 용이하다 재사용성 JenkinsFile은 코드 형태로 관리하므로, 재사용성이 뛰어나다 유지보수 …

October 05, 2023
Infra
Spring Security login 구현

Bottle-letter 프로젝트 기록 Spring Security를 사용해 로그인을 구현하며 Filter를 이용한 방식과 Argument Resolver를 이용한 방식을 알아봤다. Filter를 이용한 로그인 먼저Spring Security의 동작 원리와 구조를 이해해보자. https://spring.io/guides/topicals/spring-security-architecture/ 공식 레퍼런스에 잘 정리가 되어 있지만 간단히 설명을 해보자. 요청이 오면 Spring Security의 FilterChain이 가로챈다. Authentication 객체를 생성해서 security context에 저장하는데, 이 과정을 간략히 요약하자면 UsernamePasswordAuthenticationFilter 앞에 커스텀한 JwtFilter를 생성한다. 커스텀 필터에서는 헤더의 jwt Token을 파싱하여 분석하고 인증한다. Security에서 제공하는 와 같은 인터페이스를 구현한다…

August 29, 2023
Spring
Spring docs 적용 중 문제

Bottle-letter 프로젝트 기록 Spring docs 적용 Spring Docs는 Swagger와 같이 API docs를 생성해주는 라이브러리다. 다른점은 Spring docs는 테스트 코드를 통해 작성된다. Swagger는 Controller를 스캔하고 자동으로 생성해주며, 타이틀과 같은 커스텀 설정은 코드에 함께 기재하게 된다. (보통 어노테이션 방식) Spring Docs는 테스트 코드에 API 스펙을 작성하고, asciidoctor를 통해 adoc 파일을 생성하고 html로 변환하여 문서가 작성된다. 쉽게 말해, 테스트 코드를 통해 HTTP spec이 작성되고, 이를 원하는 대로 문서에 삽입하여 문서를 생성한다. 상용 코드에 영향을 주지 않는다 커스텀 하기 용이하다 테스트를 강제한다. 이런 장점을 가졌다. 3가지 모두 굉장히 매력적인 장점이라 Swagger보다 Spring docs를 선택하게 됐다. 문제 적용 방법은 쉽게 찾을 수 있다. build.gradles.kt…

August 06, 2023
Spring
Value Class

NextStep - TDD, 클린 코드 with Kotlin강의를 참고했습니다. Java, Kotlin의 Int 두 테스트는 모두 참일까? 당연하게도 그렇다. 코틀린은 타입 추론을 통해, 타입을 명시하지 않아도 number1, number2는 Int가 된다. 여기서 Int는 코틀린의 Primitive type이고 컴파일 된 바이트 코드를 자바를 역컴파일하면 int가 된다. 위 경우를 보자. 결과는 테스트2만 통과한다. 이유가 뭘까? 정답은 메서드와 자바의 Integer에 있다. isSameAs 메서드는 Object로 파라미터를 받는다. 그래서 Test1을 컴파일 후 자바로 디컴파일 해보면 위와 같다. isSameAs에 int를 넘길 순 없기에 원시타입 int의 래퍼 클래스인 Integer로 변환한다. 때문에 지만 이 된다. 다음 테스트를 보자 위 테스트는 어떨까? 마찬가지로 동등성 비교는 통과하지만, 주소값을 비교하는 동일성 비교는 실패할까? 정답은 모두 통과한다. 이유는 Int…

June 29, 2023
Kotlin
Gradle kotlin?

모든 것을 궁금해한다! 프로젝트 세팅 프로젝트를 새로 시작할 때 https://start.spring.io/ 를 애용한다. 의존성 추가가 간편하고 Spring 버전 업데이트에 따라 최신화 돼서 좋다. Gradle vs Maven ? 항상 Gradle만을 선택해 왔는데, 둘은 어떤 차이가 있을까? (참조: https://www.geeksforgeeks.org/difference-between-gradle-and-maven/) Gradle, Maven은 소프트웨어 빌드에 사용되는 툴이다. Maven 오픈 소스 프로젝트로 정해진 lifecycle로 다양한 소프트웨어를 관리하는 툴이다. 이는 짧은 기간안에 표준 레이아웃에서 표준화된 개발에 중점을 둔다. XML을 이용하고 Java project를 다른 언어로도 사용할 수 있도록 해준다. 장점 빌드를 단순화하고 잘 구축한다. 다양한 의존성을 자동으로 관리해준다. Jar 파일들을 다운한다. POM 파일에서 의존성을 관리하고 추가하기 편하다. …

April 20, 2023
개발
Numble 배포 자동화 딥다이브 회고록

결과물 배포 쪽은 처음 공부하다보니, 작업량 산정이 안됐다. 결과적으로, 50%도.. 완성 못한 느낌으로 제출할 수 밖에 없게 됐다 ㅠ 호스트님이 의도한 구조는 Terraform으로 클라우드 리소스 생성 및 관리(2개의 ec2 생성) Github push 시, Jenkins 서버에서 Checkout -> build -> deploy 과정을 거침 deploy 단계는 Ansible을 이용해 Web 서버에 배포 로 이해했다. 이걸 의도하신게 아닐 수도 있지만..! 내가 이해한 부분은 이렇다. 나는 Spring server를 배포해보려 했고 내가 시도한 부분을 위와 대조해 정리해보면 Terraform -> VPC 기본 세팅과 2개의 ec2 생성 Jenkins-ec2에 수동으로 Jenkins 설치 및 설정 후 Github web hook을 통해 build 성공 -> 이 과정에서 gradle build 시에는 ec2가 고장이 남.. docker에서 충분히 연습 후에 해야 했는데, 제출날이…

April 09, 2023
DevOps
Numble
1차 세션

CI 보통 개인 branch -> main merge 되면서 Build/Test 하고 Artifact Repo를 통해 필요한 걸 받아오고..? 젠킨스가 하는 일: 깃허브에서 코드가 main branch에 올라가면, hook으로 어딘가로 알려줄 수 있음 그걸 Jenkins에 쏘고 해당 레포를 clone 한다던지 할 수 있음. Jenkins pipeline으로 만들고 Github url 입력. pipeline SCM - github repo JENKINSFILE을 읽고 동작함. Terraform ec2 1개 Jenkins, 1개 Web Server. Private key, Public key를 어디서 어디 것을 알아야 할지. aws key 저장소에 private key를 미리 저장. A에서 private 다운, B에선 public을 등록해서? Ec2를 띄우는건 Terraform으로 가능하지만 그 안에 구성을 만드는건 Ansible을 사용해야함. Deploy Shell script, P…

March 31, 2023
DevOps
Sealed Class

Sealed Class 코틀린 sealed class 공식문서를 참고했습니다. 목적 클래스의 상속을 더 제어하기 위해 사용한다. 코틀린은 예약어를 통해 컴파일 과정에서 편의성을 제공하는 방식을 좋아하는 듯 하다. 이 구조에서, when 식의 else를 주목하자. 를 구현한 새로운 Class가 생긴다면, else문은 논리 오류가 될 수 있다. 즉, 하위 클래스가 추가 됐을 때 컴파일러가 when이 모든 분기를 처리하는지 알 수 없다. 또 새로운 클래스 처리를 잊어버려도 알 수 없다. 이 문제에 대한 해법이 이다. 를 상속하는 하위 클래스는 무조건 중첩 클래스로 구현되어야 한다. when식이 모든 하위 타입을 검사하는지 컴파일러는 알 수 있고, 새로운 클래스가 분기처리 되지 않으면 컴파일 오류가 난다. 는 그 자체로 abstract 하고, 인스턴스화 할 수 없다. 코틀린 1.5부터는 너무 많은 제약을 해소했다. 하위 클래스는 중첩 클래스가 아닌 가 정의된 패키지 안에서 구현할 수 있고…

March 31, 2023
Kotlin
테라폼이란?

Terraform 테라폼 공식문서 테라폼? 클라우드 리소스 + on-prem 리소스를 코드로 관리할 수 있는 도구. 컴퓨팅, 스토리지, 네트워크 같은 low-level 뿐 아니라 DNS, SaaS 까지도 관리할 수 있다. 어떻게? Terraform은 API를 통해 클라우드 플랫폼 및 기타 서비스에서 리소스를 생성하고 관리한다. 사실상 거의 모든 플랫폼과 함께 동작할 수 있다. 이미 Terraform에서는 다양한 유형의 리소스, 서비스를 관리하기 위해 providers가 작성되어 있고 AWS, Azure, Kubernetes, Github 등등 지원한다. Write 여러 클라우드 공급자 및 서비스에 걸쳐 있을 수 있는 리소스를 정의한다. 예를 들어 보안 그룹과 로드 밸런서가 있는 VPC(Virtual Private Cloud) 네트워크의 가상 시스템에 애플리케이션을 배포하는 구성을 생성할 수 있다. Plan 기존 인프라 기반으로 생성, 업데이트 또는 삭제할 인프라에 관한 계획(스크…

March 28, 2023
DevOps
Jenkins 설치

Jenkins CI/CD를 위한 툴이다. 로컬 docker에 띄워 사용해본 후, Github hook과 연결하기 위해 ec2에 Jenkins를 띄웠다. https://www.jenkins.io/doc/book/installing/에 OS별 설치 방법이 상세히 나와있다. 현재 이해한 내용은 Jenkins를 8080 포트 (다른 포트도 가능)에 띄운다. localhost:8080를 통해 Jenkins 설정 페이지에 접근하여 설정할 수 있다. 이런 설정은 cli로도 가능할 듯 싶고, 사이트 내에서 , 등을 만들 수 있다. Github repo의 을 실행하는 방식의 Pipeline을 만들면 해당 사이트에서 build하고 결과를 확인할 수 있다. 구현 과정은 ansible 스크립트 작성 이후 해보자! 결국 구현할 구조는 push(Gihub action) -> Jenkins 서버에서 확인 후 build + deploy -> terraform 이용, web-server 구축 및 배포 -> An…

March 28, 2023
DevOps
Kotlin-in-Action 5장

Kotlin-in-Action 5장 람다로 프로그래밍 람다는 다른 함수에 넘길 수 있는 작은 코드 조각 리스트의 age가 가장 높은 원소를 찾는다면 두 변수가 필요하다. 람다를 활용한다면 코드 길이가 줄어든다. 마지막 줄을 개선해보자. 함수의 마지막 인자가 람다 식이라면 중괄호로 뺄 수 있다. 람다가 유일한 인자고 괄호로 뺐다면 빈 괄호를 없앨 수 있다. 파라미터 타입을 명시하지 않고(컴파일러가 추론) 한개의 파라미터라면 더 코드를 줄인다. 자바 무명 클래스처럼 람다를 함수 안에서 정의하면 함수의 파라미터뿐 아니라 람다 정의 앞에 선언된 로컬 변수까지 람다에서 사용할 수 있다. 람다 내부에서 변수 접근이 가능하고, 변경도 가능하다. 이런 변수를 람다가 포획한 변수라고 하는데, 어떤 함수가 로컬 변수를 포획한 람다를 반환 or 변수에 저장한다면 포획된 로컬 변수의 생명주기와 함수의 생명주기가 달라 질 수 있다. 이 함수는 항상 0을 반환한다. onclick 핸들러가 가 …

March 25, 2023
Kotlin
Kotlin-in-Action 1 ~ 4장

중복되는 내용이지만 Kotlin in Action 1,2,3,4장 정리를 모아놓았습니다. Kotlin 1장 코틀린의 빌더 패턴이란, 디자인 패턴 빌더 패턴과 같다. (p.44) 이처럼 Builder를 만들어 사용하는데, 파라미터가 명시적이고 필수 파라미터를 확인할 수 있다. 외에도 여러 이점이 있어 Lombok에서도 지원하는 패턴인데 코틀린의 경우, 생성자에 변수 명을 명시할 수 있고, 매개변수별로 기본값을 가질 수 있다. 때문에 이 자체로 빌더 패턴이 구현되어 있어 이를 용이하게 사용하면 좋다. 1장은 코틀린의 주요 특성인 다양한 플랫폼, 정적 타입 언어, 함수형 + 객체 지향, 무료 오픈소스 대해 말한다. 코틀린의 철학 실용성 간결성 안전성 상호운용성 2장 대입문은 자바에서 식, 코틀린에서는 문이다. 코틀린에서는 와 같이 사용할 수 없다. 모든 변수를 val 선언, 변경이 불가피할때만 var 이용하자. 자바의 문자열 접합 연산은 내부적으로 를 사용해 효율적이다. 코틀린의 문자…

March 24, 2023
Kotlin
깃헙 블로그 개시!

👋 이전 블로그 velog, tistory를 잠깐씩 했는데 새 마음으로 시작해보자. [Tistory] (https://ggam-nyang.tistory.com/) Github.io 어떤 방식으로 내 블로그가 배포가 되어 있는지 잘 모르겠다. 이걸 분석하고 자동 배포될 수 있도록 설정해보자. 👋 이전 블로그 Github.io

March 21, 2023
블로그