# 빌드 오류 해결 가이드

**날짜**: 2025-11-29
**프로젝트**: NeoRylClient

---

## 현재 발생 오류

### 1. LNK2005 오류 (중복 정의)

**증상**: 여러 런타임 라이브러리에서 동일한 함수가 중복 정의됨

```
error LNK2005: __recalloc이(가) MSVCRT.lib(MSVCR100.dll)에 이미 정의되어 있습니다.
error LNK2005: _sprintf이(가) MSVCRT.lib(MSVCR100.dll)에 이미 정의되어 있습니다.
error LNK2005: _printf이(가) MSVCRT.lib(MSVCR100.dll)에 이미 정의되어 있습니다.
... (총 32개 중복 정의 오류)
```

**원인**: 다음 라이브러리들이 동시에 링크됨
- `LIBCMTD.lib` (Multi-threaded Debug Static CRT)
- `MSVCRT.lib` (Multi-threaded Release DLL CRT)
- `MSVCRTD.lib` (Multi-threaded Debug DLL CRT)

### 2. LNK2019 오류 (미해결 외부 참조)

```
error LNK2019: "unsigned long __cdecl ParsePacket::HandleUserLogin(...)"
외부 기호에서 확인하지 못했습니다.
```

**원인**: `ParsePacket::HandleUserLogin` 함수가 구현되지 않음

---

## 해결 방법

### ✅ 해결 방법 1: 런타임 라이브러리 통일 (권장)

모든 프로젝트에서 **동일한 런타임 라이브러리**를 사용해야 합니다.

#### Debug 빌드 설정

**방법 A**: Multi-threaded Debug DLL (/MDd) 사용 (권장)

1. **NeoRylClient 프로젝트 속성 열기**
   - 솔루션 탐색기에서 `NeoRylClient` 우클릭 → 속성

2. **구성: Debug, 플랫폼: Win32 선택**

3. **C/C++ → 코드 생성 → 런타임 라이브러리**
   - 현재: `다중 스레드 디버그 (/MTd)` 또는 혼합 상태
   - **변경**: `다중 스레드 디버그 DLL (/MDd)`

4. **확인 클릭**

5. **모든 의존 프로젝트도 동일하게 설정**:
   ```
   - MemoryManager
   - Caldron
   - CrossM
   - Effect
   - SoundLib
   - Zalla3D Base Class
   - Zalla3D Scene Class
   - CharacterActionControl
   - GlobalScript
   - ScriptEngine
   - LUA
   ```

**방법 B**: Multi-threaded Debug Static (/MTd) 사용

- 모든 프로젝트를 `/MTd`로 통일
- 장점: 배포 시 MSVCR100D.dll 불필요
- 단점: 실행 파일 크기 증가

#### Release 빌드 설정

**Release 빌드도 동일하게**:
- **권장**: `/MD` (Multi-threaded DLL)
- **대안**: `/MT` (Multi-threaded Static)

---

### ✅ 해결 방법 2: 특정 라이브러리 무시 (임시 해결)

**주의**: 이 방법은 근본적인 해결책이 아니며, 런타임 오류를 발생시킬 수 있습니다.

1. **프로젝트 속성 → 링커 → 입력**

2. **특정 기본 라이브러리 무시**에 다음 추가:
   ```
   LIBCMTD.lib;MSVCRT.lib
   ```
   또는
   ```
   LIBCMT.lib;MSVCRTD.lib
   ```

**장점**:
- 빠른 임시 해결
- 설정 변경 최소화

**단점**:
- 런타임 오류 가능성
- 메모리 관리 문제 발생 가능
- 디버깅 어려움

---

### ✅ 해결 방법 3: ParsePacket::HandleUserLogin 오류 해결

#### 원인 분석

```cpp
// AuthHandler.cpp에서 호출
bool ParseUserLogin(ClientNet::CClientEventHandler* lpHandler, PktBase* lpPktBase)
{
    // ParsePacket::HandleUserLogin 호출
    ParsePacket::HandleUserLogin(lpPktBase, ...);
}
```

`ParsePacket::HandleUserLogin` 함수가 정의되지 않았거나 링크되지 않음.

#### 해결 방법

**1) 함수 구현 찾기**

