종달랩 종다리 이야기

2024년 중앙부처 및 지자체 창업지원사업 통합공고 입니다.

IT뉴스
반응형

2024년 창업지원사업 통합공고 입니다.

 

2023년에 비해서 자금규모는 전년과 유사한 규모입니다.

 

 

https://kpdf.k-startup.go.kr:8443/SynapDocViewServer/viewer/doc.html?key=7ca1dcd32bc74537bba97773f3e84443&convType=img&convLocale=en_US&contextPath=/SynapDocViewServer

 

Document Viewer

 

kpdf.k-startup.go.kr:8443

2024년_중앙부처_및_지자체_창업지원사업_통합공고.pdf
5.50MB

 

 

 

반응형

샘알트만의 OpenAI CEO 해고가 주는 의미

해우소
반응형

 

샘알트만이 미국시간으로 2023년 11월 18일 금요일에 해임되었다고 한다.

이사회의 결정이였고, 이러한 결정은 매우 전격적으로 진행된듯 싶다.

 

샘알트만은 개발자는 아니지만, Y Combination 파트너로 여러 스타트업의 초기 펀딩에 참여해서 상당한 부를 갖고 있는 30대 투자자이기도 하다.

 

이사회의 결정에는 샘알트만이 CEO로써 상당한 신뢰를 잃었기 때문에 해고를 감행했다고 전해졌다.

 

상당한 신뢰를 잃었다는 것은 무엇을 의미할까가 궁금하였다.

 

샘앞트만은 OpenAI의 창업자이자 경영인의 역활을 수행하면서 ChatGPT를 성공적으로 오픈하였고, 대외적으로 상당한 금액의 투자를 이끌어내는데 성공한 능력있는 경영자이다.

하지만, 다른 한편으로는 AI규제의 필요성을 강조하는 부분이 있었다고 한다. 특히 가짜뉴스와 선거부분에서의 걱정에 대해서 미국정부가 모델개발을 위한 라이센스나 테스트 도입을 하는 방안을 고려해야 한다고 주장했다고 한다.

이러한 주장은 안정성과 윤리를 위해 OpenAI를 설립한 초기 취지에 부합한다는 옹호의견도 있지만, 다른 한편으로는 기술우위를 통한 후발주자의 견제를 의미하기도 한다.

 

샘알트만이 어떠한 모습을 취하였건, 그는 매우 공격적인 경영을 하였고, 이러한 그의 모습이 OpenAI의 근본적인 부분을 훼손했다고 이사진들이 판단했을 수 있다.

인공지능에 대한 양날의 검에 대해서 경영자가 선의적인 모습을 갖기는 힘들만큼 OpenAI는 빠르게 성장했고, 이에 대해서 그가 회사내부에 주는 시그널이 혼선이 있었을 것이고, 이에 따라 이사진들은 그를 신뢰하지 않고, 오히려 CTO에게 임시대표자리를 넘겼다는 것으로 봐서는 OpenAI의 근본취지를 이사진들이 더 따랐을 수도 있다.

 

MS외 기타 다른 외부 세력들이 샘알트만의 복귀를 위해서 애쓴다고 했을때, 그의 복귀가 가능할지는 모르지만, 다시 복귀한다면 OpenAI는 좀 더 과격하게 서비스를 확장해 나갈것이고, 이는 AI시장에 그렇게 좋은 시그널이 아닐 수 있을지도 모른다.

반응형

Docker run 옵션 및 활용

Computer Science/클라우드-대용량 아키텍처
반응형

Docker run 명령어를 정리합니다.

 

일반적으로 docker 이미지를 만들었다면 다음과 같이 실행하게 됩니다.

 

docker run <옵션> <이미지> <명령> <매개변수>

 

다음과 같은 형태로 만들어지게 됩니다.

docker run -it -p 8080:80 --nmae mydockerimg

