후원 여부 상관 없이 상품수 검색 결과 수를 제한을 없앴습니다.

 

프로그램 설치 하면 상품수 조회를 제약 없이 사용 하실 수 있습니다.

 

필요하신분들은 많이 이용해 주시고 댓글도 남겨주시면 감사하겠습니다. 

 

 

프로그램 시작하기

  - 프로그램 사용은 누구나 메일 인증만 되면 자유롭게 사용 할 수 있습니다. 

   현재 버전은 v1.0.1 입니다.
    등록하기 버튼을 클릭하여 정상적으로 요청이 되었는지 확인 후 (수초 정도 걸릴 수 있습니다)

    메일 수신함에서 등록 요청 링크를 눌러서 메일 인증을 완료하시면 됩니다.
    주의!! PC당 하나의 이메일 계정만 등록하여 사용할 수 있습니다.

프로그램 메인 화면입니다.

 

1. 키워드를 입력하는 곳입니다. 최대 5개까지 검색 가능하며 콤마(,) 나 앤터키(Enter) 로 키워드를 구분합니다.

2. 입력한 키워드로 키워드에 대한 조회수를 출력하기 위한 검색 버튼입니다.

3. 키워드에 대한 조회수 결과 리스트입니다. (정렬지원)

4. 상품조회 한도 : 1 ~ 300 건을 조회 가능, 또는 All(전체 : 사용시 주의!! 상당한 시간이 걸릴 수 있음.부작용.)

5. 조회대상 사이트 네이버, 11번가, 쿠팡을 선택하여 상품수 를 출력하는 버튼입니다.

    (멀티스레드 기반으로 검색 속도를 향상시켰습니다.)

6. 네이버에 등록되어 있는 키워드에 대한 전체 상품수입니다. 클릭시 네이버 쇼핑몰로 이동 (정렬지원)

7. 키워드의 조회수 대비 네이버 전체 상품의 비율을 나타냅니다. (정렬지원)

   (일반적으론 값이 적을 수록 조회수는 많은데 상품은 적다는 뜻)

8. 6과 마찬가지이며 11번가 대상입니다.

9. 7과 마찬가지이며 11번가 대상입니다.

10. 11. 위와 같고 대상은 쿠팡입니다.

 

프로그램 설치 관련 정보

 - 프로그램 설치 관련 상세 도움이 필요하시면 아래 링크로 가주세요. 

 

네판왕 설치하기(네이버 광고 키워드 상품수 검색 프로그램)

