반응형

먼저 아이폰 설정 부터 손봐줘야 한다.
설정 앱 > Safari > 고급(맨 아래에 있음) > '웹 속성' OFF를 ON으로 바꿔준다.

다음은 맥에서 Safari앱을 실행한다.
Safari를 못 찾는다면 Finder에서 응용프로그램으로 가보면 Safari가 있다.
Safari 실행 후 설정으로 이동

팝업 윈도우가 뜨면 맨 우측 상단의 고급을 눌러보자
그럼 하단에 메뉴 막대에서 개발자용 메뉴 보기 라는게 체크되어 있는지 확인하고 언체크라면 체크로 바꿔주자 

그럼 Safari의 메뉴들 중 중간 쯤 책갈피와 윈도우 사이에 개발자용이란게 뜨는걸 확인할 수 있을 것이다.

그럼 이제 개발자용을 클릭해보자.

아이폰과 맥이 케이블로 연결되어 있다면 저렇게 연결된 아이폰이 뜰것이고 >를 눌러보면 검사할 수 있는 응용 프로그램 없음 이라고 되어 있을 것이다.

Xcode에서 디버깅 할 wkWebview가 탑재된 앱을 실행하고 다시 Safari를 봐보자
그럼 아깐 검사할 수 있는 응용 프로그램 없음 이라고 되어 있던 곳에 우리의 앱이 보여질 것이다.
거기에 추가로 호출하고 있는 웹페이지까지 보여진다.
만약 테스트 하고 있는 아이폰의 OS가 최신버전인 16.4 버전 이후라면 아래 코드를 webview를 생성하는 곳에 살포시 넣어준다.
        if #available(iOS 16.4, *) {
            webView.isInspectable = true
        } else {
            // Fallback on earlier versions
        }
난 didload에서 wkWebview를 addsub해주고 있기 때문에 didload에 넣어줬다.

앱에서 웹뷰의 링크들을 요리조리 눌러보다 보면 오류가 있는 페이지에선 이렇게 오류들이 뜰 것이다.
마치 크롬의 개발자 도구처럼 말이다.

여러가지 웹 사이트내 오류가 확인되고 있는 모습니다.

난 이번에 골탕 먹은게 뭐였냐면 ATS 때문이었다.
개발서버엔 SSL적용이 잘 되지 않았다.
하지만 실서버엔 SSL이 적용 되었다.
따라서 plist.info에 ATS 예외 도메인 처리를 해두었다.
그런데 사이트는 뜨지만 이상하게 자바스크립트단에서 자꾸 막히는 증상이 발현되었기 때문에 도무지 이해가 안 갔는데
기존 소스들이 jQuery js파일을 다운받지 않고 cdn을 사용하여 실시간으로 받아오고 있었고 이 cdn호출시 http로 불러와졌기 때문에 이런 오류가 나는 구조상의 문제였다.

참고로 화면 캡쳐는 이미 ATS 처리를 한 직후의 캡쳐라 jquery오류는 나타나지 않는 모습니다.


오류가 확인되었으니 마찬가지로 예외 도메인으로 등록해주면 되니 아래처럼 plist.info를 설정해주니 
App Transport Security Settings
Allow Arbitrary Loads NO
Exception Domains
   code.jquery.com
      NSTemporaryExceptionMinimumTLSVersion TLSv1.2
      NSIncludesSubdomains YES
      NSExceptionAllowsInsecureHTTPLoads YES
      NSExceptionRequiresForwardSecrecy NO

참 고생했다.

반응형
Posted by Hippalus
,

반응형

swift로 iOS WEB APP을 만들다보면  웹과 앱 사이 통신이야 javascript로 서로 통신을 하니 별 문제가 없는데
앱 이용자와 일반 모바일 웹 이용자의 화면 UI를 다르게 제공할 일이 존재한다.
가령 GNB에 앱 설정을 불러오는 버튼은 앱 이용자에게만 지원할 때 인데 모바일 웹에선 앱의 기능 설정할 일이 없을테니 말이다.
useragent로 확인을 한들 사파리 브라우저로 접속 하든 앱의 wkwebview로 접속 하든 아주  아니 똑같다.

어쩔 수 없다.
앱으로 접속할 땐 url을 호출할 때 custom agent로 agent를 마사지 해줘야 한다.