```bash
# 함수가 정의된 파일 검색
grep -r "HandleUserLogin" --include="*.cpp" --include="*.h"
```

**2) 라이브러리 링크 확인**

- `ParsePacket` 네임스페이스가 `GlobalScript` 프로젝트에 있는 경우
- `GlobalScript.lib`가 링크되어 있는지 확인

**프로젝트 속성 → 링커 → 입력 → 추가 종속성**:
```
../../Library/Debug/GlobalScript.lib  (Debug)
../../Library/Release/GlobalScript.lib  (Release)
```

**3) 함수가 없는 경우 - 스텁 구현 추가**

```cpp
// GlobalScript/Network/ParsePacket.cpp (또는 적절한 파일)

namespace ParsePacket
{
    unsigned long HandleUserLogin(
        PktBase* pPacket,
        unsigned long* pSessionID,
        unsigned long* pUserIndex,
        CHAR_VIEW* pCharView,
        sGuildData* pGuildData,
        unsigned char* pGuildMark,
        long* pGuildMarkCRC,
        int* pAuthLevel,
        unsigned short* pServerID,
        unsigned char* pResult,
        unsigned char* pIPAddress,
        unsigned char* pMACAddress,
        unsigned long* pLoginTime)
    {
        // TODO: 구현 필요
        // 현재는 임시 스텁 함수

        if (pResult)
            *pResult = 0;  // 성공

        return 0;
    }
}
```

---

## 단계별 해결 절차

### Step 1: 현재 상태 확인

1. **솔루션 탐색기**에서 각 프로젝트 확인
2. 프로젝트 우클릭 → 속성
3. C/C++ → 코드 생성 → 런타임 라이브러리 확인
4. 각 프로젝트의 설정 기록:

```
프로젝트명                  Debug 설정       Release 설정
=========================================================
NeoRylClient                /MTd (?)        /MD (?)
GlobalScript                /MTd (?)        /MT (?)
Caldron                     /MTd (?)        /MT (?)
...
```

### Step 2: 런타임 라이브러리 통일

**Debug 빌드 - 모든 프로젝트를 /MDd로 변경**:

1. 솔루션 탐색기에서 각 프로젝트 선택
2. 프로젝트 우클릭 → 속성
3. 구성: Debug
4. C/C++ → 코드 생성 → 런타임 라이브러리 → **다중 스레드 디버그 DLL (/MDd)**
5. 확인

**Release 빌드 - 모든 프로젝트를 /MD로 변경**:

1. 구성: Release
2. C/C++ → 코드 생성 → 런타임 라이브러리 → **다중 스레드 DLL (/MD)**
3. 확인

### Step 3: 솔루션 정리 및 재빌드

1. **빌드 → 솔루션 정리**
2. **빌드 → 솔루션 다시 빌드**

### Step 4: HandleUserLogin 오류 해결

빌드 후 여전히 `HandleUserLogin` 오류가 발생하면:

1. **함수 검색**:
   ```bash
   grep -r "HandleUserLogin" --include="*.cpp"
   ```

2. **함수가 없으면 구현 추가** (위의 스텁 코드 참조)

3. **GlobalScript 프로젝트 재빌드**

4. **NeoRylClient 프로젝트 재빌드**

---

## 빠른 해결 (추천 순서)

### 🥇 1순위: 런타임 라이브러리 통일 (가장 안전)

```
모든 프로젝트:
  Debug 빌드 → /MDd
  Release 빌드 → /MD
```

**실행 방법**:
1. 각 프로젝트 속성에서 하나씩 변경
2. 또는 프로젝트 파일(.vcxproj) 직접 수정

**vcxproj 파일 직접 수정**:

```xml
<!-- Debug 빌드 -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  <ClCompile>
    <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
  </ClCompile>
</ItemDefinitionGroup>

<!-- Release 빌드 -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  <ClCompile>
    <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
  </ClCompile>
</ItemDefinitionGroup>
```

### 🥈 2순위: 라이브러리 무시 (임시)

**프로젝트 속성 → 링커 → 입력**:
```
특정 기본 라이브러리 무시: LIBCMTD.lib;MSVCRT.lib
```

**또는 vcxproj 파일**:
```xml
<Link>
  <IgnoreSpecificDefaultLibraries>LIBCMTD.lib;MSVCRT.lib</IgnoreSpecificDefaultLibraries>
</Link>
```

