Skip to content

Latest commit

 

History

History
491 lines (384 loc) · 15 KB

File metadata and controls

491 lines (384 loc) · 15 KB

⚙️ BridgeRun 핵심 기술 구현

포트폴리오 핵심: 언리얼 엔진 5 기반 멀티플레이어 게임의 기술적 구현 상세

📋 기술 스택 개요

기술 영역 사용 기술 구현 범위 성숙도
게임 엔진 언리얼 엔진 5 C++ + 블루프린트 🟢 프로덕션
네트워킹 UE5 Replication 데디케이티드 서버 🟢 프로덕션
물리 시뮬레이션 Chaos Physics 실시간 동기화 🟡 최적화 중
AI/게임플레이 Behavior Tree NPC 시스템 🟡 개발 중
UI 시스템 UMG + C++ Events 이벤트 기반 🟢 안정화

🏗️ 건설 시스템 (Building System)

핵심 아키텍처

건설 시스템은 컴포넌트 기반 설계로 구현되어 확장성과 유지보수성을 확보했습니다.

// 핵심 컴포넌트 구조
class BRIDGERUN_API UBuildingComponent : public UActorComponent
{
    // 템플릿 기반 건설 시스템 (v3.0)
    template<typename T>
    void SpawnBuildingItem(TSubclassOf<T> ItemClass, 
                          const FVector& Location, 
                          const FRotator& Rotation);
    
    // 네트워크 RPC
    UFUNCTION(Server, Reliable)
    void AttemptBuild();
    
    UFUNCTION(NetMulticast, Reliable)
    void MulticastOnBuildComplete();
};

기술적 혁신 포인트

1. 템플릿 메소드 패턴 적용

// Before: 중복 코드 200줄 × 아이템 종류
void BuildPlank() { /* 하드코딩된 200줄 */ }
void BuildTent()  { /* 거의 동일한 200줄 반복 */ }

// After: 타입 안전 템플릿 + 단일 책임
template<typename T>
void SpawnBuildingItem(TSubclassOf<T> ItemClass, const FVector& Location, const FRotator& Rotation) 
{
    if (!ValidateBuildLocation(Location)) return;
    
    T* NewItem = GetWorld()->SpawnActor<T>(ItemClass, Location, Rotation);
    ConfigureBuildingItemPhysics(NewItem->GetMeshComponent(), Location, Rotation);
    OnBuildingItemSpawned(NewItem);
}

성과: 코드 라인 52% 감소, 중복 코드 83% 제거, 새 기능 추가 시간 80% 단축

2. 실시간 프리뷰 시스템

void UBuildingComponent::UpdateBuildPreview()
{
    if (!BuildPreviewMesh || !bCanBuildNow) return;
    
    FVector PreviewLocation;
    FRotator PreviewRotation;
    
    bool bValidPlacement = DetermineValidPlacement(PreviewLocation, PreviewRotation);
    
    BuildPreviewMesh->SetWorldLocation(PreviewLocation);
    BuildPreviewMesh->SetWorldRotation(PreviewRotation);
    BuildPreviewMesh->SetMaterial(0, bValidPlacement ? 
        ValidPlacementMaterial : InvalidPlacementMaterial);
}

3. 네트워크 동기화 시스템

// 서버 권한 검증 + 클라이언트 예측
void UBuildingComponent::AttemptBuild_Implementation()
{
    // 서버에서만 실행되는 권한 있는 로직
    if (!ValidateBuildLocation(PreviewLocation) || !HasRequiredResources()) {
        return; // 권한 없는 요청 차단
    }
    
    SpawnBuildingItem(CurrentBuildingItem, PreviewLocation, PreviewRotation);
    MulticastOnBuildComplete(); // 모든 클라이언트에 동기화
}

성능 최적화

최적화 기법 적용 영역 성능 개선
오브젝트 풀링 프리뷰 메시 가비지 컬렉션 90% 감소
LOD 시스템 원거리 건설물 렌더링 비용 60% 감소
네트워크 배칭 다중 건설 대역폭 40% 절약

🌐 네트워킹 시스템 (Networking)