1. 프로그램 다운로드  설치 파일(NePanKing-1.0.0.msi)을 다운로드 받고 설치 프로그램을 실행합니다. 2. Micorosoft Defender SmartScreen 창이 뜨면 [추가정보]를 눌러서 실행을 해주시면 됩니다.  (ms 정책..

ososoi.tistory.com

 

 네이버광고 페이지에서 사용키 발급 관련 정보

 

네이버 광고 키워드 검색량 프로그램 소개 및 키 발급 (네판왕)

1. 키를 먼저 발급을 받습니다. 이미 발급 받았고 키를 알고 있다면 (2) 로 가주세요. 구글 / 네이버 검색창에서 '네이버광고' 를 검색해서 네이버 광고 페이지에 접속합니다. https://manage.searchad.nave

ososoi.tistory.com

 

 

Notice!

스터디를 위해 개인적으로 진행하고 있는 프로젝트입니다.
본 사이트에서 제공하는 정보는 오류가 있을 수 있고, 이것을 이용함에 있어 책임은 이용자 본인에게 있습니다.
서버의 운영 유지비 및 개발을 위해 후원도 받습니다. 아주 작은 금액도 감사히 받겠습니다. 여러분들의 작은 손길이 좋은 프로그램을 만드는데 힘이 됩니다.
문의 : ososoi@daum.net

 

History

2020-08-03  특이테마 개별 종목 리스트 기능 개발

2020-08-01  특이테마 추이 기능 개발

2020-07-30

    재무순위에서 [per, pbr] 스코어 합산에서 제외

    조건검색에서 신규 검색식 [VOS_MACD] 추가

2020-07-28  조건검색 결과 일부 종목 누락 현상 수정

2020-07-18  조검검색 결과 증권사 투자의견 추가
2019-06-13  사이트 재구축
2019-04-29  서비스 중단
2019-04-07  조건검색식 연동완료
2019-04-06  항목 설명 팝업창 추가
2019-04-05  종목코드-다음빅차트/종목명-네이버증권 링크설정
2019-04-02  조건검색 개발시작
2019-03-20  재무순위 개발시작
2019-03-01  사이트 구축

 

화면 사이즈 구하기

 

MediaQuery.of(context).size
MediaQuery.of(context).size.height
MediaQuery.of(context).size.width

 

 

<샘플예제>

  popupAddItem() {
    showDialog(
      context: context,
      builder: (context) {
        return Dialog(
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
          elevation: 16,
          child: Container(
            height: MediaQuery.of(context).size.height * 0.8,
            width: MediaQuery.of(context).size.width * 1.2,
            child: ListView(
              children: <Widget>[
                SizedBox(height: 20),
                Center(
                  child: Text(
                    "종목등록",
                    style: TextStyle(
                        fontSize: 24,
                        color: Colors.blue,
                        fontWeight: FontWeight.bold),
                  ),
                ),
                TextField(
                  controller: _textController,
                  onSubmitted: _handleSubmitted,
                  decoration: new InputDecoration(
                      hintText: "종목코드 / 종목이름으로 검색하세요.",
                      border: new UnderlineInputBorder(
                          borderSide: new BorderSide(color: Colors.red))),
                ),
                Container(
                  margin: const EdgeInsets.symmetric(horizontal: 4.0),
                  child: IconButton(
                      icon: Icon(Icons.search),
                      onPressed: () => _handleSubmitted(_textController.text)),
                ),
                _buildListItem(),
                SizedBox(height: 20),
                RaisedButton(child: Text("등록"), onPressed: (){},),
              ],
            ),
          ),
        );
      },
    );
  }

 

 

 

 

 

 

 

 

 

 

 

flutter 에서 다국어를 쉽게 적용 할 수 있는 방법을 알아보도록 하겠습니다.

 

우선 아래 사이트에서 한번 살펴 보는 것도 좋을 듯 싶습니다.

 

패키지는 easy_localization 을 사용할 겁니다. 말 그대로 '쉬운 다국어' 이네요.

 

현재 버전은 easy_localization 2.3.2 입니다.

 

 

easy_localization | Flutter Package

Easy and Fast internationalizing and localization your Flutter Apps, this package simplify the internationalizing process .

pub.dev

1. 디펜던시스 에 추가

dependencies:
	easy_localization: ^2.3.2

 

2. 다국어를 쓸수 있게 파일을 작성

   - 프로젝트 폴더 밑에 assets / translations / 폴더를 차례대로 만들고 json 파일 두개를 아래와 같이 만듭니다.

 

3. 그다음엔 다국어 파일의 내용을 작성해야겠죠

   - 길어서 짤렸습니다. 쌍따움표로 묶고 마지막에 , 찍으면 됩니다.

 

4. main.dart 로 돌아와서 내용을 추가해줍니다.

  - 기존 MyApp() 가 child 로 들어갑니다.

void main() {
  runApp(EasyLocalization(
      supportedLocales: [Locale('en', 'US'), Locale('ko', 'KR')],
      path: 'assets/translations',
      fallbackLocale: Locale('en', 'US'),
      child: MyApp()));
}

 

5. MyApp 클래스의 build() 추가해줍니다. 다국어 설정이 바꼈을 때 앱내에서 변환할 수 있도록

  - localizationsDelegates ~~ local: context.locale, 까지입니다.  그 밑은 네비게이터 코드입니다.

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      routes: <String, WidgetBuilder>{
        // Set routes for using the Navigator.
        '/': (BuildContext context) => Landing(),
        '/home': (BuildContext context) => DashBoard(Colors.white),
        '/login': (BuildContext context) => LoginPage()
      },
    );
  }
}

 

