오호라! 이거지!!

블루투스 이어폰 PC에 자동 연결 방법 본문

쇼핑, 사용기

블루투스 이어폰 PC에 자동 연결 방법

노네발 2026. 9. 29. 12:59

회사에서 Bose 울트라 오픈 이어버드를 사용하고 있습니다.

하루 종일 사용하는 편이라 PC와 스마트폰에 동시에 연결해 놓고 사용하는데요.

이 제품은 멀티포인트를 지원하기 때문에 평소에는 PC와 스마트폰을 함께 연결해서 사용할 수 있습니다.

그런데 한 가지 상당히 불편한 문제가 있었습니다.

자리를 비웠다 돌아오면 PC에 자동으로 다시 연결되지 않는다

회사에서 이어폰을 사용하다가 화장실에 다녀오거나 잠깐 자리를 비우면 이어폰과 PC의 연결이 끊어집니다.

다시 자리로 돌아오면 이어폰이 PC 근처에 있으니 당연히 다시 연결될 것 같지만,

실제로는 자동으로 연결되지 않는 경우가 많았습니다.

 

스마트폰은 계속 연결되어 있는 상태이고, PC만 연결이 끊어진 상태가 됩니다.

검색을 해보니 블루투스 장치를 명령어로 제어하는 여러 가지 방법이 있더군요.

 

그래서 Bluetooth Command Line Tool도 사용해 보고, 윈도우에서 블루투스 장치를 다시 연결하는 여러 방법을 찾아봤습니다.

이것저것 시도해 봤는데 생각보다 깔끔하게 해결되지 않았습니다.

결국 ChatGPT의 도움을 받아서 그냥 제가 사용할 프로그램을 하나 만들어 봤습니다.

제가 만든 방법은 단순합니다

원리는 생각보다 간단합니다.

 

지정한 이어폰이 PC에 연결되어 있는지를 계속 확인하다가,

연결되어 있지 않으면 PC의 Bluetooth 기능 자체를 껐다가 다시 켜는 방식입니다.

 

만약 지금 자동접속이 안되서 불편하다면, 설정의 블루투스를 껐다 켜보세요.

그렇게 해서 재접속이 된다면 이 방법이 가능합니다.

 

연결안될때, Bluetooth를 껐다가 다시 켜면 제가 사용하는 이어폰이 정상적으로 다시 연결되는 것을 확인했습니다.

그래서 아예 이 과정을 자동화했습니다.

프로그램을 실행해 놓으면 알아서 연결 상태를 확인하고, 연결이 끊어졌을 때 Bluetooth를 재시작합니다.

 

현재는 실제 업무용 PC에서 사용하고 있는데 잘 작동해서 혹시 비슷한 문제를 겪는 분이 있을까 싶어 공유해 봅니다.

다만 더 좋은 방법이 있다면 알려주세요.

저도 처음 만들어 보는 방식이라 더 깔끔한 방법이 있을 것 같습니다.


사용 방법

1. 처음 실행하면 감지할 장치를 선택합니다

실행파일과 소스파일은 하단에 첨부되어 있습니다.

프로그램을 처음 실행하면 현재 PC에 페어링되어 있는 Bluetooth 장치 목록이 표시됩니다.

여기에서 자동으로 연결 상태를 확인할 이어폰을 선택하면 됩니다.

장치 번호를 입력하면 해당 장치가 감지 대상이 됩니다.

이 창은 계속 띄워둡니다. 최소화는 괜찮습니다.

첫 실행시 장치 선택 화면

 

한 번 선택한 장치 이름은 프로그램 폴더의 config.txt 파일에 저장됩니다.

따라서 프로그램을 다시 실행할 때마다 장치를 선택할 필요는 없습니다.

다른 Bluetooth 장치를 감지하도록 변경하고 싶다면 config.txt 파일을 삭제한 후 프로그램을 다시 실행하면 됩니다.

그러면 다시 장치 선택 화면이 나타납니다.


2. 자리를 비웠다가 돌아오면 자동으로 재접속

이제 프로그램을 실행해 놓고 사용하면 됩니다.