여기서 사용되는 다양한 옵션들에 대해서 정리해보면 다음과 같습니다.

 

  • -i, --interactive
    • 표준 입력(stdin)을 활성화하며, 컨테이너와 연결(attach)되어 있지 않더라도 표준 입력을 유지합니다.
    • 보통 이 옵션을 사용하여 Bash 에 명령을 입력합니다.
  • -t, --tty
    • TTY 모드(pseudo-TTY)를 사용합니다.
    • Bash를 사용하려면 이 옵션을 설정해야 합니다.
    • 이 옵션을 설정하지 않으면 명령을 입력할 수는 있지만, 셸이 표시되지 않습니다.
  • --name
    • 컨테이너 이름을 설정합니다. 사용할 이름과 표시할 이름을 설정할 수 있습니다.
  • -d, --detach
    • Detached 모드입니다.
    • 보통 데몬 모드라고 부르며, 컨테이너가 백그라운드로 실행됩니다.
  • -p, --publish
    • 호스트와 컨테이너의 포트를 연결합니다. (포트포워딩)
    • <호스트 포트>:<컨테이너 포트>
      • -p 80:80
  • --privileged
    • 컨테이너 안에서 호스트의 리눅스 커널 기능(Capability)을 모두 사용합니다.
    • 호스트의 주요 자원에 접근할 수 있습니다.
  • --rm
    • 프로세스 종료시 컨테이너 자동 제거
  • --restart
    • 컨테이너 종료 시, 재시작 정책을 설정합니다.
      • --restart="always"
  • -v, --volume
    • 데이터 볼륨을 설정입니다.
    • 호스트와 컨테이너의 디렉토리를 연결하여, 파일을 컨테이너에 저장하지 않고 호스트에 바로 저장합니다. (마운트)
  • -u, --user
    • 컨테이너가 실행될 리눅스 사용자 계정 이름 또는 UID를 설정합니다.
      • --user root
  • -e, --env
    • 컨테이너 내에서 사용할 환경 변수를 설정합니다.
    • 보통 설정 값이나 비밀번호를 전달할 때 사용합니다.
      • -e GRANT_SUDO=yes
  • --link
    • 컨테이너끼리 연결합니다.
    • [컨테이너명 : 별칭]
      • --link="db:db"
  • -h, --hostname
    • 컨테이너의 호스트 이름을 설정합니다.
  • -w, --workdir
    • 컨테이너 안의 프로세스가 실행될 디렉터리를 설정합니다.
  • -a, --attach
    • 컨테이너에 표준 입력(stdin), 표준 출력(stdout), 표준 에러(stderr) 를 연결합니다.
  • -c, --cpu-shares
    • CPU 자원 분배 설정입니다.
    • 기본 값은 1024이며, 각 값은 상대적으로 적용됩니다.
  • -m, --memory
    • 메모리 한계를 설정합니다.
    • <숫자><단위> 형식이며 단위는 b, k, m, g 를 사용할 수 있습니다
      • --memory=”100000b”
  • --gpus
    • 컨테이너에서 호스트의 NVIDIA GPU 를 사용할 수 있도록 설정합니다.
      • 호스트는 NVIDIA GPU 가 장착 된 Linux 서버여야하며,
      • NVIDIA driver 가 설치되어 있어야하고,
      • docker 19.03.5 버전 이상이어야합니다.
    • GPU 모두 사용하기
      • --gpus all
    • GPU 지정해서 사용하기
      • --gpus ‘”device=0,1”’
  • --security-opt
    • SELinux, AppArmor 옵션을 설정합니다.
      • --security-opt=”label:level:TopSecret”

참조한 사이트는 다음과 같습니다.

도커의 동작 시각화 자료

 

반응형

디지털패션산업 전환의 걸림돌-1

부자마켓/지금 패션 트랜드는
반응형

제목 : 정보격차에 따른 패션산업의 불명확성

 

이 컬럼은 종달랩 회사를 운영하면서 회사가 목표한 패션산업의 디지털화를 위한 기술개발, 사업화 및 이를 위한 산업생태계에서 겪은 내용들을 기반으로 패션산업의 디지털화 전환의 걸림돌에 대한 내용을 정리한 것입니다. 최대한 객관적으로 내용을 정리해서 다른 모든 사람들이 패션산업의 혁신을 같이 만들어 내기를 원하는 마음에 스스로 기고합니다. 2022.8.21 

 

패션산업은 매우 오랜 전통을 갖고 있다. 학문적인 접근이 아니더라도, 6.25전쟁을 겪으면서 산업화를 위한 다양한 노력들 중에 가발산업, 봉제산업은 우리나라를 빠르게 산업화하고 국가를 세워나가는데 큰 몫을 한것은 배워서 알고 있다.

 

이러한 패션산업은 다양한 학문적 가치를 갖고 충분히 발전해 왔으며, 원사, 원단등의 대량의 자본과 노동력이 들어가는 분야에서 혁혁한 성과를 만들어 냈다. 이를 위해서는 정부의 지원이 필요했고, 이러한 산업을 통해서 방직공장기반의 대기업들이 하나둘 생겨나기 시작하였다.

 

원사, 원단을 바탕으로 우리는 외주용역기반의 옷을 만들기 시작했고, 다시 패션을 응용(카피가 더 정확할것 같지만)하여 자체 패션을 만들어 내기 시작하였다. 대량소품종의 제품에서 소량 다품종 시장이 형성될때까지 이 시장에서는 다양한 브랜드가 만들어 졌고, 이들또한 대기업으로 빠르게 성장하였다.

 

원사(원단) 및 완제품의 유통시장은 대기업으로 빠르게 성장하는 기업들이 만들어 졌지만, 그 안에서 다양한 패션제품을 디자인, 기획, 생산하는 분야에서는 유독 크게 성장하는 기업들이 많지 않다는 것이 특징이다. 우리가 기억하는 전태일열사는 이러한 시장쪽에 종사하고 있었고(봉제시장) 이는 매우 열악했었음을 알 수 있다.

 

내가 어릴때, 온양-천안 사이에 동방방직(?)이 있었고, 여기서는 중,고등학교를 가르치면서 밤에는 봉제(미싱)를 병행했던 곳으로 기억한다. 단순 대량의 봉제시절까지는 대기업들이 참여하고 있지만, 패션트렌드가 바뀌면서 대기업들은 해외로 공장을 돌리기 시작했고, 국내의 소량다품종은 중소공장들이 그 위상을 차지하기 시작했다.

 

원단의 생산에서 봉제공장까지 들어가는 그 과정에도 역시 중소기업들이 참여하게 된다. 다양한 시장의 니즈를 일반 대기업들은 대응할 수 없었고, 이를 중간 유통업자들이 전문적으로 대응하면서, 원단공장은 도매(에이전시)를 고객으로 자연스럽게 받아들이게 되고, 도매가 일반 디자이너를 상대하는 구조가 형성이 되기 시작했다.

 