6. 그럼 잊지말고 import 를 추가해줘야 겠죠

import 'package:easy_localization/easy_localization.dart';

 

7. pubspec.yaml 에 assets 을 알려줘야 합니다. 이것도 잊지말고 잘 추가해주세요.

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/translations/ko-KR.json
    - assets/translations/en-US.json

 

8. 이제 코드에 적용하면 됩니다.

    - 사용 하는 곳에도 import 해주세요

showAlertDialog(context, "failed_login".tr());

 

 

 

 

 

 

 

 

 

 

 


print(getAppVersionBuild())



func getAppVersionBuild() -> String

{

    let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String

    let build = Bundle.main.infoDictionary!["CFBundleVersion"] as! String



    return version + "." + build

}

 

 

 

 

 

 

Django 에 캐싱을 적용해 보자

 

dataframe 타입의 1000건 이상의 레코드를 DB에서 읽어 웹페이지에 계속 뿌려주는 케이스가 있는데, 

굳이 하루에 한번만 요청에 의해서 DB에 갔다오면 될 듯 하여 캐싱을 적용하기로 했습니다.

 

 

setting.py 에 추가

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:6379',
    }
}

 

웹서버 실행 시 아래의 오류가 발생한다면

ModuleNotFoundError: No module named 'memcache'

python-memcached 모듈 설치

$ pip install python-memcached

 

views.py 코드에서

key_mydf = 'key_finance'
df = cache.get(key_mydf)

if df is None:
  
  ''' 여기서 부터 DB작업 '''
  
  
  cache.set(key_mydf, df, 86400)
  # 864000 은 하루만큼의 초(sec)

  ''' 중략 '''
  
return render(request, 'finance.html', {'df': df})

- 캐시에 df 가 적재되어 있지 않으면 DB 작업을 통해 데이터를 가져온 후 캐시에 저장한다

- 다음 요청부터 캐시의 데이타를 사용한다

- 하루가 지나면 캐시는 해제된다.

 

 

추가 - 혹시 캐싱이 제대로 안되는 경우 

- 새로 서버를 구축한 후 로그 출력해서 확인 해본 결과 위 내용으로 제대로 캐싱이 먹히지 않았다. 

  캐싱이 안될경우 setting.py 의 middleware 에 아래 두줄 추가하고 

    MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
    ]

같은 setting.py 파일에 아래 4줄을 추가해준다. 

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
CACHE_MIDDLEWARE_ALIAS = 'default'  # which cache alias to use
CACHE_MIDDLEWARE_SECONDS = 600    # number of seconds to cache a page for (TTL)
CACHE_MIDDLEWARE_KEY_PREFIX = ''

제대로 캐싱이 되는것을 확인.

 

 

 

 

 

 

 

 

 

net-snmp 를 사용 하여 프로그램이 정상 동작 중 , 갑자기 snmp v3로 등록해두었던 장비들이 수집이 되지 않네요.

 

tcpdump 를 통해 확인 한 에러 정보는 장비쪽에서 리포트메세지가 날아오며,

 

UnknownEngineID 라는 메시지입니다.

 

snmp v3 를 테스트 할때 snmpget / snmpwalk 명령어를 사용할 수 있습니다.

 

 

이것을 가지고 샘플을 만들어보면  일반적으로

 

$ snmpget -v3 -l authPriv -u ososoi -a SHA -A brain33a -x AES -X brain33x 10.0.0.207 .1.3.6.1.2.1.1.3.0

iso.3.6.1.2.1.1.3.0 = Timeticks: (185222) 0:30:52.22

 

위와 같이 만들 수 있습니다.

 

여기서 engineid와 engine boots, engine time 을 지정하여 장비쪽으로 전송 할 수 있습니다.

 

unknown engine id 에러가 뜨는 경우 아래와 같이 한번 해보길 바랍니다.

 