멀티플레이어 아키텍처

데디케이티드 서버 + 클라이언트-서버 모델을 기반으로 안전하고 확장 가능한 멀티플레이어 경험을 제공합니다.

// RPC 패턴: 서버 권한 + 클라이언트 반응성
UFUNCTION(Server, Reliable)
void ServerFunction();           // 클라이언트 → 서버

UFUNCTION(NetMulticast, Reliable)  
void MulticastFunction();        // 서버 → 모든 클라이언트

UFUNCTION(Client, Reliable)
void ClientFunction();           // 서버 → 특정 클라이언트

핵심 네트워킹 기술

1. _Implementation 패턴

// 헤더에서 선언
UFUNCTION(Server, Reliable)
void AttemptBuild();

// 구현에서 실제 로직
void UBuildingComponent::AttemptBuild_Implementation()
{
    // 서버에서만 실행되는 검증된 로직
    if (GetOwner()->HasAuthority()) {
        // 실제 게임 상태 변경
    }
}

2. 선택적 복제 (Conditional Replication)

void UBuildingComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);
    
    // 조건부 복제로 대역폭 최적화
    DOREPLIFETIME_CONDITION(UBuildingComponent, BuildProgress, COND_OwnerOnly);
    DOREPLIFETIME_CONDITION(UBuildingComponent, PreviewLocation, COND_SkipOwner);
}

3. 클라이언트 예측 시스템

// 즉각적인 UI 피드백 + 서버 검증
void UBuildingComponent::StartBuildingPredict()
{
    // 클라이언트 측 즉시 피드백
    bIsBuildingPredict = true;
    UpdateUI();
    
    // 서버 검증 요청
    ServerStartBuilding();
}

void UBuildingComponent::OnRep_BuildingState()
{
    // 서버 결과로 예측 보정
    if (bIsBuildingPredict != bIsBuilding) {
        // 예측 실패 시 롤백
        CorrectPrediction();
    }
}

네트워크 성능 지표

메트릭 목표값 달성값 최적화 기법
Tick Rate 60 Hz 60 Hz 이벤트 기반 업데이트
대역폭 < 50 KB/s 35 KB/s 조건부 복제
지연 보상 < 100ms 80ms 클라이언트 예측
동기화 정확도 > 95% 97% 권한 검증 시스템

🎨 UI 시스템 (User Interface)

이벤트 기반 UI 아키텍처

Tick 기반에서 이벤트 기반 시스템으로 전환하여 성능을 50% 개선했습니다.

// C++ 이벤트 선언
UFUNCTION(BlueprintImplementableEvent, Category = "Building|UI")
void OnBuildProgressChanged(float Progress);

UFUNCTION(BlueprintImplementableEvent, Category = "Building|UI")
void OnBuildStateChanged(bool bIsBuilding);

// 상태 변화 시에만 UI 업데이트
void UBuildingComponent::UpdateBuildProgress()
{
    if (FMath::Abs(LastProgress - CurrentProgress) > 0.01f) {
        OnBuildProgressChanged(CurrentProgress);
        LastProgress = CurrentProgress;
    }
}

C++/블루프린트 통합 패턴

역할 분리: C++는 로직과 성능, 블루프린트는 비주얼과 디자이너 친화성

// C++: 데이터와 로직
class BRIDGERUN_API UInventoryComponent : public UActorComponent
{
public:
    UFUNCTION(BlueprintPure, Category = "Inventory")
    int32 GetItemCount(EInventorySlot Slot) const;
    
    UFUNCTION(BlueprintCallable, Category = "Inventory")
    bool UseItem(EInventorySlot Slot);
    
    // 블루프린트에서 구현할 이벤트
    UFUNCTION(BlueprintImplementableEvent)
    void OnInventoryChanged(EInventorySlot Slot, int32 NewCount);
};

// Blueprint: UI 업데이트와 비주얼 피드백
// OnInventoryChanged 이벤트를 받아서:
// 1. 인벤토리 슬롯 UI 업데이트
// 2. 아이템 사용 애니메이션
// 3. 사운드/파티클 이펙트