webView.evaluateJavaScript("navigator.userAgent") {(result, error) in 
let originUserAgent = result as! String
    let customAgent = originUserAgent + " IOSAPP"
    self.webView.customUserAgent = customAgent 
}

이렇게 보내주고 웹에서 agent를 분석할 때 IOSAPP이 존재하면 아하 우리 회원님이 앱을 사용하고 계시는구나~ 하며 앱용 기능을 제공하면 되겠다.

물론 앱에서 웹쪽으로 "이보시게 관상가 양반. 내가 앱이 될 상인가?" 라며 JAVASCRIPT 함수 하나를 서로 약속하고 호출하면 웹에선 이를 쿠키로 저장하든 세션으로 저장하든 하여 "성군 앱이 되실 분 이십니다."라며 처리해도 무방하나 좀 없어보인다.

반응형
Posted by Hippalus
,

반응형

윈도우 11로 넘어오면서 편리한 기능도 있지만 대표적으로 불편한 기능이 존재한다.
바로 마우스 우클릭 후 나타나는 팝업 컨텍스트 메뉴에서 새폴더 만들기나 바로가기 만들기 같은것들을 이용하려면
추가 옵션 표시를 눌러야만 된다. -_-

윈도우 10까지만 해도 직관적으로 새폴더를 만들 수 있었고 마우스 우측으로 바탕화면으로 바로가기도 수월히 만들 수 있었다.

이런 변화는 상당히 불편하다 못해 불쾌하기 짝이 없다.
이를 해결하기 위해선 레지스트리를 변경해 줘야 한다.
일단 윈도우키 또는 좌측 하단의 윈도우 아이콘을 누른 후 cmd를 입력하고 엔터를 치자.


Windows 10 스타일의 우클릭 메뉴를 사용하고 싶다면 아래 reg.exe부터 /f /ve까지 한줄을 복사해서 붙여넣기 후 엔터를 쌔리자.

reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve

하는김에 짜증나던 탐색기 상단 UI도 Windows 10 스타일로 바꾸자.

reg.exe add "HKCU\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}\InprocServer32" /f /ve

만약 난 윈도우 11이 좋아~ 라면 아래 명령어로 복원도 가능하다.
Windows 11 스타일의 우클릭 메뉴 복원하기
reg.exe delete "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
 
Windows 11 스타일의 탐색기 상단 UI  복원하기
reg.exe delete "HKCU\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}" /f
 

반응형
Posted by Hippalus
,

반응형

//먼저 이런 파일명이 존재한다 치자 일부러 .을 파일명에도 넣었다.
var strData = "동해물과. 백두산이.txt"

// 파일명과 확장자를 .으로 분리한다.
if let lastDotIndex = strData.lastIndex(of: ".") {
    let fileNameWithoutExtension = String(strData[strData.startIndex..<lastDotIndex])
    print(fileNameWithoutExtension) // 출력: "동해물과. 백두산이"
} else {
    print("확장자가 없는 파일명입니다.")
}

// 다음은 원하는 자릿수부터 자릿수까지 추출한다.
// 1번째 글자부터 (0이면 처음임) 8번째 자리까지 추출한다.
let startIndex = strData.index(strData.startIndex, offsetBy: 1)
let endIndex = strData.index(strData.startIndex, offsetBy: 3)

let extractedSubstring = strData[startIndex..<endIndex]

print(extractedSubstring) // 해물

반응형
Posted by Hippalus
,

반응형

간단히 사람배열과 그 사람의 보유금액배열을 스위프트로 생성해 보겠다.
사람배열은 문자열형, 보유금액배열은 Int형이다.

var arrPerson:[String] = []
var arrMoney:[Int] = []

// 한명씩 append시키고
arrPerson.append("홍길동")
arrPerson.append("고길동")
arrPerson.append("둘리")

//순서대로 보유금액을 append시킨다.
arrMoney.append(10000000)
arrMoney.append(30000000)
arrMoney.append(0)

//이제 dictionary를 선언한다. key, value는 String,Int형이다. key에는 이름이 value에는 금액이 들어갈 것이다.
var dicData = [String:Int]()

//사람과 보유금액의 배열은 1:1이므로 사람이든 금액이든 아무 배열이나 잡고 돌리면 되지만 난 사람 배열로 돌린다.
for i in 0..<arrPerson.count {
    //dictionary의 key에 사람배열의 값, value에 보유금액의 값을 저장한다.
    dicData[arrPerson[i]] = arrMoney[i]
}