이는 개인적으로 매우 매력적인 시장일 수 있다. 도매는 대기업단위로 클 필요가 없다. 생각보다 진입장벽이 낮기 때문이다. 조금만 사장님이 일하는것을 알게 되면, 거래처만 들고 나와도 바로 사업을 할 수 있기 때문이다. 그러다 보니, 개인적인 부를 키우는 사람들은 늘어났지만, 이를 기업화 하는 형태를 취하지는 않게 되었다.

 

이러한 폐쇠적이지만, 밀집이 필요한 시장의 특성을 잘 반영한 것이 동대문 종합시장과 주변의 도,소매 시장이다. 이들은 커다란 유통밀집구역을 형성하고 있고, 그 안에서 매우 내밀한 네트워크를 통해서 시장을 빠르게 움직이고 있었다. 하지만, 그 네트워크는 폐쇄적이고, 일반인들이게는 공유가 되지 않는 것이 특징이다. 이러한 특징으로 원단유통은 매우 복잡한 형태를 띄게 되고, 구매자도, 공급자도 그 안에서 나름의 유통망을 형성하는것을 그들만의 노하우라고 생각하게 되었다.

 

원단시장과 마찬가지로 부자재 시장 또한 그러한 시장의 흐름을 그대로 따라갔다. 그로 인해 형성된 또다른 시장이 평화시장, 동화상가이다. 부자재는 원단과 달리 대기업이 관여하지 않는다는 특징이 있다. 부자재의 특성상, 언제든지 대체가능하고 그 응용성이 높다 보니 대기업들이 그 시장을 따라가는것이 거의 불가능하기 때문이다. 이러한 시장은 처음부터 중소기업들이 시장을 형성하였고, 그로 인해서 더 밀접한 거래네트워크가 형성이 되었고, 시장에서 매우 밀접하게 대응할 수 있게 되었다.

 

하지만, 시장은 소량다품종으로 바뀌게 되고, 사람들의 온라인을 통한 거래가 활성화 되면서, 시장의 파이가 점점 세분화되기 시작하였다. 시장의 크기가 줄어들었다고 보기는 힘들지만, 세분화 되면서 본인들이 대응해야 할 것들이 많아짐을 시장에서는 느끼게 되었을 것이다. 이것은 업무, 재고관리의 효율성을 필연적으로 부르게 되어있다. 

 

또한, 동대문이 거대화되면서 - 기존에는 원하는 원단, 부자재를 찾는것이 그렇게 큰일이 되지 않았지만 - 지금은 2만개 이상의 매장을 뒤지고, 가격을 비교하고, 성실한 업체를 선별하고, 납품을 체크하고 하는 것이 매우 큰 일이 되어버렸다. 이 또한 커뮤니티의 속도, 신뢰의 속도, 가격의 확인등과 같은 추가적인 업무를 요구하게 되었고, 그러한 흐름에 시장도 빠르게 반응하기는 하였다. 하지만, 시장사람들이 간과하고 있는 것이 그들의 사업환경과 시장의 트랜드 변화의 속도감과 요구사항이 너무 다르다는 것이다. 

 

앙드레김 선생님의 타계는 기존의 디자이너의 시대가 저물고 새로운 형태의 디자이너들의 등장을 암시한다고 말하고 싶다. 즉, 전통적인 방식의 채널을 이용하여 권위와 인적네트워크를 통한 디자인 시장은, 스마트폰과 인터넷을 통해서 다양한 방식으로 재생산되고, 재가공되고 있었던 것이다. 이러한 트랜드는 더이상 대량생산, 고가의 옷이 아닌 개성적이고, 빠르게 소화될 수 있는 시장으로의 변화가 온것이였다. 홈쇼핑이 아닌 이제는 개인스트림, 유튜브, 무신사, 브랜디 같은 검색중심의 정보를 통한 맞춤형태로 디자인이 소비가 될 수 있게 되었다. 예전에는 백화점, 아울렛을 돌아다니면서 충동구매를 했다면, 이제는 스마트폰이 나에게 추천해주는(임의로 뿌려줄수도 있다.) 옷들을 보면서 좀 더 치밀한 충동구매를 유도해내고 있다.

 

그런 환경은 디자이너들의 생산환경의 변화를 끌어낼 수 있는 계기가 되었다. 디자이너들은 다양한 육성 프로그램을 통해서 육성되고, 동대문매장을 통한 오픈이 아닌 아마존, 알리와 같은 글로벌 매장으로의 오픈을 준비하고 있다. 이들은, 동대문의 정보를 취득하는데도 거부감이 없지만, 온라인을 통한 구매와 생산대행에도 역시 거부감이 없다. 오히려 양쪽에 대한 비교선택이 가능할 수 있다. 면대면 접촉대신 일정비용을 지불하더라도 온라인으로의 주문결제가 이들한테는 더 편리하다고 판단하고 있다. 시간비용을 통한 이익계산이 빠르기 때문이다.

 

소량생산을 통한 시장진입 -> 다품종을 생산을 통한 시장의 니즈파악 -> 시장반응을 보고 생산을 하는 온디멘드 생산 -> 풀필먼트를 통한 재고/배송의 문제 해결 -> 브랜딩을 통한 대량생산의 해외시장과 연계....

 