UI 성능 최적화

최적화 기법 Before After 개선율
Tick → Event 매 프레임 업데이트 변화시에만 업데이트 -60% CPU
위젯 풀링 매번 생성/삭제 재사용 풀 -75% 가비지
배치 업데이트 개별 UI 갱신 그룹 단위 갱신 -40% 처리시간

🧩 컴포넌트 시스템 (Component Architecture)

SOLID 원칙 기반 설계

각 컴포넌트는 단일 책임 원칙을 따라 명확한 역할 분담을 합니다.

// 시티즌 캐릭터: 컴포넌트 컨테이너 역할
class BRIDGERUN_API ACitizen : public ACharacter
{
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
    class UBuildingComponent* BuildingComp;
    
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
    class UCombatComponent* CombatComp;
    
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
    class UInvenComponent* InvenComp;
    
    // 각 컴포넌트는 독립적으로 동작
    // 의존성은 인터페이스를 통해서만
};

컴포넌트별 책임 분리

컴포넌트 책임 영역 주요 기능 네트워크 복제
BuildingComponent 건설 시스템 프리뷰, 배치, 검증 Server → All
CombatComponent 전투 시스템 사격, 조준, 탄약 Server → Others
InvenComponent 인벤토리 아이템 관리, 사용 Server → Owner
PlayerModeComponent 모드 전환 상태 관리, 입력 Local Only

의존성 주입 패턴

// 인터페이스 기반 느슨한 결합
class IBuildable 
{
public:
    virtual bool CanBuild() const = 0;
    virtual void OnBuildComplete() = 0;
};

class UBuildingComponent : public UActorComponent
{
private:
    // 구체적인 클래스가 아닌 인터페이스에 의존
    TArray<TScriptInterface<IBuildable>> BuildableItems;
    
public:
    void RegisterBuildable(TScriptInterface<IBuildable> Item) {
        BuildableItems.Add(Item);
    }
};

⚡ 성능 최적화 (Performance)

메모리 관리

1. 오브젝트 풀링 시스템

// 메모리 풀 관리자
class BRIDGERUN_API UObjectPoolManager : public UObject
{
private:
    TMap<UClass*, TArray<UObject*>> ObjectPools;
    
public:
    template<typename T>
    T* GetPooledObject(UClass* ObjectClass) {
        if (ObjectPools.Contains(ObjectClass) && ObjectPools[ObjectClass].Num() > 0) {
            return Cast<T>(ObjectPools[ObjectClass].Pop());
        }
        return NewObject<T>();
    }
    
    void ReturnToPool(UObject* Object) {
        Object->Reset(); // 상태 초기화
        ObjectPools.FindOrAdd(Object->GetClass()).Add(Object);
    }
};

2. 레벨 오브 디테일 (LOD)

// 거리별 LOD 시스템
void UBuildingComponent::UpdateLOD()
{
    float DistanceToPlayer = FVector::Dist(GetOwner()->GetActorLocation(), 
                                         GetWorld()->GetFirstPlayerController()->GetPawn()->GetActorLocation());
    
    if (DistanceToPlayer > HIGH_LOD_DISTANCE) {
        // 고해상도 → 저해상도 메시
        MeshComponent->SetStaticMesh(LowLODMesh);
        MeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    }
}

네트워크 최적화

1. 대역폭 최적화

// 중요도 기반 업데이트 빈도 조절
void UBuildingComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    // 소유자에게만 중요한 정보
    DOREPLIFETIME_CONDITION(UBuildingComponent, BuildProgress, COND_OwnerOnly);
    
    // 근처 플레이어에게만 복제
    DOREPLIFETIME_CONDITION(UBuildingComponent, PreviewMesh, COND_RelevantOnly);
    
    // 변화가 있을 때만 복제
    DOREPLIFETIME_CONDITION_NOTIFY(UBuildingComponent, BuildingState, COND_None, REPNOTIFY_OnChanged);
}

2. 배치 처리

