역시나 오류가 뜨는군. 챗지피티는 돈을 내도 이런 오류 하나 수정하려면 먼 길을 돌고 돌아야 하니 아직까지는 직접 오류들을 찾아 나서는 게 베스트인듯하다. 망할 chatgpt.
내가 경험한 오류는
signIn 예외: Unable to load DLL 'native- googlesignin'. Tried the load the following dynamic libraries: unable to load dynamic library 'native-googlesignin' because of "failed to open the requested dynamic library (0x06000000) dlerror() = dlopen failed : library "native-googlesignin" not found.
좋아. 뭔가 문제가 있구나 하면서 32000원을 낸 chatGPT를 켰다.
쉽게 해결해보자는 마인드로 해결방법을 찾은 인공지능은 나에게 똥을 가져다줬고, 돌고 돌다 이러다 팽이가 될 것 같아서 원래 하던 데로 구글에 물어봤다. 단번에 나오는 해결책. gpt는 반성해야 한다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="내 유니티 패키지 이름">
<application
android:label="@string/app_name"
android:allowBackup="true"
android:theme="@style/UnityThemeSelector"
android:exported="true"> <!-- ✅ Android 12 이상 대응 -->
<!-- ✅ 앱 실행 액티비티 (홈 아이콘) -->
<activity
android:name="com.unity3d.player.UnityPlayerActivity"
android:label="@string/app_name"
android:exported="true"
android:theme="@style/UnityThemeSelector">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Google 로그인 Federated Sign-In Activity -->
<activity
android:name="com.google.firebase.auth.internal.FederatedSignInActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="내 유니티 패키지 이름. 위 2번째 줄에 써둔 이름과 같게" /> 🔸 Google redirect URI 대응 -->
</intent-filter>
</activity>
<!-- Firebase 서비스용 메타데이터 -->
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
</manifest>
원래는 android:icon="@mipmap/ic_launcher" 이렇게 아이콘도 적어 줬었는데 리소스 충돌 나서 제거해줌.
gradle.properties (gradleTemplate.properties)
org.gradle.jvmargs=-Xmx6144m // 수정
org.gradle.parallel=true
# Android Resolver Properties Start
android.useAndroidX=true
android.enableJetifier=true
# Android Resolver Properties End
unityStreamingAssets=.unity3d,.ress,.resource,.obb // 수정
android.suppressUnsupportedCompileSdk=34 //추가
**ADDITIONAL_PROPERTIES**
처음에는 android.enableR8=false 이것도 같이 적어뒀는데, 유니티에서
The option 'android.enableR8' is deprecated. It was removed in version 7.0 of the Android Gradle plugin.
이 오류가 떴다. android.enableR8=false 이게 더 이상 유효하지 않다는 말이라 해서 삭제시켜 줬다.
나는 현재 classpath 'com.android.tools.build:gradle:7.4.2' 쓰고 있기 때문에 Gradle Plugin 7.x 대에선 R8을 무조건 사용하도록 강제되어 있다 해서 의미가 없기 때문에 지워주는 게 맞다.
위에 어떤 이가 이 버전을 4.1.3버전인가로 낮춰서 이 오류를 해결 한 사람이 있었는데, 찾아보니 Android 12,13 대응이 안된다고 추천하지 않는다 했다.
수정해 준 org.gradle.jvmargs=-Xmx6144m 이 부분의 Xmx6144m은 "Gradle 빌드시 사용 가능한 최대 메모리를 6144mb(6GB)로 설정해 주는 부분인데, Firebase + Google SDK 같이 복잡한 종속성이 있을 경우 메모리를 많이 쓰기 때문에 이렇게 설정하면 빌드 오류를 줄일 수 있다고 한다.
근데 이 부분은 이렇게 둬도 될지 나중에 확인을 다시 해봐야 될 듯?
++
Xmx6114m 설정은 지금처럼 Firebase + Google SignIn + Unity IL2CPP 빌드 구조에서는 오히려 추천되는 설정이라 한다.
pc의 실제 RAM 보다 높게 잡으면 문제가 될 수 있다 한다.
▶ 권장 기준
PC RAM 용량
추천 JVM 설정
8GB 이하
Xmx4096m (4GB)
16GB 이상
Xmx6144m 또는 Xmx8192m (6~8GB)
32GB 이상
Xmx8192m 이상도 OK
이렇게 했는데도 오류가 있다면 gradle 캐시가 재사용되고 있을 수도 있으니까 캐시를 강제로 삭제시켜 주자.
우선 Unity 끄자.
그 다음, 아래 폴더 전부 삭제: >> C:\Users\내 사용자 이름 폴더\.gradle\caches >> C:\Users\ 내 사용자 이름 폴더 \.gradle\caches\transforms-3 >> C:\Users\ 내 사용자 이름 폴더 \UnityProject\내프로젝트 이름\Library >> C:\Users\ 내 사용자 이름 폴더 \UnityProject\내프로젝트 이름\obj
나는 이렇게 해결됬는데 또 누군가 답을 찾아 돌고 돌아 들어왔다면, 이 끝으로 부디 수정되었길 바란다.
< 개발 환경 > - Unity 버전: 2022.3.51f1 (LTS) - Firebase Unity SDK: v12.10.1 - Google Sign-In Unity SDK: v1.0.4 - 기기 플랫폼: Android
firebase 초기화시키고 구글 로그인과 연동하기 위해 google-signin-plugin-1.0.4 패키지를 임포트 하고 난 뒤 유니티에선 21개의 오류들이 날 기다리고 있었다.
Library\PackageCache\com.unity.timeline@c58b4ee65782\Editor\Actions\IAction.cs(23,41):
error CS0121: The call is ambiguous between the following methods or properties:
'System.MissingExtensions.GetCustomAttribute<T>(System.Reflection.MemberInfo, bool)' and 'System.Reflection.CustomAttributeExtensions.GetCustomAttribute<T>(System.Reflection.MemberInfo, bool)'
처음에는 유니티 버전 6000.1.2f1를 사용하고 있던 상태라 오류를 따라 manifest.json에서 "com.unity.timeline" 도 삭제하고 Library 폴더도 삭제하고 다해봤는데 점점 꼬여갔다. 나중엔 텍스트 메시 프로가 갑자기 유니티에서 증발해 버리는 걸 보았다.
그래서 안전빵으로 유니티 버전을 원래 사용하던 2022.3.51f1 (LTS)로 다시 만들었는데, 또다시 같은 오류들을 만날 줄이야. 한번 피했는데 다시 만나면 수정해야지 라는 생각으로 정리해 본다.
유니티 버전 6000.1.2f1에서 만난 오류들
유니티 버전 2022.3.51f1에서 만난 오류들
생각보다 해결 방법은 간단했다.
혹시나 이 오류들 때문에 찾아왔다면 이글의 끝에는 모든 오류들이 사라진 걸 볼 수 있을 것이다.
1. 일단 첫 번째 오류였던 CS0433 Task<T> 중복 오류.
CS0433: The type 'Task<T>' exists in both 'Unity.Tasks.dll' and 'netstandard'
▶ 오류 요약.
GoogleSignIn SDK에는 자체 Unity.Tasks.dll이 포함되어 있음.
하지만 Unity 2022.3.51f1은 이미 .NET Standard 2.1 + C# Tasks 기반으로 동작함
이게 충돌해서 Task<T> 타입 중복 오류가 발생
▶ 원인 : GoogleSignIn SDK 또는 Parse SDK 내부에 포함된 Unity.Tasks.dll이 Unity 자체의 .NET Standard와 충돌.
▶ 해결 방법 : 프로젝트 내에서 Unity.Tasks.dll 을 찾아 삭제하면 된다.
- 나의 경우는 Assets/Parse/Plugins/Unity.Tasks.dll에서 찾아서 삭제했다. 여기 없으면 Assets/GoogleSignIn/Plugins/Unity.Tasks.dll 여기도 확인해 보자. 그도 아니면 그냥 프로젝트 창에서 검색 ㄱㄱ.
2. 두 번째 오류였던 CS0121 GetCutomAttribute 충돌 오류.
error CS0121: The call is ambiguous between the following methods or properties:
'System.MissingExtensions.GetCustomAttribute<T>(System.Reflection.MemberInfo, bool)'
and
'System.Reflection.CustomAttributeExtensions.GetCustomAttribute<T>(System.Reflection.MemberInfo, bool)'
▶ 의미 : 두 개의 GetCustomAttribute<T> 메서드가 동일한 시그니처로 존재해서 컴파일러가 어떤 걸 써야 할지 모르겠다며 충돌을 일으키고 있는 것.
▶ 원인 : Unity Timeline 패키지가 사용하는 Reflection API가 Firebase SDK 또는 Google SDK와 타입 충돌 발생.
▶ 해결 방법 : Window > Package Manager → Timeline 패키지 제거. 만약 Timeline 기능이 필요하다면 버전을 1.8.5 이상 수동 설치해야 된단다. 나의 경우는 일단 필요 없어서 Remove 시켰다.
3. 세 번째 오류이자 마지막 오류 Visual Scripting DLL 충돌 오류.
CS0433: The type 'X' exists in both 'A.dll' and 'B.dll'
유니티 버전 6000에서 이 오류 때문에 머리가 아팠었는데 생각보다 해결 방법이 간단했다.
▶ 의미 : Unity 내부 패키지 중 하나인 Visual Scripting이 사용하는 DLL과, 지금 설치한 GoogleSignIn SDK의 DLL이 충돌하고 있다는 뜻.
▶ 원인 : Unity 2022.3 이후 버전에서 Visual Scripting 패키지가 GoogleSignIn SDK 의 내부 DLL들과 충돌.
▶ 해결 방법 : Visual Scripting 패키지 제거.
: 유니티 상단 메뉴 Window > Package Manager > In Project > Visual Scripting 선택 > Remove.
정적 라우팅(static routing) - 사용자가 수동으로 직접 채워 넣은 라우팅 테이블의 항목을 토대로 라우팅. ex) 10.0.0.0/24로 향하는 패킷을 192.168.1.1 게이트웨이로 정적 라우팅.
동적 라우팅(dynamic routing) - 네트워크의 규모가 커지고 관리해야 할 라우터가 늘어나면 정적 라우팅마능로는 관리가 힘듦. >> 입력 실수가 발생할 수 있음. >> 입력 실수가 없어도 라우팅 경로상에 예상치 못한 문제가 발생할 경우 경로 우회가 어려움. (유연성 떨어짐)
동적 라우팅(dynamic routing)
- 자동으로 라우팅 테이블 항목을 만들고, 이를 이용하여 라우팅.
- 라우팅 프로토콜(routing protocol) 이용. >> 라우터끼리 자신들의 정보를 교환하며 패킷이 이동할 최적의 경로를 찾기 위한 프로토콜.
- 동적 라우팅을 하면 라우팅 테이블 항목이 수시로 변할 수 있음. >> 라우팅 테이블의 항목을 수동으로 입력할 필요 없음. >> 네트워크 경로상에 문제가 발생했을 때 이를 우회할 수 있게 경로가 자동으로 갱신.
라우터들의 집단 네트워크, AS(Autonomous System)
- 동적 라우팅과 라우팅 프로토콜을 이해하기 위한 배경 지식.
- 한 회사나 단체에서 관리하는 라우터 집단. >> AS마다 인터넷상에서 고유한 AS 번호(ASN : Autonomous System Number)가 할당. >> AS 번호는 사설 IP 주소처럼 사설 AS 번호도 있지만, 일반적으로 "AS 번호"는 고유한 AS 번호를 지칭.
- 한 AS 내에는 다수의 라우터가 존재. >> 라우터들은 AS 내부에서만 통신할 수도 있고, AS 외부와 통신할 수도 있음. >> AS 외부와 통신할 경우 AS 경계에서 AS 내외로 통신을 주고받을 수 있는 "특별한 라우터"를 이용. >> 이 "특별한 라우터" = AS 경계 라우터(ASBR : Autonomous System Boundary Router)
라우팅 프로토콜(routing protocol)
- 라우터끼리 자신들의 정보를 교환하며 패킷이 이동할 최적의 경로를 찾기 위한 프로토콜.
- 라우팅 프로토콜의 종류.
IGP(Interior Gateway Protocol)
- AS 내부에서 수행 (ex. RIP와 OSPF) * RIP : 최적의 경로를 선정하는 과정에서거리 벡터를 사용. * OSPF : 최적의 경로를 선정하는 과정에서링크 상태를 사용.
EGP(Exterior Gateway Protocol)
- AS 외부에서 수행 (ex. BGP)
RIP : 거리 벡터 기반 라우팅 프로토콜
- "거리"는 패킷이 경유한 라우터의 수, 즉 홉의 수를 의미. - 특정 수신지까지 도달하기 위해 "홉 수가 가장 적은 경로"를 최적의 경로라고 판단. - 홉 수가 적을수록 라우팅 테이블상의 메트릭 값도 작아짐. - 주기적으로 인접 라우터끼리 경로 정보 교환, 라우팅 테이블 갱신, 특정 수신지까지의 홉 수 계산.
OSPE : 링크 상태(link state) 기반 라우팅 프로토콜
- 현재 네트워크 구성을 마치 지도처럼 그린 뒤, 최단거리를 찾아 최적의 경로를 선택.
- 현재 네트워크의 상태(링크 정보)를 그래프의 형태로 저장. >> 링크 상태 데이터 베이스(LSDB: Link State DataBase)에 저장. >> 라우터들의 연결 관계, 연결 비용 등 현재 네트워크의 상태를 그래프로 표현하기 위한 데이터 저장.
- 대역폭을 기반으로 메트릭을 계산하여 최적의 경로를 결정. >> 대역폭이 높은 링크일수록 메트릭이 낮은 경로로 인식됨.
** RIP는 라우팅 테이블 갱신을 위해 주기적으로 라우터 간 통신이 수행되지만 OSPE는 네트워크 구성 변경 시 라우팅 테이블이 갱신된다.
EGP : BGP(Border Gateway Protocol)
- AS 간의 통신에서 사용되는 대표적인 프로토콜.
- 엄밀하게는 AS 간의 통신이 "가능한" 프로토콜 - BGP로 AS 내 라우터 간 통신도 가능. >> eBGP(external) BGP - AS 간의 통신을 위한 BGP. >> iBGP(internal) BGP - AS 내의 통신을 위한 BGP.
-피어링(peering)이라는 과정을 거쳐야 함. >> 다른 AS와의 BGP 연결을 유지하기 위해서 BGP 라우터끼리 피어가 되도록 연결되는 과정.
유의점 - BGP는 RIP와 OSPF에 비해 최적의 경로를 결정하는 과정이 복잡하고, 일정하지 않은 경우가 많음. - 경로 결정 과정에서 수신지 주소와 더불어 다양한 "속성"과 "정책"이 고려되기 때문임. - BGP의 속성은 경로에 대한 부가 정보
BGP의 속성(attribute) 대표적인 3가지
AS-PATH
- 메시지가 수신지에 이르는 과정에서 통과하는 AS들의 목록. - 메시지가 AS를 거칠 때마다, AS-PATH에는 거쳐 간 AS가 추가. - BGP는 RIP처럼 단순 "거리"가 아닌, 어디를 거쳐 어디로 이동하는 지를 나타내는 "경로"를 고려. - 이런 점에서 경로 백터(path vector) 라우팅 프로토콜의 일이라 부르기도 함.
NEXT-HOP
- 홉, 다음으로 거칠 라우터의 IP 주소를 의미.
LOCAL-PREF
- LOCAL PREFerence의 약자, 말 그대로 지역 선호도를 의미. - AS 외부 경로 선택에 있어 AS 내부에서(local) 어떤 경로를 선호할지(preference)에 대한 척도. - 일반적으로 AS-PATH나 NEXT-HOP 속성보다 우선시. - LOCAL-PREF 값은 AS 관리 주체가 설정하는 정책의 영향을 받음.
* 정책(policy) - AS 관리 주체에 따라 각기 다른 상이한 정책 사용 가능. ex. 특정 AS 우대 정책, 특정 AS 차단 정책, 보안/ 안정성 우선 정책(속도는 느릴지라도 더 안전하고 안정적인 AS를 경로로 선택), 성능 우선 정책(송수신 지연 시간이 적고 대역폭이 높은 AS를 경로로 선택) 등등.