반응형

배경


회사의 노드 홈페이지가 컨트랙트 정보를 불러올 수 없어 트랜잭션이 발생되지 않는 문제가 있었다. 컨트랙트 데이터가 꼬여있나 싶어 부랴부랴 서버를 까봤지만 문제가 없었다. 그러나, 브라우저 콘솔에 polygon-rpc.com 으로의 요청이 자꾸 실패한다는 에러가 발생하는 것이었다.

 

설마 rpc 가 문제겠나 싶어 급한대로 주석처리하고 해결하고, 리팩토링을 진행했다. 그럼에도 불구하고 계속되는 삽질.

 

혹시 몰라 chainlist 홈페이지에 Polygon rpc 를 검색해보았더니 polygon-rpc 서버가 다운이 되었던 것이다!!

문제


Polygon-rpc.com 서버가 다운되어 요청에 대한 응답 x

문제를 파악했으니 일단 내 잘못이 아님에 안심하고, 대체 서버를 찾아보기로 했다. 다행히도 polygon rpc 서버는 여러가지가 있었고 최상단 빠르고 안전해보이는 서버를 선택하게 되었다.

해결


  1. Wagmi Config 에서 transport 값 변경

기존 코드에서 transport 속성은 다음과 같이 되어있었다.

transports : {
    [polygon.id] : http()
}

 

http() 함수는 블록체인의 rpc 노드를 설정해준다. 인자 값으로 url 을 넣어주면 해당 url 로 rpc 서버가 세팅된다.

 

transports : {
    [polygon.id] : http('https://alternative-rpc-url')
}

계획


현재 다른 일들이 많아 바로 적용은 못했지만 발전된 방향을 찾을 수 있었다.

 

멀티 rpc

 

바뀐 rpc 서버도 맛이 갈 수 있기 때문에 멀티 rpc 주소를 구성해야한다.

transport: fallback([ 
    http('https://1.rpc.thirdweb.com/...'), 
    http('https://mainnet.infura.io/v3/...') 
  ]), 

 

viem 라이브러리의 fallback 함수를 사용하면 url 이 작동이 되지 않을 때, 대체 url 로 시도하게된다.

반응형
반응형

배경


어느 날 회사에서 정보처리기사를 따라는 지침이 내려왔다. 나는 절대로 딸 일이 없을거라 생각했지만 까라면 까야죠ㅠ
나에게 남은 시간 한달,, 이때는 내가 준비를 열심히 할 줄 알고 개념정리본을 동기가 구해와 열심히할 생각만했다. 정말 생각만 ㅎㅎ
어느덧 1주일이 다가오고 난 절벽끝에 다다른걸 느껴 바로 준비하기로 시작했다.

준비


개념 정리
우선은 아무리 내가 전공자라도 개념을 많이 잊었기 때문에 개념 공부를 먼저 하기로 했다. 동기가 나눠준 개념 정리 노트 1회독을 목표로 했다. 어느정도 읽어보니 정말 읽기 싫었다.
너무 읽기 싫었고 나름 아는 내용도 있기에 바로 문제풀이로 넘어갔다. 절대 하기싫어서 문제푸는것으로 넘어간게 아니다.

기출문제 풀이
시나공 홈페이지에 가보면 정보처리기사 CBT 기출이 모여있어 사이트에서 문제를 풀기로했다.

https://www.sinagong.co.kr/pds/001001001/books

 

시나공

컴활, 정보처리, 워드프로세서 등 IT 자격증 전문. 해설 포함 CBT, 최신 기출 자료 무료, 실기 채점 프로그램 제공

www.sinagong.co.kr

 

정보처리 기사 필기
시험시간 : 150분
시험과목

  1. 소프트웨어 설계
  2. 소프트웨어 개발
  3. 데이터베이스 구축
  4. 프로그래밍 언어 활용
  5. 정보시스템 구축 관리

시험은 정보는 위와 같다.

기출을 어느정도 풀어보니 내가 데이터베이스 쪽이 약하다는 것을 알게 되었고 추가적으로 개념을 준비하기로했다. 출퇴근을 하며 오답을 정리하고 개념을 다졌다.

후기


기출은 신이다.