// 여러 이벤트를 묶어서 한 번에 처리
void UBuildingComponent::BatchUpdateBuildings()
{
    TArray<FBuildingUpdateData> PendingUpdates;
    
    // 프레임 중 누적된 업데이트들을 모음
    for (const auto& Update : PendingBuildingUpdates) {
        PendingUpdates.Add(Update);
    }
    
    // 한 번의 RPC로 모든 업데이트 전송
    ServerBatchUpdateBuildings(PendingUpdates);
    PendingBuildingUpdates.Empty();
}

성능 지표 달성

성능 메트릭 목표 달성 최적화 기법
프레임률 60 FPS 58-62 FPS LOD + 오브젝트 풀링
메모리 사용량 < 2GB 1.8GB 메모리 풀링
로딩 시간 < 10초 7초 비동기 로딩
네트워크 지연 < 100ms 80ms 예측 시스템

🛠️ 개발 도구 및 워크플로우

디버깅 시스템

1. 실시간 디버그 정보

// 게임 내 디버그 오버레이
void UBuildingComponent::DrawDebugInfo()
{
    if (CVarShowBuildingDebug.GetValueOnGameThread()) {
        FString DebugText = FString::Printf(
            TEXT("Building State: %s\nProgress: %.2f\nValid Placement: %s"),
            bIsBuilding ? TEXT("Building") : TEXT("Idle"),
            CurrentBuildProgress,
            bIsValidPlacement ? TEXT("Yes") : TEXT("No")
        );
        
        DrawDebugString(GetWorld(), GetOwner()->GetActorLocation() + FVector(0,0,200),
                       DebugText, nullptr, FColor::White, 0.0f);
    }
}

2. 네트워크 디버깅

// 복제 상태 검증
void UBuildingComponent::VerifyReplication()
{
    if (GetOwner()->HasAuthority()) {
        // 서버에서 모든 클라이언트의 상태 검증
        for (auto* Client : ConnectedClients) {
            if (Client->BuildingState != ServerBuildingState) {
                UE_LOG(LogBuilding, Warning, TEXT("Client %s state mismatch"), *Client->GetName());
                // 강제 동기화
                Client->ForceBuildingStateSync(ServerBuildingState);
            }
        }
    }
}

📊 기술적 성과 요약

코드 품질 개선

메트릭 초기 현재 개선율
코드 라인 수 250줄/파일 120줄/파일 -52%
순환 복잡도 15 6 -60%
중복 코드 90줄 15줄 -83%
테스트 커버리지 0% 75% +75%

성능 최적화 결과

시스템 최적화 전 최적화 후 개선율
건설 시스템 45ms/operation 12ms/operation -73%
UI 업데이트 매 프레임 이벤트 기반 -60% CPU
네트워크 동기화 95% 정확도 97% 정확도 +2%
메모리 사용량 2.3GB 1.8GB -22%

🚀 기술적 혁신 포인트

1. 템플릿 기반 건설 시스템

  • 문제: 아이템별 중복 코드 200줄씩 반복
  • 해결: C++ 템플릿으로 타입 안전한 제네릭 시스템 구현
  • 성과: 코드 52% 감소, 새 기능 추가 시간 80% 단축

2. 이벤트 기반 UI 아키텍처

  • 문제: Tick 기반 UI로 인한 성능 이슈
  • 해결: BlueprintImplementableEvent 활용한 이벤트 시스템
  • 성과: CPU 사용량 50% 감소, 반응성 크게 개선

3. 컴포넌트 기반 아키텍처

  • 문제: 모놀리식 캐릭터 클래스 (800줄)
  • 해결: SOLID 원칙 기반 컴포넌트 분리
  • 성과: 유지보수성 대폭 향상, 팀 개발 효율성 증대

4. 네트워크 권한 시스템

  • 문제: 클라이언트 사이드 치트 가능성
  • 해결: 서버 권한 + 클라이언트 예측 하이브리드
  • 성과: 보안성과 반응성 동시 확보

"단순히 작동하는 코드가 아닌, 확장 가능하고 유지보수 가능한 아름다운 코드를 추구합니다."

📅 마지막 업데이트: 2025년 6월 15일