// 출력해보면 순서대로 홍길동 10000000, 고길동 30000000, 둘리 0이 찍히는것을 확인할 수 있다.
for (key, value) in dicData {
    print("\(key) : \(value)")
}

print("정렬 후 결과")

// 이제 정렬을 해보자
// 오름차순정렬이고 만약 내림차순이 하고싶다면 $0.1 < $1.1 대신 $0.1 > $1.1바꿔주면 된다.
// 참고로 0.1, 1.1은 첫번째 인자의 value 두번째 인자의 value를 뜻한다.
// 결과는 튜플로 반환가능하다.
var tupSortResult = dicData.sorted {$0.1 < $1.1}

//print해보면 정렬된 상태로 확인된다.
//[(key: "둘리", value: 0), (key: "홍길동", value: 10000000), (key: "고길동", value: 30000000)]
print("\(tupSortResult)")

//for문을 통해 돌려가며 찍어보면 아래처럼 보여진다.
// 둘리 0
// 홍길동 10000000
// 고길동 30000000
for i in 0..<tupSortResult.count {
    print("\(tupSortResult[i].key) \(tupSortResult[i])")
}

반응형
Posted by Hippalus
,

반응형

visual studio code를 설치하고 나면 기본 언어 설정이 auto인지라 메뉴명이나 결과안내 메세지들이 영어로 나온다.
영어가 익숙한 자들이야 그냥 쓰면 되겠지만 세종대왕의 얼을 지키려드는 자는 한글로 바꿔주면 되겠다.

방법은 쉽다.

참고로 난 chatGPT에 물어보니 한 세번 엉뚱한 답을 줬지만 결국 바른 답을 내주었다.

먼저 좌측 하단의 톱니바퀴 아이콘을 클릭 후 팝업컨텍스트 메뉴에서 설정메뉴를 누르거나 단축키로 ctrl + , 키를 누른다.

그럼 설정 메뉴가 호출되는데

여기 상단의 설정 검색이란 텍스트 박스에 아래와 같이 입력한다.
locale

그럼 맨 위에 TypeScript:Locale이 보이는데 
콤보박스에서 ko를 선택하고 vscode를 종료 후 다시 실행한다.

그럼 이처럼 영어 메뉴나 메세지들이 한글로 보이기 시작한다.

반응형
Posted by Hippalus
,

반응형

1차원 배열은 redim Preserve로 가능하지만
2차원 배열은 redim Preserve 순간 오류를 발생시킨다.
따라서 2차원 배열의 동적 할당을 원할 경우 최대 행 개수로 미리 Row를 할당시키는 수 밖에 없다.
사실상 절반의 동적 할당만 가능하다.

무슨 소리냐면
로직을 진행시키며 for문 등에서 조건에 맞을 때만 2차원 배열을 증가시키고 싶을 때가 있는데 이때 불가능하다란 이야기이다.
좀더 구체적으로 보자면
db에서 select를 해온다 치자
레코드의 수가 100건이다면 2차원 배열을 아래처럼 100개의 row를 보유한 2차원 배열 생성이 가능하다.
ReDim arrData(레코드의카운트-1, 1)
그런데 100건 중 특정 값을 갖고 있는 배열로만 생성하고 싶다하여 아래처럼 불가능하다.
nCount = 0
do until rs.eof
   if rs("isData") = "Y" then
      ReDim Preserve arrSlideImg(nCount , 1)
      nCount = nCount +1
   end if
   rs.movenext
loop

따라서 굳이 동적 할당이 필요하다면 일단 레코드의 수만큼만 배열을 생성하고
배열을 돌며 실제 출력할 때 빈 배열이면 exit for등으로 탈출하는 수 밖에 없다.

아래는 일반적인 2차원 배열의 동적 할당 코드 샘플이다.

<%
Dim arrData() ' 2차원 배열 선언
Dim numRows ' 행(row)의 개수를 저장할 변수

' 행(row)의 개수를 가변적으로 지정
Dim maxRows ' 최대 행(row) 개수
maxRows = 10 ' 예제에서는 최대 10으로 지정