$ snmpget -v3 -l authPriv -u ososoi -a SHA -A brain33a -x AES -X brain33x -e 80001f88809fad4d458bbc115f -Z 1/15 10.0.0.207 .1.3.6.1.2.1.1.3.0

iso.3.6.1.2.1.1.3.0 = Timeticks: (205022) 0:34:10.22

 

SNMP Version 3 specific 
  -a PROTOCOL           set authentication protocol (MD5|SHA) 
  -A PASSPHRASE         set authentication protocol pass phrase 
  -e ENGINE-ID          set security engine ID (e.g. 800000020109840301) 
  -E ENGINE-ID          set context engine ID (e.g. 800000020109840301) 
  -l LEVEL              set security level (noAuthNoPriv|authNoPriv|authPriv) 
  -n CONTEXT            set context name (e.g. bridge1) 
  -u USER-NAME          set security name (e.g. bert) 
  -x PROTOCOL           set privacy protocol (DES|AES) 
  -X PASSPHRASE         set privacy protocol pass phrase 
  -Z BOOTS,TIME         set destination engine boots/time 

 

 

그럼 engineid와 boots / time 을 어떻게 구하는냐 ?

아래의 OID를 통해서 알 수가 있습니다.

 

1.3.6.1.6.3.10.2.1.1 snmpEngineID 1 1 An SNMP engine's administratively-unique identifier.
1.3.6.1.6.3.10.2.1.2 snmpEngineBoots 1 1 The number of times that the SNMP engine has
(re-)initialized itself since snmpEngineID
was last configured.
1.3.6.1.6.3.10.2.1.3 snmpEngineTime 1 1 The number of seconds since the value of
the snmpEngineBoots object last changed.
When incrementing this object's value would
caus…

 

Engine ID 입니다.

$ snmpget -v3 -l authPriv -u ososoi -a SHA -A brain33a -x AES -X brain33x 10.0.0.207 1.3.6.1.6.3.10.2.1.1.0

iso.3.6.1.6.3.10.2.1.1.0 = Hex-STRING: 80 00 1F 88 80 9F AD 4D 45 8B BC 11 5F

 

Engine Boots 입니다.

$ snmpget -v3 -l authPriv -u ososoi -a SHA -A brain33a -x AES -X brain33x 10.0.0.207 .1.3.6.1.6.3.10.2.1.2.0

iso.3.6.1.6.3.10.2.1.2.0 = INTEGER: 1

 

Engine Time 입니다.

$ snmpget -v3 -l authPriv -u ososoi -a SHA -A brain33a -x AES -X brain33x 10.0.0.207 .1.3.6.1.6.3.10.2.1.3.0

iso.3.6.1.6.3.10.2.1.3.0 = INTEGER: 2417

 

 

 

centos7에서 테스트 하였습니다.

 

glibc 버전을 확인 하기 위해서 쉘에서 다음의 명령어 들로 확인 할 수 있다.

 

$ getconf -a | grep libc

GNU_LIBC_VERSION                   glibc 2.5

 

$ ldd --version

ldd (GNU libc) 2.5
Copyright (C) 2006 Free Software Foundation, Inc.

 

 

번외로 GLIBC 버전 히스토리

2011-02-01	GLIBC 2.13	glibc 2.13
2010-12-13	GLIBC 2.12.2	
2010-11-30	GLIBC 2.11.3	glibc-2.11.3 released
2010-08-03	GLIBC 2.12.1
2010-05-19	GLIBC 2.11.2	glibc-2.11.2 released
2010-05-03	GLIBC 2.12	glibc 2.12
2009-12-29	GLIBC 2.11.1	glibc-2.11.1 released
2009-11-16	GLIBC 2.10.2	
2009-11-03	GLIBC 2.11	glibc 2.11
2009-05-18	GLIBC 2.10.1
2009-05-09	GLIBC 2.10	2.10 done
2008-11-13	GLIBC 2.9	glibc 2.9
2008-04-12	GLIBC 2.8	glibc 2.8
2007-10-19	GLIBC 2.7	glibc 2.7
2007-07-31	GLIBC 2.6.1	GNU C Library version 2.6.1 release
2007-07-31	GLIBC 2.5.1	GNU C Library version 2.5.1 release
2007-05-17	GLIBC 2.6	glibc 2.6
2006-09-29	GLIBC 2.5	glibc 2.5

 

