프론트엔드 실무에서만 느낄 수 있는 극악 무도한 버그들

김규빈·2022년 2월 20일
1

아직도 해결 못한 버그들이나, 버그가 발생 이유에 대해 명확하게 이해하지 못한 부분도 있습니다. 혹시나 알고 계신 선배 개발자분이 계시다면 알려주세요😂

인트로

나는 평소 개발을 하다 버그를 마주치게 되면 최대한 구글링을 통해 해결하고자 한다. 버그의 원인을 파악하고 내가 여태껏 학습했던 코어 지식들을 활용하여 키워드 검색을 하면 대부분 그에 대한 답은 구글에 이미 나와있다. 하지만 가끔씩 구렁텅이에 빠질때가 있다. 왜 이러한 현상이 나타나는지 모르겠거니와 당장 뭐라고 검색해봐야 될지 키워드마저 감이 안오는 버그들.. 삽질을 통해 해결하고 그것이 성장이라 크게 믿고 있기에 5-6시간이 훌렁 넘어가버리기도 한다. 그럴때마다 제 사수님께 여쭤보는데, 사수님은 대부분 '아 그 부분 예전에 저도 골치 아팠던 부분이에요' 하면서 솔루션을 제시해 주신다.(역시...)
사수님의 말을 빌려오자면
그런 거 걸리면 밤 꼴딱 새우는 거예요...

그렇게 해결했거나, 아직도 해결 못한 버그 오직 실무에서만 경험할 수 있는 버그들에 대해 정리해본다.

1.원인불명 도대체 외? - 해결 못함 (web in app , vue, flutter)

시뮬레이터에서 실행했을 시 확인되는 화면

아이폰 12미니에서 구동 시 넣지 않은 보더가 확인된다???????

이게 정말 이상한 점은 아이폰 11미니, 12미니에서만 확인되는 현상 이 외의 기기는 저 보더가 나타나지 않는다.

시도해본 것

instector를 통해 확인해 봐도 보더에 대한 속성은 확인 불가.

다른 아이폰 기기에서는 나타나지 않음. 안드로이드 역시 x, 아이폰 미니 사이즈에서만 나타나는 현상

웹인앱 페이지이기 때문에 hoxy flutter에서 먹은 속성 ? => 다른 아이폰에선 보더가 없음 아님.

정말 이상한 점은 아이폰 내부에서 캡쳐할 시 저 보더는 귀신같이 사라짐...

저게 정말 사소한 것 같아 보여도 직접 앱 구동 시 내 눈에는 저것밖에 안보임.....

아이폰에서 캡쳐한 이미지

어느 렌더링 과정에서 저 보더가 생기고 있는지.. 운영체제 레벨에서 간섭이 있는건지... 도통 알 수 없다..
(flutter SafeArea 위젯에서 디스플레이 크기에 따라 내부 위치 값을 정하는 과정에서 알수 없는 버그로 인해 특정 픽셀 크기(아이폰 미니)일 때 저 보더가 생긴건 아닐지?..=> 내부 캡쳐 할 경우에는 안나타는거 보아하니 이것 또한 아님)

2.web in app에서 border 두께- 해결 못함(web in app , vue, flutter)

자세히 보면 border의 두께가 들쭉날쭉하다. 세로선을 보면 1 , 2, 3, 2, 1 순서로 두께가 두껍다.
보더는 1px solid #000 속성이며, border-collapse: collapse; 속성을 통해 테두리 공유 상쇄를 주었다. mdn에 나와있는 border-collapse속성은 아래와 같이 모든 플랫폼에서 사용 가능하다.

시도해본 것

1px 이하의 테두리는 브라우저에서 그리지 못한다. hoxy 연관이 있나 ? => 2px 로 해도 똑같은 결과

web in app이라서 ..? => inspector로 시뮬레이터에서 mdn 확인 결과 똑같이 보더가 들쭉날쭉

놀랍게도 android환경 특정 폰(갤럭시)에서는 보더의 두께가 모두 일정하다. => 이 환경 픽셀을 잡으면 지금 정상적이게 보이는 환경에선 달라진다.