### 🥉 3순위: HandleUserLogin 스텁 구현

위의 "해결 방법 3" 참조

---

## 런타임 라이브러리 비교

| 옵션 | 설명 | DLL 필요 | 크기 | 권장 |
|------|------|----------|------|------|
| **/MD** | Multi-threaded DLL (Release) | MSVCR100.dll | 작음 | ✅ Release |
| **/MDd** | Multi-threaded Debug DLL (Debug) | MSVCR100D.dll | 작음 | ✅ Debug |
| **/MT** | Multi-threaded Static (Release) | 불필요 | 큼 | 배포용 |
| **/MTd** | Multi-threaded Debug Static (Debug) | 불필요 | 큼 | - |

**현재 문제**: `/MTd`, `/MD`, `/MDd`가 혼재되어 있음

**해결**: 모든 프로젝트를 `/MDd` (Debug) 또는 `/MD` (Release)로 통일

---

## 자동화 스크립트 (PowerShell)

### 모든 vcxproj 파일의 런타임 라이브러리 변경

```powershell
# fix_runtime_library.ps1

$vcxprojFiles = Get-ChildItem -Recurse -Filter "*.vcxproj"

foreach ($file in $vcxprojFiles) {
    Write-Host "Processing: $($file.FullName)"

    $content = Get-Content $file.FullName -Raw

    # Debug 빌드를 /MDd로 변경
    $content = $content -replace '<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>', '<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>'

    # Release 빌드를 /MD로 변경
    $content = $content -replace '<RuntimeLibrary>MultiThreaded</RuntimeLibrary>', '<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>'

    Set-Content -Path $file.FullName -Value $content
}

Write-Host "완료! 모든 프로젝트가 DLL 런타임으로 변경되었습니다."
```

**사용 방법**:
```powershell
cd "S:\Source\Row\ROW Project\src\Client"
.\fix_runtime_library.ps1
```

---

## 검증 방법

### 1. 링크 오류 확인

빌드 후 다음 오류가 **사라져야** 함:
```
error LNK2005: __recalloc이(가) ... 이미 정의되어 있습니다.
error LNK2005: _sprintf이(가) ... 이미 정의되어 있습니다.
```

### 2. 외부 참조 오류 확인

다음 오류만 남아야 함 (HandleUserLogin):
```
error LNK2019: "unsigned long __cdecl ParsePacket::HandleUserLogin..."
```

이후 HandleUserLogin 구현 추가

### 3. 빌드 성공 확인

```
========== 빌드: 성공 12, 실패 0, 최신 0, 건너뜀 0 ==========
```

---

## 추가 문제 해결

### 문제: 여전히 LNK2005 오류 발생

**해결**:
1. **솔루션 정리** 후 재빌드
2. **중간 파일 삭제**:
   ```
   S:\Source\Row\ROW Project\src\Client\Intermediate\
   ```
3. **출력 디렉토리 정리**:
   ```
   S:\Source\Row\ROW Project\Game\
   ```

### 문제: MSVCR100D.dll을 찾을 수 없음

**원인**: `/MDd` 사용 시 Debug DLL 필요

**해결**:
1. Visual Studio 2010 Redistributable 설치
2. 또는 DLL을 실행 파일과 같은 디렉토리에 복사
3. 또는 `/MTd`로 변경 (Static 링크)

---

## 요약

### 🎯 권장 해결 순서

1. ✅ **모든 프로젝트 런타임 라이브러리 통일**
   - Debug: `/MDd`
   - Release: `/MD`

2. ✅ **솔루션 정리 및 재빌드**
   ```
   빌드 → 솔루션 정리
   빌드 → 솔루션 다시 빌드
   ```

3. ✅ **HandleUserLogin 함수 구현 또는 링크**
   - GlobalScript.lib 링크 확인
   - 또는 스텁 함수 추가

4. ✅ **재빌드 및 테스트**

### 🚨 주의사항

- **절대 하지 말 것**: 서로 다른 CRT를 혼합 사용
- **런타임 라이브러리는 모든 프로젝트에서 동일해야 함**
- **임시 해결책(라이브러리 무시)은 프로덕션에서 사용 금지**

---

**작성일**: 2025-11-29
**프로젝트**: NeoRylClient