기존에는 에이전시라고 하는 사람들을 통해서 진행했어야만 했던 일들이, 이제는 다양한 온라인 플랫폼, 서비스를 내세우는 서비스들을 이용해서 어느정도 충족이 가능해졌다. 또한, TV, 홈쇼핑이 아닌 라이브방송, 유튜브, 합방, 페이스북, 인스타그램, 도소매플랫폼을 통해 마음만 먹으면 적은 비용과 시간으로 예전 오프라인보다 더 많은 매출을 만들어 낼 수 있다는 것을 알게 되었다.

 

이런 변화를 직감하는 기존 원부자재 도소매시장 상인들은 변화의 맞추기 위한 노력을 안하는 것은 아니다. 하지만, 오프라인을 지속하고 있는 이상, 온라인에 집중을 못할 수 밖에 없는 구조이다. 매장손님을 상대하는게, 당장의 수익이 되고, 미래의 수익을 예측하기에는 현실이 좁고 답답하기 때문이다.

 

그래서, 결국 이들은 정보의 간극을 이용하게 되고, 예전 용산에서 듣던 "얼마까지 알아봤어", "잘 몰라서 그런데, 이건 내가 가르켜줄께." 이런 멘트를 이용해서 고객들에게 단순명료한 정보공유를 하지 않게 되었다. 사실, 이분들도 어느것이 정확한 정보인지 알지 못한다. 내가 이걸 얼마에 팔아야 이문일까 보다는, 이 손님을 내가 어떻게 단골로 만들지에 몰입되서, 손님과 딜을 하게 되는 것이다. 

 

손님과의 딜을 통해서 신뢰를 주고, 다시 고객이 본인을 찾게 하는 것은 좋은 장사전술이지만, 이제는 그 고객은 온라인/오프라인을 비교하면서 내가 편하게 주문할 수 있는 곳을 선택하게 된다. 온라인의 이탈자들은 항상 생길 수 밖에 없고, 이러한 이탈은 오프라인을 더더욱 정보격차를 만들어 낼 수 밖에 없는 위기감을 조성하고 있다.

 

정해지지 않는 상품의 가격, 재고가 파악되지 않는 현실, 상품의 DB화를 하기에는 기존 레거시처리비용이 높은 구조, 불명확한 책임소재와 증빙의 빈곤은 기존 오프라인 시장을 지탱하는 안타깝지만, 슬픈 현실이기도 하다.

 

 

반응형

Free NAS : 남아도는 컴퓨터리소스 응용 - OS 선정

Computer Science/클라우드-대용량 아키텍처
반응형

회사를 운영하다 보면 회사의 남는 리소스, 그중에 가장 아까운것들이 컴퓨터와 HDD/SSD등이다.

누군가 퇴사를 하게 되면, 그 컴퓨터를 다른 신입에게 주기에는 이미 시기가 많이 지나서 할당해주기도 그렇고,

그렇다고 이게 못쓸만큼 오래되지도 않았고..

 

재고에서 없애버리기에도 아깝고, 그렇다고 안버리기에는 쓸사람도 없고..

 

컴터에 환장한 친구들이 있으면 그들을 위한 장난감으로 던져주면 좋아라 할텐데,

딱히 그런 오타쿠스러운 친구들도 별로 없을때는 정말 아깝다.

 

당근마켓에 던지기에도 안타까운 이것들을 어떻게 하면 효율적으로 활용할까 생각하던 과정에,

일부 컴퓨터들의 리소스를 모아서 NAS를 만들면 어떨까 생각이 들었다.

 

일반 NAS를 구매하기에는 매우 가격이 비싸지만, 케이스만 대충 그럴싸한걸 구매하던지, 

아니면 기존 케이스에서 HDD/SDD들만 잘 고정시킬 수 있으면 가능할 것 같았다.

 

이것 저것 자료를 조사해본 결과 다음과 같은 순서대로 만들어 보기로 하였다.

 

1. NAS OS 및 환경 설정

2. 회사의 리소스 수집

3. 설치하고, 회사내트워크에서 운영

4. 외부에서 접속할 수 있도록 설정 및 운영

5. 업무의 효율성 득실계산

 

우선은, OS는 여러가지를 선택할 수 있었다.

 

TrueNAS : FreeNAS에서 시작하여 가장 많이 쓰는것으로 파악되는 NAS OS

헤놀로지 : 시놀로지 정품에서 파생된 정식은 아닌것으로 확인되는 NAS OS

XigmaNAS : Open Source기반의 Storage NAS로 FreeBSD기반이 특징이다.

OpenMediaVault : Debian Linux에 기반한 NAS 이다. 다양한 네트워크 서비스를 제공하는것이 특징이다. 

OpenFiler : x86_64시스템을 완전한 NAS로 바꿔주는 기능을 제공한다고 한다. 리눅스 커널기반 서비스이다.

Rockstor : Linux 및 BTRFS기반 NAS OS. SMB(Small and Midsize Business)클라우드 서버를 구축할 수 있다.

PetaSAN : Open Source Scale-Out SAN 솔루션으로 대규모 스케일관리와 높은 성능을 제공한다. 노드관리를 통해서 확장성과 운영성을 제공하는것이 특징이다. 

ESOS (Enterprise Storage OS) : SCST프로젝트에 기반한 기업용 Storage OS로 분산리눅스를 기초하고 있다. 