확실히 문제은행이라 그런지 기출 4회밖에 안풀었음에도 눈에 익은 문제들이 많이 나왔다. 평균 77점으로 좋은 성과를 낼 수 있었다. 여러분들은 꼭 기출문제 풀어보고 가시라

앞으로의 계획


사실 필기는 아무것도 아니다. 문제는 실기. 손코딩, 비트변환 이런 이상한 문제들 나온다는데 미리미리 준비해야겠다.

반응형

'Day Life' 카테고리의 다른 글

2024 하반기 지원 회고  (4) 2025.01.03
2023 회고  (1) 2023.12.31
[MSI 모던14] 블루투스, 와이파이 드라이버 어댑터 설치  (1) 2022.10.05
2022/08/06  (0) 2022.08.06
21.08.13  (0) 2021.08.13
반응형

📱 카카오톡 웹뷰에서 내 웹앱이 안 될 때: 안드로이드와 아이폰 각각의 해결 방법

🔍 웹뷰(WebView)란 무엇이고, 왜 문제가 될까?

요즘은 많은 사람들이 카카오톡, 인스타그램 같은 앱 안에서 링크를 클릭해 웹사이트를 열어본다.

이때 뜨는 창이 바로 웹뷰(WebView) 이다. 웹뷰는 앱 내부에 내장된 간이 브라우저라서, 일반 브라우저와는 다르게 기능 제한이 많다.

대표적으로,

  • 새 창 열기(window.open)가 막혀 있거나,
  • 특정 스킴 호출(intent, deeplink)이 차단되어 있는 경우가 많다.

문제는, 이런 제한된 환경에서는 내 웹앱이 예상대로 동작하지 않는다는 점이다. 특히 외부 브라우저에서 열기를 유도해야 하는 경우(ex. 결제, 다운로드, 고급 기능 사용 등)에는 웹뷰를 탈출시키는 처리가 꼭 필요하다.

이 글에서는, 카카오톡 웹뷰에서 내 웹앱이 제대로 작동하지 않았던 문제를 만나고, 이를 AndroidiOS 각각에서 해결해나간 과정을 정리했다.

💡 문제 상황

회사 플랫폼을 사용하는 사용자들이 카카오톡 웹뷰에서 구글 로그인을 시도해 막혔다는 피드백을 받게 되었다. 왜 그런지 알아보니 웹뷰에서는 이러한 SNS 로그인을 차단한다는 것을 알게 되었다.

"카카오톡으로 열었더니 버튼이 안 눌려!"

직접 확인해보니 카카오톡 웹뷰에서는 다음 문제가 공통적으로 발생했다:

  • window.open('_blank')로 새 창을 열었는데, 화면이 리프레시만 됨
  • 특히 iOS(아이폰)에서는 링크 클릭 후 아무 반응 없음
  • 안드로이드는 새 창 대신 웹뷰에서 그대로 머무름

즉, 내가 의도한 “외부 브라우저로 이동” 기능이 전혀 동작하지 않았다.


🔧 해결 과정 1 – Android: intent://로 Chrome 강제 열기

Android의 경우 다행히 해결이 빨랐다.

intent:// 스킴을 사용하면 카카오톡 웹뷰에서도 Chrome을 강제로 실행할 수 있었다:

const url = location.href;
location.href = `intent://${url.replace(/^https?:\/\//, '')}#Intent;scheme=https;package=com.android.chrome;end;`;

이 코드를 버튼에 연결하니, Chrome이 정상적으로 실행되고 내 웹사이트가 바로 열렸다.


❗ 추가 문제 상황 – iOS는 window.open('_blank')가 안 됨

그런데 iPhone에서는 다르게 굴었다.

window.open('_blank')도, window.location.href = ...웹뷰 안에서만 동작하고, Safari나 Chrome으로 넘어가질 않았다.

특히 iOS의 카카오톡 웹뷰는 새 창 열기 기능을 거의 완전히 차단하고 있었다.


🛠 해결 과정 2 – iOS: googlechrome:// 스킴으로 해결

알아보니 iOS용 Chrome은 커스텀 스킴을 통해 열 수 있다는 사실을 알게 됐다.

