//구글콘솔 광고 추가가
728x90
반응형

google-signin-plugin-1.0.4.unitypackage 버전 자체가 2018년이라는 걸 봐도 뭔가 굉장히 쓰고 싶지 않은 느낌이 들긴 한다. 

하지만 딱히 선택권이 없으니 사용했다. 

역시나 오류가 뜨는군. 챗지피티는 돈을 내도 이런 오류 하나 수정하려면 먼 길을 돌고 돌아야 하니 아직까지는 직접 오류들을 찾아 나서는 게 베스트인듯하다. 망할 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는 반성해야 한다. 

 

https://github.com/googlesamples/google-signin-unity/issues/106

 

DllNotFoundException: Unable to load DLL 'native-googlesignin': The specified module could not be found. · Issue #106 · google

Im getting an error when trying to signin with Google using the google-signin-unity plugin. its showing like this in the logcat errors: E Unity : Unable to find native-googlesignin 08-30 12:21:52.7...

github.com

무려 2019년부터 나와 같은 오류를 마주한 사람들이 있었는데, 

생각해보면 이슈에 올려져있는데 왜 google-signin-plugin-1.0.4.unitypackage 깃허브에수정본이 아직까지 올라와 있지 않은 건지 의문이 들었다.

 

Mukikaizoku씨의 말대로 해보니 단번에 해결할 수 있었다. 18개의 따봉이 달려있길래 19개로 만들어 두었다. 


 

 

우선 처음 해야 할 작업은 GoogleSignIn 패키지에서 아래 파일까지 찾아 들어간다.

 

Assets\GoogleSignIn\Editor\m2repository\com\google\signin\google-signin-support\1.0.4

 

 

여기 와보면,

 

이런 파일들이 있을 텐데, 여기서 위처럼 srcaar 확장자를 가지고 있는 파일들(6개)을 전부 arr로 바꿔주어야 한다.