이어폰과 PC의 연결이 끊어진 상태에서 다시 PC 근처로 돌아오면 프로그램이 연결 상태를 확인합니다.

연결되어 있지 않으면 Bluetooth를 자동으로 껐다가 다시 켭니다.

자동으로 재접속 성공 화면

제가 사용한 환경에서는 이 과정을 거치면 이어폰이 다시 PC에 연결됩니다.


프로그램 작동과정

전체적인 흐름은 다음과 같습니다.

장치 연결 끊김
↓
Bluetooth OFF
↓
3초 대기
↓
Bluetooth ON
↓
약 7~8초 대기
↓
연결 확인
↓
성공 → 다시 대기
실패 → 일정 시간 후 다시 시도

 

제가 사용하면서 필요한 정도로만 대기 시간을 넣어 놓은 상태입니다.


주의할 점

이 프로그램은 지정한 이어폰만 다시 연결하는 것이 아니라 PC의 Bluetooth 기능 자체를 껐다 켜는 방식입니다.

따라서 PC에 이어폰 외에 다른 Bluetooth 장치를 여러 개 연결해서 사용하고 있다면 주의해야 합니다.

예를 들어 Bluetooth 마우스나 키보드 등을 사용하고 있다면 Bluetooth가 꺼졌다 켜지는 과정에서 해당 장치들도 연결이 끊겼다가 다시 연결될 수 있습니다.

저는 현재 Bluetooth 장치를 거의 이어폰 용도로만 사용하고 있기 때문에 이 방식으로 사용하고 있습니다.

다른 Bluetooth 장치를 많이 사용하는 환경이라면 부작용이 있을 수 있습니다.


직접 프로그램 만들어 보기

사실 완성된 exe 파일만 공유하는 것도 가능하지만,

출처를 알 수 없는 실행 파일을 무조건 다운로드해서 사용하는 것은 아무래도 찜찜할 수 있습니다.

그래서 프로그램을 직접 만들 수 있도록 제작 방법과 소스 코드도 함께 올립니다.

.NET SDK만 설치되어 있다면 직접 빌드할 수 있습니다.

1. .NET SDK 다운로드 및 설치

먼저 아래 사이트에서 .NET 10 SDK를 다운로드합니다.

 

 

.NET 10.0 다운로드(Linux, macOS 및 Windows) | .NET

Linux, macOS 및 Windows용 .NET 10.0 다운로드. .NET은 다양한 유형의 애플리케이션을 빌드하기 위한 무료 크로스 플랫폼 오픈 소스 개발자 플랫폼입니다.

dotnet.microsoft.com

Windows용 설치 프로그램 중 x64 버전을 다운로드해서 설치합니다.

 


2. 빈 프로젝트 만들기

프로그램을 만들 폴더를 하나 만듭니다.

그리고 해당 폴더에서 명령 프롬프트 또는 PowerShell을 열고 다음 명령어를 실행합니다.

dotnet new console

그러면 기본적인 콘솔 프로그램 프로젝트가 만들어집니다.

닷넷 빈 프로젝트 생성 커맨드 실행 결과

 

제가 올린 소스를 수정 없이 그대로 사용하려면 프로젝트 폴더 이름을 bose로 만들어 주세요.


3. 소스 코드 수정

프로젝트를 만들면 기본적으로 Program.cs 파일이 생성됩니다.

이 파일이 실제 프로그램의 메인 소스 코드입니다.

그 외에 생성되는 프로젝트 설정 파일도 함께 사용됩니다.

아래에 제가 사용한 소스 코드를 그대로 올려두었습니다.

필요하다면 본인의 환경에 맞게 수정해서 사용할 수도 있습니다.

설정 파일인 app.manifest, BtAutoCon.csproj 과 함께 아래에 첨부하였습니다.

Program.cs

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Enumeration;
using Windows.Devices.Radios;

namespace BtAutoCon
{
    class Program
    {
        // 설정 파일
        const string ConfigFile = "config.txt";

        // 평상시 장치 상태 확인 간격
        const int CheckInterval = 3000;

        // Bluetooth OFF 후 최소 대기
        const int BluetoothOffWait = 3000;