function openInChromeiOS() {
  const chromeURL = "googlechrome://" + location.href.replace(/^https?:\/\//, '');
  window.location.href = chromeURL;

  // Chrome이 없을 경우 대비
  setTimeout(() => {
    alert("Chrome이 설치되어 있지 않다면, 우측 상단 메뉴에서 Safari로 열어주세요.");
  }, 1000);
}

이 코드를 통해 iOS 기기에서도 Chrome이 설치되어 있다면 문제없이 내 웹사이트가 열렸다.

단, Chrome이 설치되어 있지 않은 경우엔 아무 반응이 없기 때문에, 사용자에게 안내 메시지를 함께 보여주는 처리가 필요했다.


📌 최종 UX 구성

<button onclick="openInChromeiOS()">브라우저에서 열기</button>
<p>혹시 안 열릴 경우, 카카오톡 우측 상단 ••• 메뉴에서 Safari 또는 Chrome으로 열어주세요.</p>

✍️ 마무리하며

웹앱을 배포할 때 ‘브라우저에서는 되니까 끝!’이라고 생각했지만,

실제 사용 환경인 인앱 웹뷰에서는 동작 방식이 전혀 다르다는 것을 이번에 확실히 체감했다.

  • Android는 intent://로 대응
  • iOS는 googlechrome:// 스킴으로 대응
  • Chrome 미설치 시를 고려한 UX 안내 필수

앞으로는 웹앱 초기 설계 단계부터 인앱 브라우저 대응 전략도 함께 고려해야겠다고 다짐했다.

반응형
반응형

Web3 프론트엔드를 구성할 때 가장 중요한 요소 중 하나는 지갑 연결과 스마트 컨트랙트 연동의 안정성과 편의성입니다. 이번 글에서는 @reown/appkitwagmi, ethers, viem을 활용하여 모던한 Web3 dApp 환경을 구성하는 방법을 소개합니다.

특히, Reown에서 제공하는 AppKitButton을 사용해 지갑 연결 UI를 심플하게 구성하고, 스마트 컨트랙트 연동은 wagmi를 활용하여 안전하게 처리합니다.


🧱 1. 프로젝트 구조 개요

bash
복사편집
src/
├── appkit/                 # wagmi + appkit 설정
│   └── config.js
├── contracts/              # 스마트 컨트랙트 ABI 및 주소
│   ├── CounterABI.json
│   └── address.js
├── hooks/                  # wagmi용 커스텀 훅 (읽기/쓰기)
│   ├── useCounterRead.js
│   └── useCounterWrite.js
├── pages/
│   └── CounterPage.jsx     # 실제 스마트 컨트랙트 연동 화면
├── App.jsx                 # 전체 앱 엔트리 포인트

각 폴더 및 파일의 목적은 다음과 같습니다:

폴더/파일 설명
appkit/config.js AppKit + wagmi의 핵심 설정을 담당
contracts/CounterABI.json 스마트 컨트랙트 ABI 정의 파일
contracts/address.js 스마트 컨트랙트 주소 정의
hooks/ 컨트랙트 호출을 담당하는 useContractRead, useContractWrite 활용 커스텀 훅 모음
pages/CounterPage.jsx dApp 메인 화면. 읽기/쓰기 기능 제공
App.jsx AppKitProvider 및 WagmiConfig로 앱 전체를 감싸는 설정

⚙️ 2. AppKit + wagmi 설정

📁 파일: appkit/config.js

import { WagmiAdapter } from '@reown/appkit-adapter-wagmi';
import { mainnet, arbitrum, sepolia } from '@reown/appkit/networks';
import type { AppKitNetwork } from '@reown/appkit/networks';

export const projectId = import.meta.env.VITE_PROJECT_ID || "b56e18d47c72ab683b10814fe9495694"; // localhost 테스트용

export const metadata = {
  name: 'AppKit',
  description: 'AppKit Example',
  url: 'https://reown.com',
  icons: ['https://avatars.githubusercontent.com/u/179229932']
};

export const networks = [mainnet, arbitrum, sepolia] as [AppKitNetwork, ...AppKitNetwork[]];

export const wagmiAdapter = new WagmiAdapter({
  projectId,
  networks,
});

export const config = wagmiAdapter.wagmiConfig;

🧠 설명:

  • projectId: reown/appkit 기반 연결을 위한 ID입니다. Reown Cloud에서 발급.
  • WagmiAdapter: wagmi와 AppKit을 연결하는 설정자 역할.
  • wagmiConfig: 전체 앱에서 사용할 wagmi 설정을 반환합니다.

🧩 3. App.jsx 설정

📁 파일: App.jsx

import { WagmiConfig } from 'wagmi';
import { AppKitProvider } from '@reown/appkit';
import { wagmiAdapter, config, networks, metadata } from './appkit/config';
import CounterPage from './pages/CounterPage';

function App() {
  return (
    <WagmiConfig config={config}>
      <AppKitProvider adapter={wagmiAdapter} metadata={metadata}>
        <CounterPage />
      </AppKitProvider>
    </WagmiConfig>
  );
}

export default App;

🧠 설명:

WagmiConfigAppKitProvider로 전체 애플리케이션에 Web3 상태(Context)를 적용합니다.


🔐 4. 지갑 연결 버튼 - AppKitButton 사용

Reown은 UI 모달과 연결 기능이 포함된 AppKitButton을 제공합니다.

사용 예시 (CounterPage.jsx 내부에서 사용):


<AppKitButton />

🧠 설명:

AppKitButton은 내부적으로 지갑 연결 상태를 감지하고, 연결되지 않았다면 모달을 띄워 사용자가 지갑을 선택하게 유도합니다. 커스텀 버튼 대신 이 컴포넌트를 활용하면 통일성 있는 UI/UX 제공이 가능합니다.


🔍 5. 컨트랙트 읽기 훅 – useContractRead

📁 파일: hooks/useCounterRead.js


import { useContractRead } from 'wagmi';
import { COUNTER_ADDRESS } from '../contracts/address';
import abi from '../contracts/CounterABI.json';

export const useCounterRead = () => {
  const { data, refetch } = useContractRead({
    address: COUNTER_ADDRESS,
    abi,
    functionName: 'getCount',
    watch: true,
  });

  return { count: data?.toString() ?? '0', refetch };
};

🧠 설명:

스마트 컨트랙트의 getCount()를 호출하여 현재 카운터 값을 가져옵니다. watch: true 옵션으로 자동 업데이트도 가능하게 설정되어 있습니다.


✍️ 6. 컨트랙트 쓰기 훅 – useContractWrite

📁 파일: hooks/useCounterWrite.js


import { useContractWrite, useWaitForTransaction } from 'wagmi';
import { COUNTER_ADDRESS } from '../contracts/address';
import abi from '../contracts/CounterABI.json';

export const useCounterWrite = () => {
  const { data, write } = useContractWrite({
    address: COUNTER_ADDRESS,
    abi,
    functionName: 'increment',
  });

  const { isLoading, isSuccess } = useWaitForTransaction({ hash: data?.hash });

  return { write, isLoading, isSuccess };
};

🧠 설명:

  • increment() 함수 호출을 위해 트랜잭션을 생성합니다.
  • useWaitForTransaction() 훅으로 실제 블록체인에 기록될 때까지 대기합니다.

📄 7. 최종 화면 구성 – CounterPage.jsx

📁 파일: pages/CounterPage.jsx


import { useCounterRead } from '../hooks/useCounterRead';
import { useCounterWrite } from '../hooks/useCounterWrite';
import { useEffect } from 'react';

const CounterPage = () => {
  const { count, refetch } = useCounterRead();
  const { write, isLoading, isSuccess } = useCounterWrite();

  useEffect(() => {
    if (isSuccess) refetch();
  }, [isSuccess]);

  return (
    <div className="p-6">
      <AppKitButton />
      <h1 className="text-xl font-bold mt-4">현재 카운트: {count}</h1>
      <buttononClick={() => write?.()}
        disabled={isLoading}
        className="mt-4 px-4 py-2 bg-green-500 text-white rounded"
      >
        {isLoading ? '처리 중...' : '카운트 증가'}
      </button>
    </div>
  );
};

export default CounterPage;

🧠 설명:

  • 버튼 클릭 시 increment() 실행
  • 트랜잭션 완료 후 상태값 재조회
  • AppKitButton으로 지갑 UI 자동 처리

 

반응형

'BlockChain > Web3' 카테고리의 다른 글

[1] Frontend in Web3  (0) 2025.04.06

+ Recent posts