CryptoNAS : CryptoNAS 프로젝트는 데이터 암호화를 대중화하기 위해 시작되었다. CryptoNAS live-CD는 복잡한 없이 데이터를 암호화하기 위해 만들어졌다고 보면 될것 같다. 단, 해당 프로젝트는 비트코인화되면서 맛이 좀 간듯 하다.(일본어로 비트코인관련 정보만 뜨네요)

 

일부 자료들을 찾아보면 USB에 OS를 설치하고 USB로 부팅하는것도 볼 수 있다. 

개인적으로 USB로 부팅하고, 나머지 스토리지를 모두 NAS에 할당하는것도 나쁘지는 않을 것 같다.

 

위 자료들을 통한 조사 결과는 TrueNAS로 설치, OpenMediaVault를 통한 설치를 가장 유력하게 생각한다.

그래도 자료를 가장 많이 찾을 수 있고, 리눅스 기반이라는 것이 운영관리에 최적화될것 같다.

 

다음에는 회사의 어떤 리소스들을 긁어모을 것인지를 사진과 함께 정리해보자.

 

반응형

카카오톡, 페이스북, 구글 간편로그인 오류문제중 인증서부분

Computer Science/Android&iOS
반응형

디버그 모드에서는 대부분 SSO 로그인의 구현과 테스트가 쉽다.

 

하지만, 릴리즈로 바꾸는 과정에서는 새로이 인증키도 만들어야 되고, 이것으로 인증도 해야 하고, SSO 사이트에 들어가서 등록 및 키해쉬, SHA-1을 등록도 해야 한다.

 

이렇게 개발PC에서 등록한 것으로 완벽하게 테스트 마치고 앱스토어에 올렸는데, SSO오류가 나거나 앱이 그냥 뻗어버리는 경우가 발생할 수 있다.

 

카카오톡, 구글에서의 오류메시지를 실시간으로 출력해본 결과 인증이 잘못되었다고 나오는 것이다.

 

분명히 나는 제대로된 인증서로 제대로 키해쉬, SHA-1을 입력했는데...

 

만일 내가 구글플레이스토어에서 앱무결성관련 설정을 건드린적이 있다면, 이부분을 의심해야 한다.

 

구글에서는 내가 만든 앱이라도 이 인증서를 이용해서 다시 인증을 하는 작업을 하게 되는것이다. 

그로인해서 인증에 따른 MD5, SHA-1, SHA-256의 값이 변경이 되어버린채 등록이 된다.

 

그래서 내가 PC에 생성한 인증서관련 값들이 먹히지 않게 된다.

 

내가 설정한 앱에서 대충 여기까지 따라오시고, 앱서명탭을 누르면 오호라.. 구글이 비밀스럽게 사용하는 인증서 정보가 있다.

우리는 여기서 값들을 이용하기면 하면 된다.

 

만일 키해쉬를 추출해야 한다면, 

 

echo <SHA-1 인증서 지문> | xxd -r -p | openssl base64

이렇게 해서 해쉬값을 변환할 수 있다.

반응형

iOS 화면전환 및 데이터 전송방식(동기 방식)

Computer Science/Android&iOS
반응형

동기방식에서 데이터를 주고 받는 방식은 생각보다 직관적입니다.

 

Android나 일반적인 프로그램에서는 데이터를 함수를 통해서 전달하는 경우가 많습니다. 이동하려는 개체를 생성하고, 이곳에 전달할 데이터개체를 생성해서 초기값으로 넣어주고, 이동하려는 개체를 호출하는 그런 방식이 조금 일반적입니다.

 

하지만, iOS는 이부분에서 조금 더 직관적인 부분이 있습니다.

 

이제 아래 예를 통해서 해당 방식을 고민해봅시다.

 

왼쪽 ViewController는 오른쪽 ViewController에 값을 전달할거고, 오른쪽에 ViewController는 값을 전달받아서 표시하고, 수정할것입니다. 수정된 내용은 다시 왼쪽의 ViewController로 보내는 그런 순환방식입니다.

왼쪽에서 오른쪽으로 데이터를 보내고, 역시 오른쪽에서 왼쪽으로 보내는걸 상상합시다.

일단, 왼쪽에 VC를 보면 "입력되지 않았습니다."라고 표시된 3개의 값들이 있는데, 처음에는 아무런 값도 없다고 가정해봅시다.

 

먼저 중요하게 봐야 할 부분이 어느시점에 화면에 데이터값을 표시할것인가 입니다. 우선 코드를 먼저 봅시다.

 

class RegisterController: UIViewController {
  @IBOutlet var resultEmail: UILabel!
  @IBOutlet var resultUpdate: UILabel!
  @IBOutlet var resultInterval: UILabel!
  
  var paramEmail: String? = ""
  var paramUpdate: Bool? = true
  var paramInterval: Double? = 0
  
  override func viewWillAppear(_ animated: Bool){
    if let email = paramEmail{
      resultEmail.text = email
    }
    
    if let update = paramUpdate{
      resultUpdate.text = update == true ? "AutoUpdate":"No Auto"
    }
    
    if let interval = paramInterval{
      resultInterval.text = "\(Int(interval))"
    }
  }
  
  @IBAction func close(_ sender: Any){
    self.presentingViewController?.dismiss(animated: true)
  }
  