버전 2.5 ~ 2.13 까지

 

 

 

 

클라우드 서버에 외부 접속 가능하도록 서버를 실행 시키고 

host : 0.0.0.0

port : 8008

 

여러가지 방법으로 시도 해도 클라우드 서버의 Django 서버에 접속 실패 하는 상황

1. 클라우드 홈의 방화벽 설정에서 포트 설정

2. selinux 를 끄고

3. iptable 을 꺼도

 

모두 안됐는데, 다음 한줄이 해결책이었다...

 

firewall-cmd --add-port=8008/tcp

 

만약 서버 재부팅 시에도 계속 유지를 하고 싶다면

 

--permanent 옵션을 추가한다.

 

firewall-cmd --permanent --add-port=8008/tcp

 

클라우드에서 CentOS8 x64 인스턴스를 생성했습니다.

 

저는 vultr.com 이라는 클라우드 호스팅 업체를 이용하고 있습니다. 저렴하고 괜찮은 것 같습니다. 아래링크를 타고 가시면 됩니다.

 

SSD VPS Servers, Cloud Servers and Cloud Hosting by Vultr

Vultr Global Cloud Hosting - Brilliantly Fast SSD VPS Cloud Servers. 100% KVM Virtualization

www.vultr.com

 

CentOS8 이 설치가 됐다고 가정하고

 

 

개발툴 관련 패키지를 차례대로 설치를 합니다.

$ yum -y update

yum -y groupinstall "Development Tools"

yum -y install openssl-devel bzip2-devel libffi-devel

 

 

다음으로 파이썬3.8 을 설치하기 위해 wget 을 설치합니다.

$ yum -y install wget

$ wget www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz

$ tar xvf Python-3.8.3.tgz

 

파이썬3.8 컨피그레이션과 인스톨 수행

$ cd Python-3.8.3

$ ./configure --enable-optimizations

$ make altinstall

 

 

인스톨이 끝나고 나서 제대로 설치 되어 있는지 버전 확인

 

$ python3.8 --version

 

.bash_profile 에 alias 를 등록하여 python 으로 실행하도록 바꿉니다

 

alias python='python3.8'

 

설치된 파이썬 버전 확인

 

혹시, 파이썬 실행시 아래와 같은 오류가 발생한다면

 

ModuleNotFoundError: No module named '_sqlite3

 

$ yum install sqlite-devel

 

설치 후 , 파이썬 재 설치를 진행한다.

 

$ ./configure --enable-optimizations

$ make altinstall

 

 

 

저는 vultr.com 라는 해외 클라우드를 사용하고 있는데 생각보다 저렴합니다. AWS , KT클라우드 보다 쌉니다.

 

작년까진가 인스턴스는 아시아에 싱가포르, 일본 밖에 없었는데 언제부터 생겼는지 서울이 생겼더군요. 

 

일본, 싱가포를 이용할땐 가끔씩 장애도 많이 나고 그랬었는데, 서울로 인스턴스를 옮긴 후부터는 확실히 장애가 거의 없는듯 합니다.

 

젤 저렴한 5천원 짜리도 있고, 적당히 개인사이트 운영에는 만원짜리도 충분 할 듯 싶습니다. 

 

아래 링크 걸어 두었으니 관심 있으신 분들은 저렴하게 나만의 서버를 가지시고 구축해보시면 좋을 것 같습니다.

 

 

 

 

SSD VPS Servers, Cloud Servers and Cloud Hosting by Vultr

Vultr Global Cloud Hosting - Brilliantly Fast SSD VPS Cloud Servers. 100% KVM Virtualization

www.vultr.com