' 변수의 값을 조건에 따라 증가시키며 배열 크기 동적 할당
numRows = 0 ' 초기 행(row) 개수는 0
ReDim arrData(maxRows - 1, 1) ' 배열 크기 동적 할당
Do While numRows < maxRows
    numRows = numRows + 1 ' 행(row) 개수 증가

    ' 배열에 데이터 채우기
    arrData(numRows - 1, 0) = numRows ' 첫 번째 열(column)에는 행(row) 번호 저장
    arrData(numRows - 1, 1) = "Data " & numRows ' 두 번째 열(column)에는 데이터 저장
Loop

' 배열 데이터 출력
Response.Write("<table border='1'>")
For i = 0 To numRows - 1
    Response.Write("<tr>")
    For j = 0 To 1
        Response.Write("<td>" & arrData(i, j) & "</td>")
    Next
    Response.Write("</tr>")
Next
Response.Write("</table>")
%>

반응형
Posted by Hippalus
,

반응형

 -- MSSQL 전체컬럼 확인방법
SELECT
   TBLNAME.name AS TBLNAME, COLNAME.name AS COLNAME
FROM
   sys.tables AS TBLNAME
   INNER JOIN sys.columns AS COLNAME ON TBLNAME.object_id = COLNAME.object_id


-- MSSQL 특정컬럼 검색방법
SELECT
   TBLNAME.name AS table_name, COLNAME.name AS column_name
FROM
   sys.tables AS TBLNAME
   INNER JOIN sys.columns AS COLNAME ON TBLNAME.object_id = COLNAME.object_id
WHERE
COLNAME.name = '찾으려는 컬럼명'

반응형
Posted by Hippalus
,

반응형

보통 게시판 페이징 쿼리를 만들 때 두가지 방법을 쓴다.
구닥다리 방법은 먼저 불러올 전체 카운트를 구하고 이를 토대로 실제 불러오는 쿼리에서 NOT IN으로 제외하고 불러오는 쿼리인데
똑같은 쿼리를 남발해야 하므로 아직도 사용하는 곳이 있다면 문제가 심각해 보이므로 PASS

두번째 방법은 ROW_NUMBER를 이용하는 쿼리인데 ROW_NUMBER()로 내마음속 번호를 생성시킨 후 이를 기준으로 페이징을 한다.
그나마 써줄만하다.

SELECT
   MEMTBL.USERID_IDX
FROM (
   SELECT ROW_NUMBER() OVER (ORDER BY USERID_IDX) AS ROWNUM, USERID_IDX FROM MEMBER_TABLE 
       ) AS MEMTBL
WHERE
   MEMTBL.ROWNUM BETWEEN 1 AND 10
 
마지막으로 MS-SQL 2012 이후 부터 사용가능한 쿼리인데 아래처럼 간결한 쿼리가 가능해졌다.

SELECT
   USERID_IDX
FROM
   MEMBER_TABLE WITH (NOLOCK)
ORDER BY 
   USERID_IDX
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY

시작위치는 OFFSET으로 지정하고
FETCH NEXT로 몇번까지 불러올지 지정만 하면 그만이다.

반응형
Posted by Hippalus
,

반응형

애플 소셜 로그인을 구현하다 보면 p8 파일 때문에 고생을 하지만 이 부분만 구현되면 다른건 문제가 되지 않는다.
딱 하나 애플은 이메일을 공개하거나 사이트마다 새로운 이메일을 생성하여 해당 사이트에 제공하도록 privaterelay.appleid.com 서비스를 제공한다.
privaterelay.appleid.com로 매핑하여 원본 이메일에 메일을 발송한다란건데
애플 소셜 로그인 구현 후 이런 이메일에 그냥 메일을 발송하면 100% 발송 실패가 뜬다.

이를 해결하기 위해 아래처럼 애플 사이트에서 사전 설정 작업을 진행해야 한다.

 

개발자 사이트 접속
https://developer.apple.com/kr/

계정(account) 메뉴 선택
https://developer.apple.com/account

 


인증서, 식별자 및 프로파일 하단 메뉴들 중 아무메뉴나 선택 하면 좌측에 메뉴들 중 Services를 선택
Certificates
Identifiers
Devices
Profiles
Keys
Services



Sign in with Apple for Email Communication의 Configure버튼 선택하면 아래 링크로 최종 이동 된다.
https://developer.apple.com/account/resources/services/configure

여기에서 발송할 도메인과 Email을 입력하면 된다.
여러개인 경우 콤마(,)로 구분하면 됨

 

로그인 - Apple

 

idmsa.apple.com

 

반응형
Posted by Hippalus
,