보더 두께 잡겠다 try => 밤에 잠 못잔다.

3.Ios copy api - 해결 (web in app , vue, flutter)

보통 자바스크립트로 copy 액션을 구현하는 방법은 비교적 최신에 나온 ClipboardAPI를 이용하거나 execCommand API를 통해 이루어진다. ClipboardAPI는 execCommand API보다 최신 스펙이기 때문에 웹 호환성이 떨어지기 때문에 execCommand api 를 사용하여 클립보드에 복사하는 기능을 만들고 있었다.

어니언의 경우 이 기능은 레퍼럴 이벤트에 사용하게 되었는데, 구조를 보면 링크 생성 버튼 클릭 통해 firebase dynamic link를 거쳐 고유의 레퍼럴 링크를 생성 받고 그 링크를 클립보드에 저장시켜 보다 나은 레퍼럴(공유) 사용자 경험 환경을 만들어주고 링크를 통해 가입을 하게 되면 레퍼럴 이벤트 참여자로써 혜택을 부여했다.

async deeplinkHandler(){
	const parmas = {
        //user Info
      };
      try {
        //deeplink 생성
        const result = await postShareUrl(parmas);
        //성공 시 copy api
        if (result) {
          this.copyClipboard(result.data.shortLink);
        }
      } catch {
        alert("에러! 다시 시도해 주세요");
      }
},
 copyClipboard(url) {
    try {
      var textarea = document.createElement('textarea'); 
      textarea.value = url; // 복사할 메시지
      document.body.appendChild(textarea);
      textarea.select(); 
      textarea.setSelectionRange(0, 9999); // For IOS 
      document.execCommand('copy');
      console.log("sucess")
      document.body.removeChild(textarea);

       } catch (err) {
           alert(err);
         }
    },

이 로직은 안드로이드 환경에선 문제없이 작동한다. 하지만 ios의 경우에는 링크 생성 후 copy가 안되는 문제가 발생하게 되는데, ios 환경의 경우에는 사용자의 액션 직후에 Copy가 이루어져야 한다.
어니언의 경우 clipboard에 복사할 메시지를 구하기 위해서 외부 호출을 통해 주소를 받아온다.
button 클릭 -> onclick 이벤트 발생 -> 복사할 메시지를 구하기 위해 서버 요청 -> 응답이 오고 복사할 메시지를 clipboard copy를 이용하여 복사.
이러한 경우에는 사파리에서 복사가 되지 않는다. 버튼을 누른 직후에 copy를 하지 않고, 외부 호출을 통해 callback에서 copy가 이루어졌기 때문이다.
이러한 문제를 해결하기 위해서는 복사할 메시지를 미리 구해놓고 button이 클릭되어 클릭 이벤트가 발생하였을때 바로 clipboard로 복사가 되어야 한다.

async deeplinkHandler(){
	const parmas = {
        //user Info
      };
      try {
        //deeplink 생성
        const result = await postShareUrl(parmas);
        //성공 시 copy api
        if (result) {
          this.copyClipboard(result.data.shortLink);
        }
      } catch {
        alert("에러! 다시 시도해 주세요");
      }
},
 copyClipboard(url) {
    try {
      //Ios 체크
      let ios = navigator.userAgent.match(/ipad|iphone/i);
      
      if (ios) {
        if (confirm("생성된 주소가 있습니다 클립보드에 복사 하시겠습니까? ")) {
          //컨펌창을 띄워 확인이 되었을 경우 바로 복사 시도 
           	textarea.value = url; // 복사할 메시지
            document.body.appendChild(textarea);
            textarea.select(); 
            textarea.setSelectionRange(0, 9999); // For IOS 
            document.execCommand('copy');
            console.log("sucess")
            document.body.removeChild(textarea);
        }else{
        	//...
        	}
      }
       } catch (err) {
           alert(err);
         }
    },

를 통해 해결 가능하다.

4. 계속 ...

profile
FrontEnd Developer

0개의 댓글