본론으로 저는 여러가지 방법으로 시도 해보았는데 다 실패하고 수동으로 Let's Encrypt 인증서를 생성에 성공 하였습니다.

 

1. certbot 다운

  첫번째로, 적당한 위치에 certbot 을 다운 받습니다.

wget https://dl.eff.org/certbot-auto

 

2. certbot 권한 부여

   실행 권한을 부여합니다.

hmod a+x certbot-auto

 

3. 인증서 생성 명령 실행

  certbot-auto을 이용하여 수동으로 인증서를 생성합니다. vostock.kr 은 제 도메인입니다.

certbot certonly -d vostock.kr --manual --preferred-challenges dns

 

4. DNS TXT 네임과 value 확인

  위 명령을 실행하면 아래 처럼 출력이 되는데 붉은 박스의 첫번째 줄의 challenge 네임과 (_acme~~.kr 까지) 그리고 두번째 줄의 value 를 기억해 둡니다.

  주의!! 여기서 바로 엔터를 눌러서 진행 하면 안됩니다. 5번으로 가서 클라우드 DNS 설정을 추가해야합니다.

 

 

5. 클라우드 DNS 설정 변경

  자신의 클라우드 서버에 접속하여서 DNS 설정에서 (이부분은 클라우드 업체가 다르다 보니 상이할듯 하지만) 

TXT타입으로 DNS 를 추가합니다. 

 

6. SSL 인증서 받기 마무리 하기

   5번을 한후 다시 돌아와서 엔터키를 누르면 인증서를 받았다고 축하해줍니다.

 

주의: 여러번 실패할 경우 강제로 Let's Encryt 에서 일정시간 모든 요청이 거부당합니다. 

        90일 만기이므로 주기적으로 갱신을 시켜줘야 합니다. 이것은 스크립트로 등록해서 자동 처리 할 수 있습니다.

 

crontab -e

위 명령어 실행 후 vi 모드에서 아래 행 추가

0 0 1 * * certbot renew

 

 


현재 적용중인 조건 검색식 리스트 입니다. 

종목들은 메뉴 [조건검색검출종목]에서 확인 할 수 있습니다.

여러분들의 성공적인 투자 기원합니다.

 

기존 아래 4가지 전략에서 

 

1. 20이평 근접

2. 기관외인 입질

3. 볼린저밴드 하단

4. 거래량 수상

 

다음 3가지로 변경했습니다. 텍스트로는 길어서 이미지로 대체합니다.

1. 주봉이동평균돌파

2. 일봉이동평균돌파

3. MACD 시그널 돌파

 

MACD 시그널 돌파
일봉이동평균돌파
주봉이동평균돌파

 


위의 조건들을 토대로 해서 나온 결과가 조건검색검출 종목 메뉴의 일자별 종목 리스트 입니다.

 

계속해서 검색식을 테스트 하고 좀더 좋은 종목을 찾기 위해서 연구를 해야할 것 같습니다.

 

 

 

 

1. 프로그램 다운로드

   설치 파일(NePanKing-1.0.0.msi)을 다운로드 받고 설치 프로그램을 실행합니다.

 

NePanKing-1.0.1.msi
1.08MB

 

2. Micorosoft Defender SmartScreen 창이 뜨면 [추가정보]를 눌러서 실행을 해주시면 됩니다.

   (ms 정책이라 저같은 듣보잡 소프트웨어 설치시 경고메세지가 나옵니다.ㅜ;)

 

 

3. 설치 인스톨러가 화면에 뜨면 다음 버튼을 눌러 계속 설치를 진행합니다.

 

 

4. 설치 폴더를 선택하거나 다음 버튼을 눌러 계속 진행합니다.

   기본 위치는 [C:\Program Files (x86)\NePanKing\] 입니다.

 

 

5. 설치가 완료되었습니다.

 

 

6. 바탕화면에 보시면 바로가기가 생성되었을 겁니다.

 

7. 프로그램을 실행을 하면 로그인창이 뜹니다.

   이후의 진행은 등록하기 버튼을 눌러서 이메일 인증 후 사용하시면 됩니다. 

   

 

 