        // Bluetooth ON 후 이어폰 연결 대기
        const int BluetoothOnWait = 8000;

        // 연결 실패 후 다음 시도까지 대기
        const int RetryInterval = 10000;

        // 라디오 상태가 실제로 바뀌었는지 확인하는 간격
        const int RadioStateCheckInterval = 500;

        // 라디오 상태 변경 최대 대기 시간
        const int RadioStateTimeout = 10000;


        static async Task Main()
        {
            Console.WriteLine("======================================");
            Console.WriteLine(" Bluetooth 자동 재연결 프로그램");
            Console.WriteLine(" Bluetooth 라디오 OFF / ON 방식");
            Console.WriteLine("======================================");
            Console.WriteLine();


            // --------------------------------------------------------
            // 저장된 장치 ID 읽기
            // --------------------------------------------------------

            string? deviceId = LoadDeviceId();


            // --------------------------------------------------------
            // 첫 실행이면 장치 선택
            // --------------------------------------------------------

            if (string.IsNullOrWhiteSpace(deviceId))
            {
                deviceId = await SelectDevice();

                if (string.IsNullOrWhiteSpace(deviceId))
                {
                    Console.WriteLine();
                    Console.WriteLine("장치가 선택되지 않았습니다.");
                    Console.WriteLine("프로그램을 종료합니다.");
                    return;
                }

                SaveDeviceId(deviceId);

                Console.WriteLine();
                Console.WriteLine("장치 선택이 저장되었습니다.");
                Console.WriteLine();
            }


            // --------------------------------------------------------
            // 저장된 장치 확인
            // --------------------------------------------------------

            var selectedDevice =
                await DeviceInformation.CreateFromIdAsync(deviceId);

            if (selectedDevice == null)
            {
                Console.WriteLine(
                    "저장된 Bluetooth 장치를 찾을 수 없습니다.");

                Console.WriteLine();
                Console.WriteLine(
                    "config.txt를 삭제한 후 다시 실행해서");
                Console.WriteLine(
                    "장치를 다시 선택해주세요.");

                return;
            }


            Console.WriteLine(
                $"감시 장치: {selectedDevice.Name}");

            Console.WriteLine();
            Console.WriteLine("Bluetooth 자동 재연결 감시 시작...");
            Console.WriteLine();


            // --------------------------------------------------------
            // Bluetooth 라디오 접근 권한 요청
            // --------------------------------------------------------

            Console.WriteLine(
                "Bluetooth 라디오 제어 권한 확인 중...");

            var access =
                await Radio.RequestAccessAsync();

            if (access != RadioAccessStatus.Allowed)
            {
                Console.WriteLine();
                Console.WriteLine(
                    "Bluetooth 라디오 제어 권한을 얻지 못했습니다.");

                Console.WriteLine(
                    $"권한 상태: {access}");

                Console.WriteLine();
                Console.WriteLine(
                    "Windows에서 Bluetooth 제어 권한을");
                Console.WriteLine(
                    "허용할 수 있는지 확인해주세요.");

                return;
            }

            Console.WriteLine(
                "Bluetooth 라디오 제어 권한: OK");

            Console.WriteLine();


            // --------------------------------------------------------
            // Bluetooth 라디오 찾기
            // --------------------------------------------------------

            Radio? bluetoothRadio =
                await FindBluetoothRadio();

            if (bluetoothRadio == null)
            {
                Console.WriteLine(
                    "Bluetooth 라디오를 찾을 수 없습니다.");

                return;
            }

            Console.WriteLine(
                $"Bluetooth 라디오: {bluetoothRadio.Name}");

            Console.WriteLine(
                $"현재 라디오 상태: {bluetoothRadio.State}");

            Console.WriteLine();


            // --------------------------------------------------------
            // 메인 감시 루프
            // --------------------------------------------------------

            while (true)
            {
                try
                {
                    var device =
                        await BluetoothDevice.FromIdAsync(deviceId);

                    if (device == null)
                    {
                        Console.WriteLine(
                            $"{DateTime.Now:HH:mm:ss}  " +
                            "Bluetooth 장치를 찾을 수 없음");
                    }
                    else
                    {
                        Console.WriteLine(
                            $"{DateTime.Now:HH:mm:ss}  " +
                            $"상태: {device.ConnectionStatus}");


                        if (device.ConnectionStatus ==
                            BluetoothConnectionStatus.Disconnected)
                        {
                            Console.WriteLine();
                            Console.WriteLine(
                                "→ Bluetooth 장치 연결 끊김!");

                            Console.WriteLine(
                                "→ Bluetooth 자체를 OFF → ON 합니다.");

                            bool result =
                                await RestartBluetoothRadio(
                                    bluetoothRadio);

                            if (result)
                            {
                                Console.WriteLine();
                                Console.WriteLine(
                                    $"→ Bluetooth ON 완료.");
                                Console.WriteLine(
                                    $"→ {BluetoothOnWait / 1000}초 동안 " +
                                    "이어폰 연결을 기다립니다...");

                                await Task.Delay(
                                    BluetoothOnWait);


                                // 연결 확인
                                bool connected =
                                    await CheckConnection(deviceId);

                                if (connected)
                                {
                                    Console.WriteLine();
                                    Console.WriteLine(
                                        "★ Bluetooth 이어폰 연결 성공!");
                                    Console.WriteLine();
                                }
                                else
                                {
                                    Console.WriteLine();
                                    Console.WriteLine(
                                        "→ 아직 연결되지 않았습니다.");

                                    Console.WriteLine(
                                        $"{RetryInterval / 1000}초 후 " +
                                        "Bluetooth OFF → ON을 다시 시도합니다.");

                                    await Task.Delay(
                                        RetryInterval);
                                }
                            }
                            else
                            {
                                Console.WriteLine();
                                Console.WriteLine(
                                    "→ Bluetooth 라디오 재시작 실패.");

                                Console.WriteLine(
                                    $"{RetryInterval / 1000}초 후 다시 시도합니다.");

                                await Task.Delay(
                                    RetryInterval);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine();
                    Console.WriteLine(
                        "오류: " + ex.Message);

                    Console.WriteLine(
                        $"{RetryInterval / 1000}초 후 다시 시도합니다.");

                    await Task.Delay(
                        RetryInterval);
                }


                await Task.Delay(CheckInterval);
            }
        }


        // ============================================================
        // Bluetooth 장치 선택
        // ============================================================

        static async Task<string?> SelectDevice()
        {
            Console.WriteLine(
                "Bluetooth 장치를 검색하고 있습니다...");
            Console.WriteLine();


            string selector =
                BluetoothDevice.GetDeviceSelector();


            DeviceInformationCollection devices =
                await DeviceInformation.FindAllAsync(
                    selector);


            var bluetoothDevices =
                devices
                .Where(x =>
                    !string.IsNullOrWhiteSpace(x.Name))
                .OrderBy(x => x.Name)
                .ToList();


            if (bluetoothDevices.Count == 0)
            {
                Console.WriteLine(
                    "Bluetooth 장치를 찾을 수 없습니다.");

                return null;
            }


            Console.WriteLine(
                "자동 재연결할 Bluetooth 장치를 선택하세요.");

            Console.WriteLine();


            for (int i = 0;
                 i < bluetoothDevices.Count;
                 i++)
            {
                Console.WriteLine(
                    $"{i + 1}. {bluetoothDevices[i].Name}");
            }


            Console.WriteLine();
            Console.Write(
                "선택: ");


            string? input =
                Console.ReadLine();


            if (!int.TryParse(
                input,
                out int number))
            {
                Console.WriteLine(
                    "잘못된 선택입니다.");

                return null;
            }


            if (number < 1 ||
                number > bluetoothDevices.Count)
            {
                Console.WriteLine(
                    "잘못된 번호입니다.");

                return null;
            }


            var selected =
                bluetoothDevices[number - 1];


            Console.WriteLine();
            Console.WriteLine(
                $"선택: {selected.Name}");


            return selected.Id;
        }


        // ============================================================
        // Bluetooth 라디오 찾기
        // ============================================================

        static async Task<Radio?> FindBluetoothRadio()
        {
            var radios =
                await Radio.GetRadiosAsync();


            foreach (var radio in radios)
            {
                Console.WriteLine(
                    $"라디오 발견: {radio.Name} / {radio.Kind} / {radio.State}");

                if (radio.Kind == RadioKind.Bluetooth)
                {
                    return radio;
                }
            }


            return null;
        }


        // ============================================================
        // Bluetooth 라디오 OFF → ON
        // ============================================================

        static async Task<bool> RestartBluetoothRadio(
            Radio radio)
        {
            try
            {
                // ----------------------------------------------------
                // OFF
                // ----------------------------------------------------

                Console.WriteLine();
                Console.WriteLine(
                    "  → Bluetooth OFF 요청...");


                var offStatus =
                    await radio.SetStateAsync(
                        RadioState.Off);


                if (offStatus != RadioAccessStatus.Allowed)
                {
                    Console.WriteLine(
                        $"  → Bluetooth OFF 실패: {offStatus}");

                    return false;
                }


                Console.WriteLine(
                    "  → OFF 요청 완료.");


                // ----------------------------------------------------
                // 실제로 OFF가 될 때까지 기다림
                // ----------------------------------------------------

                bool reallyOff =
                    await WaitForRadioState(
                        radio,
                        RadioState.Off,
                        RadioStateTimeout);


                if (!reallyOff)
                {
                    Console.WriteLine(
                        "  → Bluetooth가 실제 OFF 상태가 되지 않았습니다.");

                    return false;
                }


                Console.WriteLine(
                    "  → Bluetooth 실제 OFF 확인.");


                // 추가 안정화 대기
                await Task.Delay(
                    BluetoothOffWait);


                // ----------------------------------------------------
                // ON
                // ----------------------------------------------------

                Console.WriteLine();
                Console.WriteLine(
                    "  → Bluetooth ON 요청...");


                var onStatus =
                    await radio.SetStateAsync(
                        RadioState.On);


                if (onStatus != RadioAccessStatus.Allowed)
                {
                    Console.WriteLine(
                        $"  → Bluetooth ON 실패: {onStatus}");

                    return false;
                }


                Console.WriteLine(
                    "  → ON 요청 완료.");


                // ----------------------------------------------------
                // 실제로 ON이 될 때까지 기다림
                // ----------------------------------------------------

                bool reallyOn =
                    await WaitForRadioState(
                        radio,
                        RadioState.On,
                        RadioStateTimeout);


                if (!reallyOn)
                {
                    Console.WriteLine(
                        "  → Bluetooth가 실제 ON 상태가 되지 않았습니다.");

                    return false;
                }


                Console.WriteLine(
                    "  → Bluetooth 실제 ON 확인.");


                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                    "  → Bluetooth 라디오 제어 오류:");

                Console.WriteLine(
                    ex.Message);

                return false;
            }
        }


        // ============================================================
        // 라디오가 실제 목표 상태가 될 때까지 대기
        // ============================================================

        static async Task<bool> WaitForRadioState(
            Radio radio,
            RadioState targetState,
            int timeoutMilliseconds)
        {
            int elapsed = 0;


            while (elapsed < timeoutMilliseconds)
            {
                try
                {
                    RadioState state =
                        radio.State;


                    Console.WriteLine(
                        $"  → 현재 Bluetooth 상태: {state}");


                    if (state == targetState)
                    {
                        return true;
                    }
                }
                catch
                {
                    // 상태 조회 실패 시 다음 확인에서 재시도
                }


                await Task.Delay(
                    RadioStateCheckInterval);


                elapsed +=
                    RadioStateCheckInterval;
            }


            return false;
        }


        // ============================================================
        // Bluetooth 이어폰 연결 확인
        // ============================================================

        static async Task<bool> CheckConnection(
            string deviceId)
        {
            try
            {
                var device =
                    await BluetoothDevice.FromIdAsync(
                        deviceId);


                if (device == null)
                {
                    Console.WriteLine(
                        "  → Bluetooth 장치를 찾을 수 없음");

                    return false;
                }


                Console.WriteLine(
                    $"  → 현재 장치 상태: " +
                    $"{device.ConnectionStatus}");


                return device.ConnectionStatus ==
                       BluetoothConnectionStatus.Connected;
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                    "  → 연결 상태 확인 오류: " +
                    ex.Message);

                return false;
            }
        }


        // ============================================================
        // config.txt 읽기
        // ============================================================

        static string? LoadDeviceId()
        {
            try
            {
                if (!File.Exists(ConfigFile))
                    return null;


                string id =
                    File.ReadAllText(
                        ConfigFile).Trim();


                return string.IsNullOrWhiteSpace(id)
                    ? null
                    : id;
            }
            catch
            {
                return null;
            }
        }


        // ============================================================
        // config.txt 저장
        // ============================================================

        static void SaveDeviceId(
            string deviceId)
        {
            try
            {
                File.WriteAllText(
                    ConfigFile,
                    deviceId);
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                    "설정 저장 실패: " +
                    ex.Message);
            }
        }
    }
}

