반응형

흔히 부르는 햄버거 메뉴를 눌렀을 때 이벤트 감지를 알려주는 강좌를 보고 따라 했음에도 햄버거 메뉴가 동작 자체를 안하는 문제를 발견했다.
        leading: IconButton(
          icon: Icon(Icons.menu),
          onPressed: () {
            print("Menu Call!!!!");
          },
        ),
강좌에서 동작했던 코드인데
아래처럼 해야만 동작했다.
        leading: Builder(
          builder: (context) => IconButton(
            icon: new Icon(Icons.settings),
            onPressed: () => Scaffold.of(context).openDrawer(),
          ),
        ),

그새 구글이 구글했나보다.
작작 좀 바꿔라.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  //const MyApp({super.key});
  final appTitle = 'Drawer Demo';
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: appTitle,
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Builder(
          builder: (context) => IconButton(
            icon: new Icon(Icons.settings),
            onPressed: () => Scaffold.of(context).openDrawer(),
          ),
        ),
        title: Text('Drawer'),
        elevation: 0.0,
        centerTitle: true,
        actions: [
          IconButton(
            icon: const Icon(Icons.shopping_cart),
            onPressed: () {
              print("AA2222");
            },
          ),
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {},
          ),
        ],
      ),
      body: Center(child: Text('My Page!')),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            // DrawerHeader(
            //   child: Text('Drawer Header'),
            //   decoration: BoxDecoration(
            //     color: Colors.blue,
            //   ),
            // ),
            UserAccountsDrawerHeader(
              currentAccountPicture: CircleAvatar(
                backgroundImage: AssetImage('assets/0001.gif'),
              ),
              otherAccountsPictures: [
                CircleAvatar(
                  backgroundImage: AssetImage('assets/0002.png'),
                )
              ],
              accountEmail: Text('dev.yakkuza@gmail.com'),
              accountName: Text('Dev Yakuza'),
              onDetailsPressed: () {
                print('press details');
              },
              decoration: BoxDecoration(
                  color: Colors.blue[300],
                  borderRadius: BorderRadius.only(
                    bottomLeft: Radius.circular(40),
                    bottomRight: Radius.circular(40),
                  )),
            ),
            ListTile(
              title: Text('Item 1'),
              onTap: () {
                Navigator.pop(context);
              },
            ),
            ListTile(
              title: Text('Item 2'),
              onTap: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

visual studio code로 flutter를 개발하기 위해 extension을 설치하고 F1을 눌러 New project를 누르면 

이딴게 호출되는 사람이 있을 수 있다.  그게 나다 -_-
이상한건 난 분명히 환경변수를 설정해줬단 말이다.
그래도 뜨니 어쩔 수 없다. 또 하는 수 밖에

flutter site에서 파일을 다운받은 후 루트 > Users > hippalus (참고로 이 폴더는 내 유저명임) > Development (참고로 새로 만든 폴더임) > flutter를 위치시켜 뒀다.

터미널을 열어(터미널이 어디있는지 모른다면 응용프로그램 폴더의 유틸리티 폴더를 참조할것)

vim editor를 열기 위해 

vi ./~zshrc 입력 후 엔터

vim editor에 대해 더 알고 싶다면 이 블로그 글 참조 바람 잘 설명되어 있음
머여 내 포스트랑 겹치는 내용이네? ㅋ
https://d-dual.tistory.com/8

 

[ Mac OS / Terminal ] zsh 셸에서 Vim을 이용하여 환경 변수 설정하는 방법.

📝 VIM 소개 - vim.org Vim은 모든 종류의 텍스트를 만들고 변경할 수 있도록 구성 가능한 텍스트 편집기입니다. 대부분의 UNIX 시스템 및 Apple OS X에 "vi"로 포함되어 있습니다. 라고 vim 공식 페이지에

d-dual.tistory.com

vim editor에서 i를 눌러 INSERT모드로 진입 후 각자 위치시킨 경로를 입력 

export PATH="$PATH:/Users/hippalus/Development/flutter/bin"

다 입력했다면 esc키를 눌른 후 :wq 엔터치면 vi editor에서 빠져나옴

터미널로 다시 넘어왔다면 업데이트 한 내용을 적용하기 위해 source 명령어 사용

source .bashrc 실행하면 끝

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

SELECT
   OBJECT_NAME(object_id),  OBJECT_DEFINITION(object_id)
FROM 
   sys.procedures
WHERE 
   OBJECT_DEFINITION(object_id) LIKE '%내용%'

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

<INPUT TYPE="CHECKBOX" NAME="CHK" CLASS="CHECKDATA" VALUE="1">체크1
<INPUT TYPE="CHECKBOX" NAME="CHK" CLASS="CHECKDATA" VALUE="2">체크2
<INPUT TYPE="CHECKBOX" NAME="CHK" CLASS="CHECKDATA" VALUE="3">체크3

이렇게 체크박스가 동일한 클래스명으로 여러개 존재하고 라디오 버튼처럼 하나의 체크박스만 체크 가능하게 할 경우
체크박스의 체인지 이벤트에 아래와 같이 코딩해주면 끝남

           
$(".CHECKDATA").on('change', function() {
                $(".CHECKDATA").not(this).prop('checked', false);  
            });

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

망할 azure PaaS 환경의 클라우드 이관 작업을 진행하려다 보니 관련 부서에서 날짜 관련해서 제약사항이 생긴다란 이야기를 듣고 생각해보니 기존 소스들이 이관되면 엉망이 되겠다 싶어 미리 준비해보았다.

당장 javascript로 만들어진 new Date()만 보더라도 한국 시간과 미국 시간의 차이로 임계영역에 다다르면 날짜가 서로 꼬이게 될 것이란건 너무나 자명했다.

현재 서버호스팅 환경에선 new Date()시 2022-08-08 19:00:00이던게 
미국과 한국은 13시간의 차가 있으므로 azure PaaS 클라우드 환경에선 2022-08-09 20:00:00으로 보여지게 될테니 말이다. 

그리하여 기존의 new Date()대신 new AzureDate()를 호출하면 해당 함수내에서 알아서 시간계산을 해서 값을 돌려준다면 모든게 해결될 듯 보였다.
어차피 getFullYear(), getMonth(), getDate() 등의 함수는 new Date()로 받아온 시간객체를 통해 얻는 행위이므로 AzureDate()만 만들다면 이 모든건 소스 수정 없이 우아하게 처리 될 것이다.

아래가 그 결과물이다. 
    function AzureDate() {
        var dt;
        
        if (arguments.length == 0) {
            dt = new Date();
        } else if (arguments.length == 1) {
            dt = new Date(arguments[0]);
        }

        dt.setHours(dt.getHours() + 13);        
        
        return dt;
    }

특이한 부분은 arguments.length라는 부분이다.
new Date(), new Date("2022-08-08") 이렇게 인자를 넘겨서 객체를 생성하기 때문에 내가 만든 javascript 함수도 이에 대응할 필요가 있었다.

하지만 우리의 자바스크립트는 오버로딩을 지원하지 않는다.
https://www.geeksforgeeks.org/function-overloading-in-javascript/
Unlike the other programming languages, JavaScript Does not support Function Overloading
Here is a small code which shows that JavaScript does not support Function Overloading.

 

Function Overloading in JavaScript - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

따라서 arguments.length로 분기해준다면 훌륭하게 잘 처리가 가능하다.

다 만들어 놓고 azure cloud에 올려 테스트해봤더니 -_-
시간차가 벌어지지 않더라
생각해보니 javascript는 로컬이잖 -_-

내친김에 classic asp로도 만들어봤는데 마찬가지로 시간차가 없었단 -_-

    function AzureDate() 
        Dim dateVal
        dateVal = dateadd("h", 13, now())
        
        AzureDate = year(dateVal) & "-" & Right(String(2, "0") & month(dateVal), 2) & "-" & Right(String(2, "0") & day(dateVal), 2)
    end function

    function AzureNow() 
        Dim dateVal
        dateVal = dateadd("h", 13, now())
        AzureNow = dateVal
    end function


한국 서버에서 돌린 결과 2022-08-08 오후 7:30:00
8/8/2022 7:30:00 PM
azure Cloud서버가 한국에 있어서 그런건지...
이건 좀 이상하므로 설치한 담당자에게 물어보는 중

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

print.css
0.00MB

인터넷에 보면  javascript로 프린트를 하는데 동적인 TD의 높이 때문에 자칫 페이지가 넘어갈 때 화면이 짤리는 상황을 경험하게 된다.
이를 완벽하게 해결한 쉬운 소스를 공개한다.
보통 폼은 첫번째 장에는 헤더가 있고 다음장부터는 헤더가 없는 경우가 많다.
본 포스팅은 이러한 경우까지 대응하고 있다.
말은 거창하지만 사실 그냥 그만큼 자리 차지하고 있고 그 아랫부분부터는 동적으로 알아서 잘라주고 이어주고 알아서 잘 되니 신경 안써도 된다.

1. 페이지 상단에 본 포스팅의 print.css 첨부파일을 호출한다.

<link type="text/css" rel="stylesheet" href="/css/print.css" />


2. 스타일에 아래 코드를 추가한다.

<style>
@page { size: A4 }
* {
-webkit-print-color-adjust: exact !important; /*Chrome, Safari */
color-adjust: exact !important; /*Firefox*/
}
</style>

3. body에 print.css의 class인 A4사이즈를 지정한다.
<body class="A4">

4. 첫 페이지의 헤더를 위치시킨다. 내용은 각자 알아서 마음대로 교체하면 됨
id는 SECTIONPAGE1으로 하였다.
실질적인 출력 영역은 DIVTOPAREA class로 지정하였고 내용을 담당하는 DIV의 class는 DIVDATAAREA
끝으로 다음 tr의 높이가 페이지를 넘어서서 짤리게 될 경우 페이지 하단에 공백을 계산하여 넣어줘야 하므로 공백 DIV인 DIVBUFFERAREA가 추가되었다.
제목헤더인 DIVTOPAREA는 1페이지만 출력시키므로 SECTIONPAGE1에만 추가되어 있다.
참고로 여기서 거론한 class를 제외한 tdPrintWhite 클래스 등은 그냥 내 소스의 공통 css에서 사용되는 클래스이므로 무시하면 됨
<section class="sheet padding-10mm" id="SECTIONPAGE1">
<div class="DIVTOPAREA">
<table class="" width="100%" border="0" cellspacing="0" cellpadding="10">
<tr>
    <td class="tdPrintWhite" width="100%;" align="center"><h1>제목헤더영역</h1>
        <a href="#" class="btnblue" id="BTNPRINT">인쇄</a>
    </td>
</tr>
</table>
</div>
<br />
<div class="DIVDATAAREA"></div>
<div class="DIVBUFFERAREA"></div>
</section>

5.데이터를 출력시킬 SECTIONPAGE영역을 여유있게 미리 만들어 둔다.
동적으로 그때그때 생성해도 되지만 이게 편하다.
난 총 4페이지까지면 충분하므로 2부터 4까지 for문을 돌려 생성하였다.
<%
for iSEL = 2 to 4
%>

<section class="sheet padding-10mm" id="SECTIONPAGE<%=iSEL %>">
<div class="DIVDATAAREA"></div>
<div class="DIVBUFFERAREA"></div>
</section>

<%
next
%>

여기까지 진행했으면 일단 1차 준비는 끝났다.
이제 실질적으로 큰 영역에 모든 데이터들을 뿌려주고 페이지가 모두 로딩이 된 후 이 영역의 데이터들을 계산하여 앞서 만들어둔 SECTIONPAGE section의 DIVDATAAREA에 붙여넣기를 진행할 것이다.

6.보면 div에 id가 부여되었고 class도 편의상 id와 동일하게 부여하였다.
특이한 점은 rowspan이 2이다.
즉 아래와 같은 표형태이다.
굳이 왜 rowspan을 예로 들었냐면 그 이유는 잠시 후 아래에서 설명할 것이다.
이것 때문에 약간 고생을 한 경험이 있기 때문이다.

순번 성명 항목 현황
근거 일자 기종
<div id="DIVITEMBODY" class="DIVITEMBODY">
<table class="" width="100%" border="1" cellspacing="0" cellpadding="5">
<tr>
<td class="tdPrintGray" width="50px;" rowspan="2">순번</td>
<td class="tdPrintGray" width="*" rowspan="2">성명</td>
<td class="tdPrintGray" width="200px;" rowspan="2">항목</td>
<td class="tdPrintGray" width="400px;" colspan="3">현황</td>
</tr>
<tr>
<td class="tdPrintGray" width="200px;">근거</td>
<td class="tdPrintGray" width="100px;">일자</td>
<td class="tdPrintGray" width="100px;">기종</td>
</tr>
......for문을 통해 모든 데이터들을 각자 알아서 출력......
</table>
</div>

7.여기까지 HTML소스 끝이다.
이제 jQuery, javascript로 DIVITEMBODY의 데이터들을 계산해서 복사 붙여넣기를 하면 된다.
소스는 그냥 복사해서 붙여넣기 해보면 잘 동작할 것이다.
응용하려면 로직이 비교적 간단하니 바보 아니면 이해 가능한 수준이기도 하고 ;p
위에서 설명하기로 했던 내용으로 중요한 부분인 rowspan이 없는 헤더인 경우 "//헤더TR이 2줄 이므로 if (index == 0) 대신 if (index<= 1)로 사용"하라고 주석까지 달아 두었다.
SECTION을 4개가 아닌 10개를 만들었다면 for (nSectionPage = 2; nSectionPage <= 4; nSectionPage++)의 4를 10로 바꾸면 된다.
이 정도면 정말 이유식을 떠먹여줬다 본다.
나머진 복사 붙여넣기 하면 끝

<script>
    $(document).ready(function() {
        var bAppendEnd = false;
        var nLastTrIndex = 0;
        var nSectionPage = 1;

        var objSECTIONPAGE;
        var objTopArea;
        var objDataArea;
        var objBufferArea;

        objSECTIONPAGE = $("#SECTIONPAGE" + nSectionPage);

        objTopArea = objSECTIONPAGE.find($(".DIVTOPAREA"));
        objDataArea = objSECTIONPAGE.find(".DIVDATAAREA");
        objBufferArea = objSECTIONPAGE.find(".DIVBUFFERAREA");

        objDataArea.append($("#DIVITEMBODY").clone().attr("id", "DIVITEMBODY" + nSectionPage));

        var fSafeArea = 1118.740157 - (objTopArea.height() + 37.79527559);


        objSECTIONPAGE.find($(".DIVITEMBODY tr")).each(function(index, tr) {
            if (fSafeArea - $(this).height() > 0 && bAppendEnd == false) {
                fSafeArea = fSafeArea - $(this).height();
                nLastTrIndex = index;

                if (index == 0) {
                    if (fSafeArea - $(this).closest('tr').next('tr').height() < 0) {

                        bAppendEnd = true;

                        $(this).hide();
                        fSafeArea = fSafeArea + $(this).height();

                        console.log(objDataArea.html());
                        objDataArea.hide();
                    }
                }
            } else {
                bAppendEnd = true;
                $(this).hide();
            }
        });

        objBufferArea.height(fSafeArea);


        for (nSectionPage = 2; nSectionPage <= 4; nSectionPage++) {
            objSECTIONPAGE = $("#SECTIONPAGE" + nSectionPage);

            //objTopArea = objSECTIONPAGE.find($(".DIVTOPAREA"))
            objDataArea = objSECTIONPAGE.find(".DIVDATAAREA");
            objBufferArea = objSECTIONPAGE.find(".DIVBUFFERAREA");

            //objTopArea.append($("#DIVTOP").clone().attr("id", "DIVTOPAREA" + nSectionPage));
            objDataArea.append($("#DIVITEMBODY").clone().attr("id", "DIVITEMBODY" + nSectionPage));

            fSafeArea = 1118.740157 - 37.79527559;

            if (nLastTrIndex < objSECTIONPAGE.find($(".DIVITEMBODY tr")).length - 1) {
                bAppendEnd = false;

                objSECTIONPAGE.find($(".DIVITEMBODY tr")).each(function(index, tr) {
                    if (index <= 1) {   //헤더TR이 2줄 이므로 if (index == 0) 대신 if (index<= 1)로 사용
                        $(this).show();
                        fSafeArea = fSafeArea - $(this).height();
                    } else {
                        if (nLastTrIndex >= index) {
                            $(this).hide();
                        } else {
                            if (fSafeArea - $(this).height() > 0 && bAppendEnd == false) {
                                $(this).show();
                                fSafeArea = fSafeArea - $(this).height();

                                nLastTrIndex = index;

                            } else {
                                bAppendEnd = true;
                                $(this).hide();
                            }
                        }
                    }
                });

                objBufferArea.height(fSafeArea);
            } else {
                objSECTIONPAGE.hide();
            }

        }

        $("#DIVITEMBODY").hide();



        $("#BTNPRINT").click(function(e) {
            e.preventDefault();

            $("#BTNPRINT").hide();
            window.print();
            $("#BTNPRINT").show();
        });
    });  
</script>

끝으로 블로그 운영하는 사람들 중 복사하기 막아둔 인간들은 X잡고 반성해라
늬들도 어디서 줍줍한 알량한 잡지식인데 뭐 대단한 지식인냥 복사방지까지 해두고 난리부르스를 추는지 이해가 안간다.
만약 복사방지로 애써 찾은 소스 복사 할 수 없는 저질 블로그를 만나걸랑 크롬스토어에서 SuperCopy 슈퍼 카피를 추가하면 바로 복사되니 반드시 설치하여 복사에 성공하길 기원한다.
https://chrome.google.com/webstore/detail/supercopy-enable-copy/onepmapfbjohnegdmfhndpefjkppbjkm

 

SuperCopy 슈퍼 카피

오른쪽 키 허용, 선택 허용, 복사 허용, 붙 여 넣 기 허용.

chrome.google.com

이상 전달 끝

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

앱스토어를 통해 Xcode를 업데이트 하다보면 종종 업데이트 멈춤 현상을 경험하게 된다.
수년째 반복되는 일임에도 애플은 나몰라라
이것 때문에 애플개발자 지원센터에 유선 문의도 했었지만 그 이후에도 또 이렇게 먹통이 돼버렸다.
아래 대기상태로 몇시간을 지켜봐도 동일하다.

무한 로딩 증상이 지속될 경우 아래 내용대로 시도하고 리부팅도 하다보면 언젠간 업데이트 버튼을 마주할 수 있게 된다.
업데이트 버튼을 누르면 다시 처음부터 8기가가 넘는 Xcode 업데이트 파일을 다운받게 되고 운이 좋다면 업데이트를 성공시킬 수 있다.
그나마 파랑 로딩 인디케이터라면 업데이트에 희망적이라 본다.
회색 로딩 인디케이터라면 절망적이지 싶다.
일단 아래 내용대로 터미널을 통해 캐시 파일들을 삭제하고 운좋게 다시 업데이트를 재시작 하였지만 작성중인 현 상태에서도 동일하게 설치 중 대기 상태이긴 하다.
회색 인디케이터가 아니라 좀 기다리면 되지 싶긴한데..성공하면 댓글로 성공 여부를 남겨두겠다.



앱스토어 캐시 삭제
1. 앱스토어 임시 파일 삭제
터미널(terminal) 실행
터미널 상태에서 아래 명령어 실행 후 Finder가 뜨면 해당 폴더 모조리 삭제
open $TMPDIR../C/com.apple.appstore/

2. 앱스토어 캐시 파일 삭제
터미널 상태에서 아래 명령어 실행 후 Finder가 뜨면 해당 폴더 모조리 삭제
open ~/Library/Caches/com.apple.appstore

3. 기타 앱스토어에이전트 중지
터미널(terminal) 실행
터미널 상태에서 pkill -9 -f appstoreagent 명령어 입력

오죽했으면 이용자가 앱스토어 Xcode 리뷰에 분노의 리뷰를 달아놨을까?

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

튜닝도 거치고 쿼리분석기에서 예상실행계획상 누락된 인덱스도 없으며 0.1초만에 잘 나오는 쿼리상으론 아무 문제 없는 쿼리임에도 불구하고 웹페이지에서 실행하면 15초씩 걸리는 이상한 현상이 발견되었다.


가만히 놔둬선 안되겠다 싶어 구글링을 해보니 나와 같은 증상을 겪은 사람들이 이미 여럿 존재함을 확인할 수 있었다.

이유는 ARITHABOART 이녀석 때문인데 시퀄서버에선 기본값이 ON이지만 ADO에선 아래 표처럼 기본값이 OFF


결론은 쿼리 날릴 때 ADODB의 설정을 건드려주면 된다.
Static Query인 경우엔 쿼리문 앞에 SET ARITHABORT ON을 넣어주고
Set objCmd = Server.CreateObject("ADODB.Command")
    SQL = ""
    SQL = SQL & vbCrLf & "SET ARITHABORT ON"
    SQL = SQL & vbCrLf & "SELECT"
    ......
    With objCmd
    .ActiveConnection = dbConn
    .CommandType = adCmdText
    .CommandText = SQL
    
               .Parameters.Append .CreateParameter("param", adDate, adParamInput, , paramdata)
    End With
    
    Set rs = Server.CreateObject("ADODB.RecordSet")
    rs.CursorLocation = adUseClient
    rs.Open objCmd, , adOpenStatic, adLockReadOnly

    If rs.EOF Then
    Else
    End If

    rs.Close
    Set rs = Nothing
Set objCmd = Nothing

Stored Procedure인 경우
SqlConnection dbConn = new SqlConnection(strConnection);

dbConn.Open();
SqlCommand cmdAritabort = new SqlCommand("SET ARITHABORT ON", dbConn);
cmdAritabort.ExecuteNonQuery();
           
SqlCommand cmd = new SqlCommand("dbo.usp_example", dbConn);
cmd.CommandType = CommandType.StoredProcedure;

SqlDataAdapter adapter = new SqlDataAdapter(com);
adapter.Fill(table);

dbConn.Close();


관련하여 더 자세히 느끼고 싶다면 Slow in the Application, Fast in SSMS? Understanding Performance Mysteries란 버거형님의 진중하고 장대한 글을 참고해보길 바란다.
https://www.sommarskog.se/query-plan-mysteries.html
해당 글에선 좀 다르게 이야기 해주던데 너~~~무 길고 난 ARITHABOART ON 설정으로 느린 쿼리를 해결하였으므로 이쯤에서 만족하려 한다.

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

일전에 네이버 서치어드바이저(searchadvisor.naver.com)를 통해 사이트 등록을 요청하였으나 수집보류라는 어처구니 없는 상태가 지속되었다.

검색해보니 몇가지 방법이 존재하는데 그 중 그나마 해결 가능한 방법이 고객센터를 통해 요청을 하는 방법이 있어 고객센터를 통해 문의를 접수하였으나 아니나 다를까 아래와 같은 같잖은 답변을 받아볼 수 있었다.

안녕하세요. **** 고객님,문의하신 내용에 답변드립니다. 

네이버는 모든 사이트 및 웹문서의 수집/반영을 보장하지 않습니다.
수집보류가 노출되는 것은 최적화 여부, 사이트 신뢰도, 사이트 상태 등에 따라 다양한 원인이 있으며, 수집 요청한 사이트의 수집 여부를 판단하기 어려워 보류가 된 경우를 뜻합니다.

웹마스터도구의 수집 요청 기능은 수집 시스템에게 수집 대상 URL을 전달하는 도우미의 역할만을 담당하며 수집성공이 되더라도 검색결과 노출을 보장할 수 없습니다.

장황하게 되도 않는 이야기를 늘어놓았으나 요지는 니 말은 알겠는데 그냥 가만히 있어라라는 이야기다.
ㅎㅎㅎㅎㅎㅎㅎ
말은 못하겠지만 이유는 알만하다.

구글은 사이트 등록이 완료되어 크롤링이 되고 있건만 네이버는 이런 답변만을 줄 뿐이다.

혹자는 존버하면 언젠간 될 수 도 있다 하지만 바다 건너 미국 기업은 따박 따박 크롤링 해가주는데 국내 기업인 네이버는 이런 식의 반응에 미온적인 태도이니 화가 나지 않을 수 없다.
등록을 요청한 사이트엔 아무런 문제가 없다.
PC, mobile 모두 부트스트랩을 통해 사이트 체크시 정상 확인이 가능하고 사이트맵 xml 제출, meta tag 등 시키는 대로 모든것을 완벽히 수행했음에도 이런식의 변명으로 일관될 뿐이다.

그럼에도 불구하고 크롤링이 불가하니 답답 그 자체가 아닐 수 없다.

 

반응형
Posted by Hippalus

댓글을 달아 주세요

반응형

iframe으로 불러들인 컨텐츠의 높이만큼 부모창에서 iframe의 높이를 동일하게 만들고 싶을 경우 몇가지 고려할 요소가 존재한다.
구조는 대략 이러하다.

부모창
<div id="부모창의DIV">
    <iframe id="부모창의IFRAME"></iframe>
</div>

자식창
<div id="자식창의DIV">
</div>

1. contents() 
2. on load

1. contents() 
먼저 iframe에 접근하기 위해선 그냥 find로 접근하면 안된다.
contents().find()로 접근해야 한다.

$("#부모창의IFRAME").contents().find("#자식창의DIV")

2. on load
1번까지 하고 접근해보면 null을 리턴하거나 undefine을 리턴한다.
본창의 document가 ready되었을 뿐이지 iFrame의 내용까지 모두 불러와진게 아니기 때문이다.
따라서 1번 코드는 이렇게 호출되어야만 한다.
부모창의IFRAME의 contents에서 자식창의DIV란 요소를 획득하겠다란 이야기인데
언제?
iFrame이 모두 불러와져서 온전하게 자식요소들에 접근이 가능할 때 접근하겠다.

$("#부모창의IFRAME").on("load", function() {
        var objIframeChild = $("#부모창의IFRAME").contents().find("#자식창의DIV);
        $("#부모창의DIV").height(objIframeChild.height());
        /* objIframeChild로 iFrame의 자식을 획득하였으니 이녀석을 가지고 놀면 된다. 
            objIframeChild.height() 등등*/
}

여기까지 한다면 내 도메인 내에선 아무 문제 없이 주고 받고가 가능하지만
다른 도메인이라면 이야기가 달라진다.

망할 cross oigin

Uncaught DOMException: Blocked a frame with origin "http://~~~~" from accessing a cross-origin frame.
크롬에서 개발자 도구로 지켜보면 이 에러를 내뱉으며 동작하지 않는다.

iFrame 소스의 on load 또는 jQuery $(document).ready 아래에 부모로의 통신용 postMessage를 구현해준다.
구조는 간단하다.
window.parent.postMessage() 안에 {키, 값} 형태로 넣어주고 콤마(,) 이후 전달 되는 도메인이나 IP주소를 입력해주면 된다.
도메인이나 IP주소 대신 *도 가능하지만 해킹당할 우려가 있으니 가급적 지양해야 할 것이고
만약 여러 도메인으로 통신을 해야겠다면 도메인이나 IP주소만 바꿔가며 window.parent.postMessage를 반복하면 된다.

window.parent.postMessage({키값: 보내고 싶은 값 }, "허용되는 도메인 또는 아이피");

보내는 곳인 자식쪽 소스
window.parent.postMessage({ childHeight: $("자식창의DIV").height() }, "http://......");

받는 곳인 부모쪽
그냥 리스너로메세지 받겠다 하면 끝이다.
window.addEventListener('message', function(e) {
        $("#부모창의DIV").height(e.data.childHeight);
 });

반응형
Posted by Hippalus

댓글을 달아 주세요