현재 알림을 받을 수 있는 상태인지 아닌지 확인 하는 Swift 코드입니다.

 

let isRegistered = UIApplication.shared.isRegisteredForRemoteNotifications

if(isRegistered) {

}

else {

}

 

예제 코드

// 알림 설정이 on / off 인지 확인 후 , off 일 경우 알림을 활성화 하라는 얼럿창 노출
let isRegistered = UIApplication.shared.isRegisteredForRemoteNotifications
if(isRegistered) {
   //
   _ = SweetAlert().showAlert("title_regist".localized, subTitle: "알림 수신이 설정되어 있습니다", style: AlertStyle.warning)
   return
}
else{
   _ = SweetAlert().showAlert("title_regist".localized, subTitle: "알림 수신 설정을 활성화 하세요", style: AlertStyle.warning)
   return
}

 

SweetAlert 은 얼럿창관련 오픈 소스인데 https://sweetalert2.github.io/

여기로 가시면 다운 받을 수 있습니다.

 

SweetAlert2

A beautiful, responsive, customizable and accessible (WAI-ARIA) replacement for JavaScript's popup boxes

sweetalert2.github.io

일단 IOS13에서 테스트 해보니 잘 됩니다.

 

 

백터 사용 시 실수 할 수 있는 문제입니다.

 

아래 코드에서 어떤 문제점이 있나 한번 보실래요?

 

#include "stdafx.h"
#include <string>
#include <vector>

using namespace std;

int fn1(vector<string> *pvt) {

	int totallen = 0;
	
	for (int i = 0; i < pvt->size(); i++) {
		totallen += pvt[i].size();
	}
	
	return totallen;
}

int main()
{
	vector<string> vtDumy;
	vtDumy.push_back("hello");
	vtDumy.push_back("my");
	vtDumy.push_back("name");
	vtDumy.push_back("is");
	vtDumy.push_back("ososoi!");

	int totallen = fn1(&vtDumy);

	printf("total len=%d\n", totallen);

	getchar();
    return 0;
}

 

 

위 코드를 가지고 visual studio 에서 빌드하면 정상적으로 빌드가 되고 실행도 됩니다. 

 

우리가 예상한 결과값은 "hellomynameisososoi!" 총 20자 입니다.  

 

하지만 실행하게 되면 

 

오잉 쓰레기값이??

 

결과를 말씀드리면 아래코드에서 문제가 있습니다.

 

totallen _= pvt[i].size();

 

여기서 pvt는 백터의 포인터이기 때문에 실제 우리가 원하는 백터의 n번째 원소(string)의 길이를 얻기위해서는

 

totallen += (*pvt)[i].size();

 

더 명시적으로 표현하자면 아래와 같습니다.

 

totallen += (*(vector<string>*) pvt)[i].size();

 

 

비단 벡터 뿐만 아니라 포인터를 다루면서 종종 실수 할 수 있는 경우인데요,

 

기본 변수 타입의 포인터는 익숙해서 실수를 잘 안 할 수 있는데, 벡터등 컨터이너에 포인터를 붙일 때 . 찍고 컴파일 오류가 없기 때문에 그냥 지나칠 수 있을 것 같습니다.

 

저도 좀전에 실수 해서 생각 나는 김에 여기에 샘플코드와 함께 적어봤습니다. 

 

 

코딩량이 많고 빨리빨리 작업하다보면 빌드가 정상적으로 되는 것을 보고 그냥 지나칠 수 있는데요,

 

잘못하다간 나중에 로직에러 / 데이터 검증에 디버깅 할때는 더 많은 수고가 들지도 모르겠죠..;;

 

포인터를 다룰 때는 함수의 전달과 사용되는 부분들을 꼼꼼히 훑어 보고 다음 코드로 넘어가는 습관과 펑션을 짜고 나서 데이터 전달. 연산에 대한 테스팅을 한번씩 해보고 다음 단계로 넘어가는 습관이 중요할 것 같습니다.

 

 

+ Recent posts