4. 프로그램 빌드하기

소스 코드를 넣었다면 먼저 다음 명령어를 실행합니다.

dotnet restore

그다음:

dotnet build

정상적으로 빌드되면 bin 폴더 아래에 실행 파일이 생성됩니다.

닷넷 프로젝트 빌드 명령어 실행 결과

dotnet restore는 프로젝트에서 필요한 구성 요소를 준비하는 과정이고, dotnet build가 실제로 프로그램을 빌드하는 과정이라고 생각하면 됩니다.


5. 다른 PC에서 사용할 exe 만들기

개발 환경이 없는 다른 PC에서도 사용할 수 있도록 exe 파일 하나로 만들어 보겠습니다.

다음 명령어를 실행합니다.

dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true

그러면 다음과 비슷한 경로에 실행 파일이 생성됩니다.

bin
└─ Release
   └─ net10.0-windows10.0.22621.0
      └─ win-x64
         └─ publish
            └─ bose.exe

self-contained 옵션을 사용했기 때문에 해당 PC에 .NET SDK가 설치되어 있지 않아도 실행할 수 있도록 필요한 런타임을 함께 포함합니다.

대신 파일 용량은 일반적인 exe보다 훨씬 커집니다.

 


6. 만약 피씨 부팅시에 실행되게 하고 싶다면