  @IBAction func showRegister(_ sender: Any){
    let uvc = self.storyboard!.instantiateViewController(withIdentifier: "FormVC")
    
    guard let vc = uvc as? FormController else {
      return
    }
    
    vc.paramEmail = self.paramEmail!
    vc.paramUpdate = self.paramUpdate!
    vc.paramInterval = self.paramInterval!
    
    uvc.modalTransitionStyle = UIModalTransitionStyle.coverVertical
    uvc.modalPresentationStyle = .fullScreen
    self.presnet(uvc, animated: true)
  }

코드를 보면 화면전환을 present형태로 하는 것을 확인할 수 있습니다. 만일 우리가 화면전환을 NavigationController로 한다면 마지막 코드를 다음과 같이 전환하면 됩니다.

 

 //self.present(rvc, animate: true)
 self.navigationController?.pushViewController(rvc, animated: true)

 

중요한 것은 3가지 입니다.

 

- 변수의 정의

- viewWillAppear()에서 화면갱신시 이전 ViewController로부터 전달받은 값으로 화면 갱신

- showRegister() 함수에서 이동할 개체를 확인한 후 해당 개체안에 정의된 변수에 직접 값을 입력

 

내용이 그렇게 어렵지 않으므로 설명은 생략하고, 나머지 ViewController의 코드를 살펴보겠습니다.

 

class FormController : UIViewController{
  @IBOutlet weak var email: UITextField!
  @IBOutlet weak var update: UILabel!
  @IBOutlet weak var interval: UILabel!
  
  @IBOutlet weak var isUpdate: UIswitch!
  @IBOutlet weak var ControlInterval: UIStepper!
  
  var paramEmail: String = ""
  var paramUpdate: Bool = false
  var paramInterval: Double = 0
  
  override func viewDidLoad(){
    self.email.text = paramEmail
    self.update.text = paramUpdate == true ? "Auto Update":"No Auto"
    self.isUpdate.setOn(paramUpdate, animated: true)
    self.interval.text = "\(Int(paramInterfal))"
  }
  
  @IBAction func onSwitch(_ sender: UISwitch){
    if sender.isOn == true{
      self.update.text = "Auto Update"
    } else {
      self.update.text = "No Auto"
    }
  }
  
  @IBAction func onStepper(_ sender: UIStepper){
    let value = Int(sender.value)
    self.interval.text = "\(value)"
  }
  
  @IBAction func onSubmit(_ sender: Any){
    let preVC = self.presentingViewController
    
    guard let vc = preVC as? RegisterController else {
      return
    }
    
    vc.paramEmail = self.email.text
    vc.paramUpdate = self.isUpdate.isOn
    vc.paramInterval = self.ControlInterval.value
    
    self.presentingViewController?.dismiss(animated: true)
  }
}

여기서도 주의깊게 볼 부분은 다음과 같습니다.

 

- 변수의 정의

- viewDidLoad()에서 외부로부터 전달받은 값으로 화면을 구성

- onSubmit() 함수에서 되돌아갈 ViewController를 그에 맞는 class로 형변환후 변수를 저장

 

여기서도 present에 대응하는 코드로 작성되었지만, NavigationController를 이용했다면 다음 함수만 변경해주면 됩니다.

 //self.presentingViewController?.dismiss(animated: true)
 self.navigationController?.popViewController(animated: true)

 

마지막으로 Segue를 통한 화면전환시의 데이터전달만 마지막으로 정리해봅시다.

 

모든 코드에서는 이동할 또는 돌아갈 ViewController를 미리 인지하고 그에 맞게 class를 변환해서 데이터를 넣어주었습니다. 그런데, Segue는 그런 과정이 없습니다. Segue를 통한 이동시에는 해당 Segue를 identifier를 통해서 호출하기만 했습니다. 그러면 데이터를 넣어주는 시점이 언제일까? 

 

- prepare()를 통해서 segue를 통한 이동/반환시에 해당 목적지를 구분해서 데이터를 넣어줍니다.

 

@IBAction func onPerformSegue(_ sender: Any){
  self.performSegue(withIdentifier: "ManualSubmit", sender:self)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?){
  let dest = segue.destination
  guard let vc = dest as? ResultViewController else {
    return
  }
  
  rvc.paramEmail = self.email.text!
  rvc.paramUpdate = self.isUpdate.isOn
  rvc.paramInterval = self.interval.value
}

prepare함수를 오버라이드해서 그 시점에 이동할 ViewController를 확인하고 데이터를 넣어주면 됩니다. Action Segue일때도 해당 함수를 통해서 데이터를 넣어주면 됩니다.

 

 

반응형

iOS 화면전환 및 데이터 전송방식(비동기 방식)

Computer Science/Android&iOS
반응형

화면전환시 데이터를 주고받는 방식은 동기식, 비동기식으로 나눌 수 있습니다.

 

비동기식은 별도의 저장소를 두고 그곳에 데이터를 저장하고, 상호 데이터를 조회하는 방식입니다.

 

갑을 주고받는다기 보다는 글로벌한 곳에 데이터를 두고 상호참조하는 방식으로 이해하면 됩니다.

 

그러면 어디에 데이터를 저장하고 읽고, 쓰기를 진행하면 될까요.

 

1. AppDelegate를 이용한 접근

 

Swift의 모든 개체가 다 접근할 수 있는 AppDelegate class가 적합합니다.

 

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?
  