(다른 파일들은 ㄴㄴ

 

 

이렇게 바꿔주고, 유니티로 돌아간다. 

 

 

두 번째로, 유니티 프로젝트창에서 타고 타고 아까 바꿔 뒀던 폴더를 찾아 들어간다. 

 

위처럼 퍼즐 모양 파일을 클릭하면 인스펙터 창이 뜰 텐데, 거기서 Android를 체크해 주고 Apply를 눌러준다. 

 

이렇게 해두면 된다.

 

 

이렇게 되면 끝이다. 빌드시켜서 확인해보면 구글 로그인이 아주 잘되는 걸 확인할 수 있다. 

728x90
반응형
728x90
반응형
Could not resolve all files for configuration ':launcher:releaseRuntimeClasspath'. See the Console for details.

 

뭐가 문제인지 이 오류덕에 한참을 돌고 돌아 빌드를 시켰다.

처음엔 SDK, NDK, JDK 폴더를 다 지우고 다시 유니티허브에서 다운로드하여 보고,

custom main gradle template 문제인가 싶어 꺼보고, 경로가 제대로 안되어 있나 다시 체크하고,

자바 버전도 바꿔보고, Assets > External Dependency Manager > Android > Force Resolve 도 해보고,

gradle 속성에 추가도 해보고, 빌드 설정에서 API 레벨도 높여보고,

키스토어도 새롭게 만들어서 비밀번호도 바꿔보고, 프로젝트도 껐다가 켜보고 ㅎㅎㅎ 원래 이렇게 빌드가 어려웠나.

 

 

https://ksml4.com/fixed-could-not-resolve-all-files-for-configuration-launcherreleaseruntimeclasspath/

여기서도 비슷한 오류길래 해봤지만 실패하고,

 

https://discussions.unity.com/t/could-not-resolve-all-files-for-configuration-launcher-releaseruntimeclasspath/945621

여기서도 나와 같은 오류였지만 해결되지 않아서 또다시 뒤적거리다 알게 된 사실. 

 

생각보다 수정할 게 많았다.

mainTemplate.gradle과 launcherTemplate.gradle, gradle.properties, baseProjectTemplate.gradle, AndroidManifest.xml 전부 수정했다.

 

내 버전 : Unity 2022.3.62f1

알아두기 >> 
Unity 2022.3에서는 Enable Android Libraries 자체가 UI에서 제거됨. 옵션 없음. 내부적으로 자동 처리됨.

 


우선 유니티 셋팅 - Publishing Setting

 

  • 항목상태설명
✅ Custom Main Manifest 켜짐 AndroidManifest.xml 수동 편집 가능
❌ Custom Launcher Manifest 꺼짐 이건 일반적으로 안 쓴데.
✅ Custom Main Gradle Template 켜짐 mainTemplate.gradle 적용 가능
✅ Custom Launcher Gradle Template 켜짐 launcherTemplate.gradle 적용 가능
✅ Custom Base Gradle Template 켜짐 baseProjectTemplate.gradle 적용 가능
✅ Custom Gradle Properties Template 켜짐 gradleTemplate.properties 편집 가능
❌ Custom Gradle Settings Template 꺼짐 필요 없음 (기본 그대로 유지해도 OK)
❌ Custom Proguard File 꺼짐 아직 필요 없음 (릴리즈 최적화 시 사용)

 

  • EDM4U (External Dependency Manager) 설정 확인

>> Assets > External Dependency Manager > Android Resolver > Settings

>> Patch mainTemplate.gradle, Use Jetifier, Enable Auto-resolution 활성화.

>> 유니티 재시작.

 

mainTemplate.gradle

 

기본으로 이렇게 되어있다.

apply plugin: 'com.android.library'

 

여기를 일단,

// ✅ Unity가 라이브러리용으로 쓸 경우를 대비한 조건 처리
def isLibrary = project.hasProperty("android_library") && android_library.toBoolean()
if (isLibrary) {
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

 

이렇게 바꾸면 유니티에서 오류가 뜬다. 바꾸지 말자.

얘보다 안 되는 놈 먼저 해결하는 게 중요하기 때문에 얘는 기본으로 그대로 두고 가자.

 

아래가 수정한 mainTemplate.gradle.

// Unity External Dependency Resolver: Do NOT use this file for android_library builds

apply plugin: 'com.android.library'

**APPLY_PLUGINS**
**INJECT_MANIFEST**

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
// Android Resolver Dependencies Start
    implementation 'com.google.android.gms:play-services-auth:16+' // Assets/GoogleSignIn/Editor/GoogleSignInDependencies.xml:10
    implementation 'com.google.android.gms:play-services-base:18.6.0' // Assets/Firebase/Editor/AppDependencies.xml:17
    implementation 'com.google.firebase:firebase-analytics:22.4.0' // Assets/Firebase/Editor/AuthDependencies.xml:15
    implementation 'com.google.firebase:firebase-app-unity:12.10.1' // Assets/Firebase/Editor/AppDependencies.xml:22
    implementation 'com.google.firebase:firebase-auth:23.2.0' // Assets/Firebase/Editor/AuthDependencies.xml:13
    implementation 'com.google.firebase:firebase-auth-unity:12.10.1' // Assets/Firebase/Editor/AuthDependencies.xml:20
    implementation 'com.google.firebase:firebase-common:21.0.0' // Assets/Firebase/Editor/AppDependencies.xml:13
    implementation 'com.google.signin:google-signin-support:1.0.4' // Assets/GoogleSignIn/Editor/GoogleSignInSupportDependencies.xml:9
// Android Resolver Dependencies End
    **DEPS**
}

configurations {	// ✅ 의존성 충돌 방지용 exclude (중복 Dex 방지)
    all {
        exclude group: 'com.google.guava', module: 'listenablefuture'
    }
}

// Android Resolver Exclusions Start
android {
  packagingOptions {
      exclude ('/lib/arm64-v8a/*' + '*')
      exclude ('/lib/armeabi/*' + '*')
      exclude ('/lib/mips/*' + '*')
      exclude ('/lib/mips64/*' + '*')
      exclude ('/lib/x86/*' + '*')
      exclude ('/lib/x86_64/*' + '*')
  }
}
// Android Resolver Exclusions End
android {
	namespace "com.unity3d.player"		//여기 주석해두면 안됨. 고유한 패키지명 넣어두기.
    ndkPath "**NDKPATH**"
    compileSdkVersion 34	// <-- 버전을 정확하게 써주자.
    buildToolsVersion '34.0.0'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    defaultConfig {
        minSdkVersion 24	// <-- 버전을 정확하게 써주자. 버전을 더 낮추면 또 오류가 떠서 24로 해둠
        targetSdkVersion 34	// <-- 버전을 정확하게 써주자.
        ndk {
            abiFilters "armeabi-v7a", "arm64-v8a"
        }
        versionCode 1
        versionName '1.0'
        consumerProguardFiles 'proguard-unity.txt'
    }

    sourceSets {	// ✅ defaultConfig 블록 **바로 아래**에 추가
        main {
            //manifest.srcFile 'AndroidManifest.xml' //**INJECT_MANIFEST** 해줬기 때문.(수동 지정 대신 자동으로 병합) 주석 대신 그냥 제거해도 됨
        }
    }

    lintOptions {		// 안드로이드 내부에 있어야 함!
        abortOnError false	// <-- 이 줄 추가
    }

    aaptOptions {
        noCompress = unityStreamingAssets.tokenize(', ')	// <-- 이 줄 수정
        ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
    }

    packagingOptions {
        exclude 'META-INF/*'
        exclude 'commonMain/default/manifest'
        pickFirst '**/*.dex' // <-- 이 줄 추가
    }
}

 

 

 

launcherTemplate.gradle

 

apply plugin: 'com.android.application'

android {
	namespace "**내 유니티 프로젝트 이름**"
	ndkPath "**NDKPATH**"
    compileSdkVersion 34 	// 버전 정확하게
    buildToolsVersion '34.0.0'
    
    aaptOptions {
        // 최신 Unity 방식: StreamingAssets 압축 방지
        noCompress = unityStreamingAssets.tokenize(', ')
    }

    defaultConfig {
        applicationId '**APPLICATIONID**'
        minSdkVersion 24		// 버전 정확하게, 여기도 낮게 하면 오류떠서 하나씩 올리다보니 24가 됨
        targetSdkVersion 34		// 버전 정확하게
        versionCode 1
        versionName '1.0'
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    signingConfigs {
        release {
            storeFile file('**자신의 키스토어 위치**')
            storePassword '**키스토어 비밀번호**'
            keyAlias '**자신의 Alias이름**'
            keyPassword '**자신의 비밀번호**'
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt'
        }
    }

    packagingOptions {
        // 중복 manifest 충돌 해결
        exclude 'META-INF/*'
        exclude 'commonMain/default/manifest'
        pickFirst '**/*.dex' // ✅ 추가!
    }
}

dependencies {
    implementation project(':unityLibrary')
}

 

 

 

baseProjectTemplate.gradle

 

여기서는 아래처럼 google(), mavenCentral()이 둘다 있어야 한다.

buildscript {
    repositories {
        google() 			//google(), mavenCentral() 둘다 있어야 함.
        mavenCentral()		//google(), mavenCentral() 둘다 있어야 함.
    }
    
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.2'
    }
}

allprojects {
    repositories {
        google()			//google(), mavenCentral() 둘다 있어야 함.
        mavenCentral()		//google(), mavenCentral() 둘다 있어야 함.
        
    }
}

 

 

AndroidManifest.xml

 

<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

 

 
나는 이렇게 해결됬는데 또 누군가 답을 찾아 돌고 돌아 들어왔다면, 이 끝으로 부디 수정되었길 바란다.

 

728x90
반응형
728x90
반응형

어플을 만들다가 만난 오류 해결 방법 적어둔다.

< 개발 환경 >
- 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. 

 

 

이후 유니티를 재시작하면 오류가 말끔 사라지는 걸 확인할 수 있다.

728x90
반응형
728x90
반응형

오랜만에 상상을 해봤다. 노란색, 초록색, 분홍색 행주를 100개인가 사둔 것을 바라보며.

 

내가 지금 기억하고 있는 저 행주를 구매한 날이 나의 미래에 오는 어느 날이라 한다면, 내가 기억하는 그날의 존재는 무엇일까.

 

현시대를 살면서 예언자라는 단어를 한 번도 안 들어 본 사람은 없을 것이다.

우리가 사는 세상은 누군가에 의해 읽혔고, 앞으로 다가올 미래들이 적혀있는 예언서가 존재한 다는 것.

그것을 말한 사람을 우리는 예언자라 부른다. 지금도 아주 유명한 예언자가 있지 않은가. 노스트라다무스라던가. 바바 반가라던가.

만약 그들이 정말로 미래를 보았다면, 그들은 어떻게 보았을까.

 

끊임없는 형상들이 시간순으로 눈앞에 나타난 걸까? 예언가들의 예언 중에는 구체적인 내용이 아닌 추상적인 내용의 예언도 있다.

시간 또한 정해진 예언들이 존재한다. 그들은 어떻게 시간까지 예언할 수 있었을까. 마치 그날의 시간을 보고 온듯하게. 

 

마치 도래하지 않은 미래를 과거처럼 기억하고 있는 그들의 모습이 나는 단순히 환상을 보았다고 생각하지 않는다.

이런 것을 생각하면서, 만약 내가 지금 기억하고 있는 저 행주를 구매한 날이 과거가 아니라 앞으로 다가오는 어느 날의 미래라 생각해 본다면 꽤나 재밌는 상상이다.

 

내가 행주를 샀다는 기억이 실제로는 10일 후에 내가 사는 날의 미래를 본 것이라면. 나는 나의 기억에서 그날의 날짜를 찾고 있을 것이다. 그날의 시간이 나의 기억이 과거인지, 미래인지를 알려주는 유일한 대답일 테니.

 

기억이라는 단어의 뜻을 제대로 찾아봤다.

어학사전에는 "이전의 인상이나 경험을 의식 속에 간직하거나 도로 생각해냄."이라고 적혀있다.

우리가 과거라고 확신하는 형상이 아직 일어나지 않은 미래라고 가능성을 열어둔다면, 우리는 우리의 기억들을 확신할 수 있을까?

기억이 단순히 나의 과거가 아닌 내 머릿속에 새롭게 새겨진 미래의 경험일 수도 있지 않을까.

 

영화나, 과학 서적들을 보면 "시간은 여러 흐름으로 동시다발적으로 존재할 수 있다."라고 하지 않는가.

만약 내가 생각하고 있는 기억이 미래의 어느 시점과 연결된 감각이고, 동일한 지점의 시각화라면 나는 미래의 순간을 지금 기억하는 이 과거와 연결할 수 있지 않을까.

 

아인슈타인이 말한 일반 상대성 이론을 생각했을 때 중력이 강한 곳에서는 시간이 더 느리게 흐른다고 하지 않는가.

커다랗게 생각하면 같은 우주 공간에 있어도 서로 다른 속도의 시간을 사용하게 되는 것처럼. 어떤 지점에서는 우리의 과거가 지금이 될 수 있고, 미래가 될 수 있다는 것이라 생각한다. 

 

그냥 행주를 보며 잠깐의 상상을 해보았다. 장마의 날씨 덕에 흐릿하게 생각나던 과거의 기억이 오버랩되어 상상하게 되었다.

재밌었다.   

 


 

어젯 밤 산책 중 라이팅이 예뻐서 사진찍어 봤다. 2000년대로 타임워프한 기분이었다.

 

어젯밤에 이걸 보고 지나가면서 스치듯 생각하던 게 오늘의 행주와 연결된 기분이 든다.

역시 생각은 상상과 연결되어 있다. 

 

 

728x90
반응형
728x90
반응형
정적 라우팅과 동적 라우팅
- 정적 라우팅과 동적 라우팅은 IP 주소를 할당하는 방법과 유사하다.

정적 라우팅 - 수동으로 구성된 라우팅 테이블 항목을 통해 수행되는 라우팅.
동적 라우팅 - 자동으로 라우팅 테이블 항목을 만들고, 이를 이용하여 라우팅.

정적 라우팅(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를 경로로 선택) 등등. 

 

728x90
반응형
728x90
반응형

 

며칠 전 인테리어를 끝내고 기존에 있던 가구를 버리고 새로운 소파를 들였다.

그런데 소파가 원래 이렇게 비쌌었나? 마음에 드는 제품들이 200, 300, 500만 원까지 가는 걸 보고 이게 맞나라는 생각이 들었다.

소모되는 가구인데 이 정도 투자를 해야 하나 고민하던 중 발견한 로코코 소파.

우리가 원했던 소파는 합리적인 가격이면서 한국의 미가 담겨있는 디자인이길 바랐다.

쉽지 않은 조합이었는데 이 두 가지 조건을 동시에 만족시키는 소파가 로코코에 있는 게 아닌가. 

샹베리 소파의 나무 곡선에서 기와지붕처럼 느껴지는 라인 부분은, 우리가 찾았던 전통의 미감을 발견하게 해 주었다.

영화 "파묘"에서 나왔던 소파라고 광고하고 있는 걸 보았는데, 거기서도 예쁘더라.

파묘를 봤을 때는 그냥 부잣집 인테리어 소품정도로 스쳐 지나가던 소파를 우리가 사게 되다니. 참 묘한 인연이다.

 

소재는 가죽으로 할지 페브릭으로 할지 고민을 많이 했지만, 오래 쓰기엔 아무래도 가죽이 낫겠다는 생각으로 가죽을 선택했다.

3인과 4인 사이즈를 선택할 수 있었다. 거실의 벽면 길이에 가장 이상적인 비율을 고려했을 때 4인 사이즈가 더 적합할 것 같아서 4인 사이즈를 선택했다. 무엇보다 4인 소파는 프레임 나무가 2개로 분리되어 합쳐진 다는 부분이 마음에 들었다. 

 

한 가지 아쉬운 부분은 처음 소파를 찾아보았을 때 프레임 부분이 통 원목으로 들어갈 줄 알고 평상처럼 사용 가능할 줄 알았던 부분인데, 막상 받아보니 생각보다 좌판 부분이 얇은 구조여서 불가능해 보였다. 이 부분은 여전히 아쉽다. 

 

 

그래도 마음에 드는 부분이 꽤 있다.

1. 소파 쿠션이 단단해서 허리를 잘 받쳐준다. 앉거나 눕기에도 소파의 넓이가 넓기에 여유 있게 사용 가능하다.

2. 가죽 색상을 모카로 했는데 채도가 낮아서 오래 사용해도 질리지 않을 것 같고 답답해 보이지 않는다.

3. 프레임의 원목 색상이 진해서 거실 공간에 무게 중심을 잡아준다.

 

여러모로 집에 오는 지인들이 탐을 내는 소파가 되었다. 우리 눈에만 예뻐 보이는 게 아닌 것 같아 내심 흐뭇했다.

1인 소파도 있었는데 마음 같아서는 들이고 싶었달까.  

 

사용하다 보니, 소파와 연결해 사용할 스툴이 있으면 더 좋았겠다는 생각을 했다. 옆으로 누워서 TV를 보는 것보단, 정방향으로 바라보며 다리를 올리는 게 더 편할 것 같은 기분 때문이었다.

그래도 지금도 만족한다. 가죽 상태도 좋고 원목도 단단해 보여, 꽤 오래 사용하다가 바꿀 때가 되면 가죽만 다시 맞춰도 될 것 같았다. 그때는 페브릭을 선택해 분위기를 바꿔볼 수도 있겠지.

 

로코코 소파는 일단 아주 마음에 든다. 

 

쿠션들이 분리되서 청소할 때 좋음.

 

728x90
반응형
728x90
반응형

내가 제일 좋아하는 여름 과일, 산딸기

 

 

여름이 온 게 실감이 되는 날씨다.

여름 하면 산딸기 아니겠는가. 폭신한 산딸기 하나 입에 넣고 오물거리면 톡톡 터지는 알겡이들로 즐거움을 얻는다. 

 


백합이 여기저기 피어나고 있다.

 

 

백합이 피는 계절이다. 붉은색, 노란색, 흰색.

백합의 아름다운 색깔들을 보고 있으면 여름도 예뻐보이는 것 같기도 하고? 

 


전혀 변하지 않는 공간

 

 

여긴, 어떻게 늘 이렇게 같을 수 있을까.

사계절 중 가장 예쁜 색으로 이곳을 담으려면 여름에 와야 한다.

추억이 담겨 있는 장소.

오랫동안 사랑했던 드라마 속 배경같이, 나의 추억이 시퀀스처럼 흐른다. 

 


여름이다.

 

 

태극기가 눈에 보였다. 언제 또 이런 예쁜 태극기를 담을 수 있을까 싶어 사진으로 남겼다.

 


학교들을 볼 때마다 우리의 학창시절이 떠올리지 않는가.

 

 

이제 졸업한지 꽤 지난 나이인데 학교들은 어디서 만나도 내 추억이 떠오른다. 꼭 좋은 기억들만 있는 것도 아닌데,

추억은 추억인지 자꾸만 그 시절 내가 그리워진다. 지나간 청춘이 괜히 아쉽다. 

 


여름의 간식.

 

 

감자 좋아하니? 누군가 물으면 좋아한다 말해야 되나.

김에 싸서 먹으면 은근히 맛있는 걸 사람들은 알까. 오이지도 시원하고, 수박도 달달하고.

여름이 진짜 왔나보다.

 

 

 

728x90
반응형
728x90
반응형

며칠 전 아빠가 생일 선물이라며 통장과 함께 돈을 주셨다. 

아빠는 우리의 생일에 맞춰서 항상 적금을 들어 두신다. 

1년짜리 적금이 만료되는 날, 우리는 아빠의 사랑을 그 어떤 조건도 없이 받게 된다. 

작년인가 재작년에는 그 돈으로 색소폰을 구매했었는데, 이번에는 뭘 해볼까 고민하다 나의 혈육과 팔찌를 맞추기로 했다. 

평소 십자가 하나쯤은 지니고 싶다는 혈육의 말을 기억해 우리는 십자가 모양을 팔찌를 찾았다. 

 

사실 나는 우리만 할 것 같은 독특한 디자인을 원했지만, 반려되었다. 

"G-Dragon 정도 돼야 감당할 수 있는 디자인"이라며, "안돼, 돌아가." 소리를 들은 나는 풀이 죽었지만 우리 팔목에 맞는 사이즈는 이미 품절이라는 소식을 듣고 다시 회복했다. 어차피 안 되는 거였다면, 굳이 좌절할 필요 없지. 

 

십자가 팔찌가 생각보다 예쁜 게 없었다. 어떤 건 이상하게 길어서 촌스럽고, 어떤 건 디자인 자체가 별로였다. 

그러다 발견한 "스튜디오 코랄". 

십자가 크기가 꽤 작아보이긴 했지만, 깔끔한 디자인에 마음이 들었다. 

 

스튜디오 코랄은 한남과 안국, 두 군데에 있는 주얼리 숍이다. 

예약제로 운영된다는 말에 최대한 빠른 주말로 예약을 잡고 다녀왔다. 우리는 종로를 좋아해서 안국점을 선택했다. 

종로의 햇살을 가득 받으며 스튜디오로 향했다. 

 

비도 안오고 색깔이 예뻤다.

 

 

 

알고 보니, 우리가 좋아하는 팥빙수 가게 근처에 있어 어렵지 않게 도착했다. 

인사를 하고 팔찌 종류들을 쭉 확인해 보며 십자가 모양을 자세하게 들여봤다. 

역시나 작고 소중한 십자가 하나가 팔찌 한가운데 자리 잡고 있었다. 

"너무 작은가?" 고민하고 있는데, 새로운 디자인 하나를 골라 드는 나의 혈육.

"십자가 하나를 몸에 지니고 싶다 했잖아?"라는 말과 함께 쳐다보니 멋쩍은 미소를 하고 있길래 웃겼다.

그래, 뭐 마음에 드는 걸 하면 되지라는 생각도 잠시. 디자인에 대한 고민이 오래되자 우리는 엄마, 아빠한테 십자가 팔찌와 함께 다른 팔찌들의 사진을 찍어서 조언을 듣고자 했다.

 

그러다 아주 놀라운 상황에 직면하게 된다.

 

"십자가에만 초점이 맞춰지고 다른 팔찌들은 초점이 안맞는데?" 

"세 번이나 찍었는데 안 맞아. ㅋㅋㅋㅋㅋㅋ"

 

다른 팔찌들을 클릭해서 맞춰봐도 초점이 안맞는다.

마치 해리포터에서 지팡이가 주인을 고르는 것처럼 선택되는 기분을 느낀 우리는 고민을 그만두기로 했다.

집에 와서 찍어둔 동영상을 확인하다가 갑자기 조명을 바꾼 것처럼 십자가 팔찌에만 햇빛이 들어오는 것을 발견했을 때는 너무 어이가 없었다. 우리가 이런 걸 믿는 편은 아니지만, 이 정도면 좀 무서울 정도랄까.

 

손목이 얇아서 처음에는 줄을 줄여볼 까 고민했다. 그렇다고 딱 맞게 하기엔 답답하고. 그냥 기본으로 맞추기로 했다.

한 달 쯤 기다리면 받을 수 있다는 말을 듣고 결제했다.

택배도 가능하다고 했지만, 왠지 직접 가서 받아보는 게 더 의미가 있을 것 같아 그때쯤 다시 들르기로 했다.

에코백도 주셔서 동네에서 휘뚜루마뚜루 들고 다닐 것 같다.

 

부디 안질리고 오래 하고 다니길 바래본다.

 

 

스튜디오 코랄 안국점

 

 

728x90
반응형

+ Recent posts