Win+R -> shell:startup 실행

하면 시작프로그램 탐색기가 열립니다. 여기에 exe 파일의 바로가기를 넣어주면 부팅시마다 실행됩니다.

시작 프로그램창 호출 명령어

관리자 권한이 필요해서 실행시마다 확인 버튼을 클릭해주어야 합니다.

 


소스 파일과 실행 파일

소스 파일과 실행 파일을 함께 첨부합니다.

실행 파일

실행 파일입니다. 아무 피씨나 작동되게 5번 방식으로 빌드한 파일이라 쓸데없이 용량이 큽니다.

 

 

BtAutoCon.exe

 

drive.google.com

 

소스 코드

BtAutoCon.zip
0.00MB

 

실행 파일을 바로 사용하는 것도 가능하지만, 가능하면 소스 코드를 확인한 후 직접 빌드해서 사용하는 것을 권장합니다.

특히 이 프로그램은 Bluetooth 기능을 껐다 켜기 위해 관리자 권한이 필요합니다.


마무리

사실 처음부터 제대로 된 Bluetooth 자동 연결 프로그램을 만들려고 했던 것은 아닙니다.

그냥 "멀티포인트 이어폰 PC에 자동 연결 안되나?"라는 불편함 하나 때문에 이것저것 찾아보다가 결국 직접 만들어 보게 됐습니다.

 

현재 제가 사용하는 환경에서는 꽤 잘 작동하고 있습니다.

다만 Bluetooth 자체를 OFF → ON 하는 다소 단순한 방법이라 완벽한 해결 방법이라고 생각하지는 않습니다.

혹시 특정 Bluetooth 장치만 강제로 재연결하는 더 좋은 방법이나,

Windows에서 지원하는 다른 방법을 알고 계신다면 댓글로 알려주시면 감사하겠습니다.

저도 더 좋은 방법을 찾게 되면 프로그램을 수정해 볼 생각입니다.

 

이런 간단한 프로그램 만드는데는 AI가 참 편하군요.