본문 바로가기

프로그래밍184

Watchdog Timer 직접 설정하고 리셋시키기 WDT(Watchdog Timer)란 ?MCU가 정해진 시간 안에 스스로 살아 있음을 증명하지 못하면, 자동으로 리셋을 발생시켜 시스템을 다시 살리는 안전장치.이번에는 실제로 WDT를 직접 설정하고, 일부러 WDT를 무시해서 리셋을 발생시킨 후, 리셋이 발생한 원인을 확인해보려고 함. Watchdog Timer 직접 설정하고 리셋시키기 기본 구조WDT는 단순히 "타이머"가 아니라, 그 자체가 독립된 시스템 감시 모듈임.WDT Enable → Timeout 설정 → 일정 주기 내 WDT 리셋(clear) → 안 하면 강제 시스템 리셋 즉, 정상적인 루프 흐름 안에서만 WDT를 계속 초기화해주고, 만약 시스템이 멈춰 루프를 돌지 못하면 → WDT가 MCU를 리셋함.AVR 기준: 코드 예제 (ATmega32.. 2025. 7. 17.
웹뷰 앱을 스토어에 등록하기 위한 필요 기능 요즘 웹 기반 서비스를 빠르게 앱으로 출시하려는 수요가 많아짐. 특히 사내 전용 서비스, 이벤트 페이지, 커머스 사이트 등은 굳이 앱을 따로 만들기보다 기존 웹을 WebView로 감싸는 방식을 많이 시도함. 하지만 구글 플레이나 애플 앱스토어에서는 이런 단순 웹뷰 앱을 거부하는 경우가 많음.사유는 명확함. "이 앱은 웹사이트를 단순히 감싸고 있을 뿐이며, 앱으로서의 고유한 기능이 없습니다.""해당 서비스는 사용자가 브라우저 즐겨찾기로 추가하여 사용할 수 있습니다." 특히 애플은 더욱 엄격함. 내장 사파리 뷰를 사용하는 수준이라고 판단되면 앱이 아예 등록되지 못하고 심사에서 거절됨. 즉, 단순한 웹뷰 앱으로는 스토어에 올라갈 수 없음. 웹뷰 앱을 스토어에 등록하기 위한 필요 기능어떤 기능이 들어가야 .. 2025. 7. 17.
디바운싱(Debouncing)이란? – 버튼 중복 입력 막는 법 임베디드 시스템에서 스위치를 눌렀을 때 한 번만 눌렀는데도 여러 번 입력이 발생하는 현상, 경험해본 적 있을 것이다. 이건 고장이 아니라, 기계적 스위치가 눌리는 순간 내부 접점이 튕기면서 다수의 전기적 신호가 발생하기 때문이라고 한다.이 현상을 스위치 바운스(Bounce)라고 하고, 이를 소프트웨어로 처리하는 기법이 바로 디바운싱(Debouncing)입니다.디바운싱을 제대로 하지 않으면 버튼 하나로도 앱이 오작동할 수 있기 때문에, 실무 임베디드 개발에서 반드시 처리해줘야 할 요소이다. 디바운싱(Debouncing)이란? – 버튼 중복 입력 막는 법MCU, 임베디드 개발에서 꼭 알아야 할 입력 처리 기술 바운스 현상이란?실제 스위치는 ‘딱’ 눌리는 것이 아니라, 매우 짧은 시간 동안 여러 번 ON/.. 2025. 7. 16.
[Flutter] Flutter에서 네트워크 상태 감지하기 Flutter 앱에서 “네트워크 연결”은 거의 모든 기능의 기반이지만, 사용자 입장에서 가장 방치되기 쉬운 UX 요소임. 예를 들어 인터넷이 꺼진 상태에서 버튼을 눌러도 아무 반응이 없다면, 그건 기능 고장이 아니라 사용자 경험의 실패일 수 있음.이 글에서 Flutter 앱에서 실시간 네트워크 상태를 감지하고, API 기반으로 실제 연결 가능 여부를 확인하며, 연결이 끊겼을 때 사용자에게 알림을 띄우는 구조를 정리하려고 한다. Flutter에서 네트워크 상태 감지 및 알림 띄우기네트워크 상태 모니터링 시작connectivity_plus 패키지를 활용하여 Wi-Fi, LTE 등 연결 변화 감지. 단순히 네트워크 타입이 바뀐 것이 아닌,실제로 인터넷이 되는지를 다음 단계에서 확인StreamSubscrip.. 2025. 7. 16.
[Flutter] Flutter에서 키보드 위에 UI 띄우기 Flutter에서 TextField를 사용하는 화면을 만들다 보면, 키보드가 올라왔을 때 그 위에 UI를 띄워야 할 상황이 종종 생긴다. 예를 들어 자동완성 추천, 전송 버튼, 태그 제안 목록 등등...하지만 기본적으로 키보드는 OS 레벨에서 뜨기 때문에, Flutter 위젯 위에 바로 띄우는 방식으론 자연스러운 동작을 만들기 쉽지 않다. 이 글에서 키보드 상태를 감지하고, 그 위에 부드럽게 UI를 띄우는 방법을 정리해보려고 한다. Flutter에서 키보드 위에 UI 띄우기키보드 상태 감지키보드가 올라오면 bottomInset 값이 키보드 높이로 바뀌고, 키보드가 내려가면 0이 됨.이 값을 활용하면, UI가 키보드 위에 뜨도록 위치를 조정할 수 있음.final bottomInset = MediaQuer.. 2025. 7. 16.
[Flutter] GoRouter + ShellRoute 구조 완전 이해하기 Flutter 앱을 만들다 보면, 하단 탭을 유지하면서도 자연스럽게 화면을 전환하고 싶은 순간이 많다. 하지만 기존의 Navigator 구조로는 탭 간 히스토리 공유나 상태 유지를 쉽게 구현하기 어려울 때가 있다.이 글에서 Flutter의 공식 라우팅 패키지인 GoRouter를 사용하여, ShellRoute, StatefulShellRoute, 그리고 IndexedStack을 통해 탭별 상태를 유지한 채 라우팅하는 구조를 정리하려고 한다. GoRouter + ShellRoute 구조 완전 이해하기GoRouter와 ShellRoute를 사용하는 이유? 기존 BottomNavigationBar + PageView 조합 → 코드 복잡도 증가탭 클릭마다 새 화면이 빌드됨 → 상태 초기화 문제 발생Flutter.. 2025. 7. 16.
[Flutter] Dio에서 토큰 만료 자동 갱신 처리하기 Flutter로 앱을 만들다 보면, 인증 처리에서 가장 자주 마주치는 문제가 바로 access token 만료이다. 서버로부터 401 Unauthorized 응답을 받았을 때 어떻게 자동으로 refresh token을 사용해 갱신하고, 다시 원래 요청을 재시도할 수 있을까?이 글에서 Dio를 기반으로 Flutter 앱에서 토큰 만료 시 자동으로 재발급하고 재요청까지 처리하는 구조를 정리하려고 한다. Dio + 토큰 갱신 구조 구현기본 구조 이해대부분의 인증 시스템은 다음과 같이 구성Access Token: 유효기간 짧음, 요청 시 헤더에 사용Refresh Token: 유효기간 김, access token이 만료됐을 때 재발급 요청용Dio 인스턴스 설정class AppDio with DioMixin im.. 2025. 7. 16.
[Flutter] 카카오톡 공유 카카오톡 공유하기 버튼을 누르면 정해진 메세지를 선택한 친구한테 보낼 수 있는 기능을 구현해보았다! Flutter 카카오톡 공유하기 기능 kakao developers 내 어플리케이션 등록 및 설정 기능을 구현할 어플리케이션을 등록하는 과정은 생략하겠다. 궁금하다면 아래 포스팅에 자세하게 설명되어 있으니 참고 바람! https://cording-cossk3.tistory.com/208 [Flutter] Kakao Map api 사용하기 카카오 developer 사이트 바로가기 카카오계정 accounts.kakao.com [ + 애플리케이션 추가하기] 클릭 앱 이름, 사업자명 입력 후 저장 그럼 다음과 같이 리스트에 애플리케이션이 추가된 것을 확인 가능. cording-cossk3.tistory.com 등.. 2024. 4. 4.
[Flutter] Github를 이용하여 universal link, deep link 구현해보기 QR코드를 인식해서 앱이 설치되어 있으면 앱의 특정 페이지로, 설치되어있지 않으면 설치 페이지로 이동하기 위해 deep link에 대해 알아봤다. 제일 많이 사용하는 Firebase Dynamic link로 구현하려고 했지만, 2025년 8월 25일 부로 서비스가 종료된다고 해서 사용해도 나중가서 마이그레이션을 해야 하는 상황이 오면 또 이것저것 찾아보느라 시간 낭비할 것 같아서 Github를 이용하여 universal link, deep link를 구현해보았다. 다시 까먹지 않기 위해 포스팅을 쓴다. Android deep link project_name/android/app/src/main/AndroidManifest.xml Github로 웹호스팅을 할거니까 host 속성 값으로 user_name.g.. 2024. 3. 7.
Kotlin 배우기 (3) Contents 조건식 If 표현식 java와 달리 Kotlin에서는 변수에 값을 할당할 때 if-else if-else 표현식으로도 저장이 가능하므로 삼항연산자를 사용할 필요가 없다. max = if (a > b) a else b val maxLimit = 1 val maxOrLimit = if (maxLimit > a) maxLimit else if (a > b) a else b if 표현식의 분기는 블록 처리할 수도 있다. 또, 값을 반환하거나 변수에 값을 할당하는 경우에 if 표현식을 사용할 경우 else 분기는 필수로 사용되어야 한다. val max = if (a > b) { print("Choose a") a } else { print("Choose b") b } when 표현식 when 표현.. 2024. 2. 13.