  var paramEmail: String?
  var paramUpdate: Bool?
  var param.....

여기에 변수를 정의합니다.

 

그러면 해당 데이터는 어떻게 접근할까요?

@IBAction func onSubmit(_ sender: Any){
  let ad = UIApplication.shared.delegate as? AppDelegate
  
  ad?.paramEmail = self.email.text
  ..

다음과 같이 UIAppliation에 접근해서 데이터를 바로 읽고, 쓰면 됩니다.

 

2. UserDefaults 객체를 이용한 방법

iOS에는 코코아 터치 프레임워크가 있습니다. iOS의 전통적인 프레임워크이고 swift에서도 사용이 가능합니다. 이 개체의 장점은 앱을 삭제하기 전까지는 반영구적으로 사용이 가능하다는 것입니다.

 

내부적으로 plist파일을 이용하여 값을 저장관리합니다. 기존에는 UserDefaults객체에 NSData, NSString, NSNumber와 같이 코코아 프레임워크에서 사용하는 데이타타입만 저장이 가능하지만, Swift에서는 기본 데이터타입도 저장관리가 가능해진 부분이 있습니다.

 

데이터에 읽고 쓰는 코드만으로 설명은 줄여도 될것 같습니다.

 

@IBAction func onSubmit(_ sender: Any){
  let ud = UserDefaults.standard
  
  ud.set(self.email.text, forKey: "email")
  ud.set(self.isUpdate.isOn, forKey: "isUpdate")
  ud.set(self.interval.value, forKey: "interval")
  
  self.presentingViewController?.dismiss(animated: true)
}

이 코드는 UserDefault에 데이터를 저장하게 됩니다.

 

overide func viewWillAppear(_ animated: Boole){
  let ud = UserDefaults.standard
  
  if let email = ud.string(forKey: "email") {
    resultEmail.text = email
  }
  
  let update = ud.bool(forKey: "isUpdate")
  resultUpdate.text = (update == true ? "Auto Update":"No Auto")
  
  let interval = ud.double(forKey: "interval")
  resultInterval.text = "\(Int(interval))"
}
반응형

iOS 화면전환 및 데이터 전송정리(Segue를 이용한 전환)

Computer Science/Android&iOS
반응형

4. Segue

 

Segue는 화면간의 연결을 표시하는 링크와 같다고 저는 이해했습니다. 그것의 이름이 Segue고요.

No Coding환경에서 Segue는 굳이 이름이 없어도 되는 경우가 많습니다. 하지만, 이건 기존 개발자들에게는 매우 불안한 요소입니다. 왜 불안하냐면.. 그냥 이름이 없으니까요.

 

코딩없이 우리가 Segue를 이용한것을 "Action Segue"라고 합니다. 버튼, 테이블 셀의 이벤트 트리거에 자동으로 연결이 되기 때문입니다.

Action Seguq라고 이름이 나옵니다. 오른쪽 마우스버튼으로 호출되는 메뉴입니다.

이건 굳이 우리가 프로그래밍 하지 않아도 되고, Storyboard를 통해서 직관적(?)으로 알 수 있습니다. 

사실 직관적이지는 않죠. 화면이 많으면 더더욱.. 하지만 코딩을 하지 않는것이 어디입니까.

 

이것말고 우리는 프로그램으로 제어하는 방법을 알려드리고자 합니다. 이걸 "Manual Segue"라고 합니다.

 

Action Segue는 버튼과 같은 컨트롤과 ViewController간의 관계입니다. 그렇기 때문에 해당 버튼의 동작과 연결시킬 수 있었습니다. 하지만, Manual Segue는 ViewController간의 관계를 정의해주고 이름을 명명해줘야 합니다. 역시 그림으로 설명합니다.

Manual Segue는 다음과 같이 생성합니다.

 

Action Segue는 다음과 같이 컨트롤과 Segue를 하일라이트 합니다.
Manual Segue는 ViewController를 전체로 표시합니다.

이제 우리는 Segue의 이름을 정해줘야 합니다.

Seguq의 이름은 Identifier에 넣으면 됩니다.

이제 버튼을 누르면 Segue를 통해서 화면전환하는 코드를 작성합니다. 이때 사용하는 함수와 예제 코드는 다음과 같습니다.

@IBAction func wind(_ send: Any){
  self.performSegue(withIdentifier:"ManualWind", sender:self)
}

여기서 함수 이름을 왜 wind라고 졌을까요. 지금까지 작명과는 다른데 말이죠.

 

화면전환하는 것을 iOS에서는 wind된다고 합니다. 그럼 그 반대는 unwind이겠죠.. 

 

여기서 재미있는것은 unwind되는 시점을 각각의 ViewController안에 작성해야 한다는 것입니다. 그래야 우리는 unwind되는 곳의 함수를 불러서 그쪽으로 이동하게 됩니다.

 

@IBAction func wind(_ send: Any){
  self.performSegue(withIdentifier:"ManualWind", sender:self)
}

@IBAction func unwindToVC(_ segue: UIStoryboardSegue){}

위 코드뭉치를 보면 wind를 통해서 해당 segue와 연결된 ViewController로 이동을 하게 됩니다. 그런데 복귀되는 함수도 같이 있습니다. 즉, 이 함수를 통해서 우리는 현재의 ViewController로 돌아오게 됩니다.

 

unwindToVC는 오른쪽 ViewController의 상단 "Exit"버튼과 연결됩니다.

ViewController에는 항상 위에 3개의 버튼이 있습니다. 그중에 가장 마지막에 "Exit"가 이런 unwind함수들과 연결이 됩니다.

 

unwind함수를 만드는것은 간단합니다. 함수 parameter에 (_ segue: UIStoryboardSegue) 만 정의하면됩니다. 그러면 swift가 전체 코드에서 다음과같은 parameter가 있는 함수들 리스트를 보여주고, 우리는 돌아갈 ViewController의 unwind함수만 선택하면 됩니다.

위에 그림을 보면 왼쪽에 Exit 바로 밑에 unwind가 있는것을 볼 수 있습니다.

 

버튼을 Exit와 연결시킵니다.
unwind함수들 즉 함수 parameter가 (_ segue: UIStorygoardSeguq) 인 함수리스트를 보여줍니다.

물론 전에 unwind함수를 표시하므로 내가 가야할 곳의 ViewController의 함수를 잘 선택해야 합니다.

 

휴.. 지금까지 속성으로 화면전환을 정리했습니다.

 

기존 개발자는 화면 컨트롤만으로 동작하는게 너무 힘들었습니다. 하지만, 익숙해지면 되는문제였습니다. 다만, 한번에 코드안에서 파악이 안된다는것은 아직도 생소합니다.

 

화면전환은 총 3가지 입니다.

- present(_, animated:) <-> presentingViewController.dismiss()

- navigationController.pushViewController() <-> navigationController.popViewController()

- performSegue(withIdentifier:,sender:) <-> unwind 함수

 

다음에는 화면전환시 데이터를 어떻게 주고 받는지를 정리합니다.

 

반응형

iOS 화면전환 및 데이터 전송정리(Navigation controller)

Computer Science/Android&iOS
반응형

3. 네비게이션 컨트롤러 (Navigation Controller)

 

네비게이션 컨트롤러는 다양한 페이지들이 서로 연관이 있다면 호출하고 다시 되돌아오는데 기본적인 편리성을 제공하는 View Controller입니다.

기존에 present는 화면전화 및 복귀를 내가 직접 코딩해야 했고, 복귀할때 적어도 1개의 버튼을 만들어야 했지만, Navigation Controller는 이러한 부분을 자동화 해준다고 보면됩니다.

 

기존 오래된 개발자 입장에서는 이 부분을 어떻게 이해해야 하나 고민했지만, 역시 오래보면 익숙해진다고, 그냥 익숙해지면 됩니다.

 

Navigation Controller를 만들기 위해서는 처음부터 Navigation Controller를 화면에 추가하거나, 기존의 ViewController에 Navigation Controller를 embed시키면 됩니다. 말로 풀어쓰면 어렵고, 화면을 보고 설명합시다.

 

Library입니다.

Library에서 Navigation Controller를 추가합니다. 이러면 다음과 같이

Library에서 Navigation Controller를 선택
화면에 2개의 View Controller가 표시가 됩니다.

표시가 됩니다. 기본적으로 Table View Controller가 추가가 됩니다. 여기서 Table View Controller안에 컨트롤을 삭제하고 마치 새것처럼 작업해도 됩니다. 

 

저는 이 방법보다는 기존에 사용하던 View Controller가 있다면, 거기에 Navigation Controller를 추가하는게 더 맘에 편합니다. 이 방법은

ViewController를 선택하고 메뉴에서 다음과 같은 기능을 선택합니다.

그림에 자세히 설명이 되어있습니다. View Controller를 선택하고, Editor/Embed In/Navigation Controller를 선택하면 됩니다.

 

Navigation Controller 와 연결된 View Controller들은 Navigation Item이 자동으로 생성되고, 뒤로가기가 자동으로 생성됩니다.

그렇습니다. 이렇게 자동으로 뒤로가기가 생성이 됩니다. 물론 Navigation Controller와 연결을 시켜야 하지만요.

 

연결시키는 방법은 오른쪽 마우스 버튼으로 연결시키면 됩니다.

연결여부는 여기를 통해서 확인됩니다. Show 형태로 되었습니다. 이건 뭘 의미할까요.

사실 이러한 연결은 No coding형태입니다. Present에서도 이야기 드렸듯이 코딩으로 또는 No coding으로 구현이 가능합니다.

 

위에 마우스가 아닌 버튼에 함수를 설정하면 다음과 같을 것입니다. 

 

@IBAction func moveByNavy(_ sender: Any){
  guard let uvc = self.storyboard?.instantiaterViewController(withIdentifier: "SecondVC") else{
    return
  }
  
  self.navigationController?.pushViewController(uvc, animated: true)
}

navigationController의 pushViewController(_, animated:)를 이용한것입니다. 그래서 Show(e.g. Push)로 표시가 되는 것입니다.

 

뒤로가기 위해서는 자동으로 뒤로가는 버튼이 생성이 됩니다. 물론 이것도 우리는 코딩으로 처리할 수 있습니다.

 

@IBAction func back(_ sender: Any){
  self.navigationController?.popViewController(animated: true)
}

여기서 조심해야 할것은 NavigationController를 이용하게 되면 우리 의지와는 상관없이 NavigationItem이 추가로 생성되고, 왼쪽에 뒤로가기 버튼이 자동으로 생성된다는 것입니다. UI충돌을 막기 위해서는 View Controller의 왼쪽상단에 Navigation Item이 생성되는것을 고려한 UI디자인이 필요합니다.

반응형