4월, 2020의 게시물 표시

[dailycoding] 위장

이미지
[dailycoding] 위장 문제 clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다. 스파이가 가진 의상의 수는 1개 이상 30개 이하입니다. 같은 이름을 가진 의상은 존재하지 않습니다. clothes의 모든 원소는 문자열로 이루어져 있습니다. 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 ‘_’ 로만 이루어져 있습니다. 스파이는 하루에 최소 한 개의 의상은 입습니다. 입출력 예 clothes return [[yellow_hat, headgear], [blue_sunglasses, eyewear], [green_turban, headgear]] 5 [[crow_mask, face], [blue_sunglasses, face], [smoky_makeup, face]] 3 해결의 과정 문제는 단순히 수학문제에서 마주할 수 있는 조합의 문제이다. 옷의 종류가 a,b,c가 있다면 a b c가지가 있다. 하지만 옷을 입지 않은 가짓수도 있기 때문에 (a+1)(b+1)(c+1) 가지의 조합이 나온다. 마지막으로 하나도 입지 않은 가짓수는 제외해야하기 때문에 (a+1)(b+1)(c+1) - 1 을 계산한다. 입력 받은 옷 중에 같은 이름은 없기 때문에 결국 옷 종류별로 몇개씩 있는지만 고려하면된다. 옷 종류별로 몇벌씩 가지고있는지 계산한다. 종류별 옷을 전부 +1 한뒤 곱한다. 마지막에 -1을 해준다. import Foundation func solution(_ clothes:[[String]]) -> Int { var clothType : [String : Int] = [:] var answer = 1 clothes.forEach {item in // 옷 종류별 갯수를 계산한다. if clothType.keys.contains(item[1]){

[dev] Opensource에 처음 기여해보고 싶어서 찾은 내용

이미지
Opensource에 기여하기 오픈소스에 기여해보는 첫 발을 내디딘기념 오픈소스를 시작하게 된 동기 개발자로 성장하면서 계속 가지고있던 갈증 중 하나는 협업 이라는 키워드였다. 결국 좋은 개발자란, 다양한 사람들과 다양한 일을 할 수 있는 개발자 일테니 말이다. 회사에서 하는 일도 성장에 도움이 되지만 자신이 생긱하기에 재미있어 보이는 프로젝트에 좋아하는 만큼 기여해보고 싶다라는 막연함으로 오픈소스를 찾게되었다. 하지만 이번이 첫 도전은 아니다. Github을 처음 알았을 때도, 오픈소스에 관련된 세미나를 들었을 때도 항상 꼭 컨트리뷰터가 되어야지 마음만 먹고 프로젝트만 뒤적뒤적거리다가 접은적이 한 두번이 아니었다. 그래서 이번에는 어떤 프로젝트에 기여하면 좋을지에 대한 검색 방법에 대해 찾아보았다. 이전에 받았던 조언들은, 너가 평소에 쓰는 서비스에서 불편한 점을 개선해 보아라, 오탈자 수정, 문서화작업을 해 보아라 라고 받았지만 와 닿지가 않았다. 그래서 이번에 선택한 방법이 내가 사용하고 있는 언어로 기여할 수 있는 프로젝트 찾기 와 Open source alternative 라는 키워드였다. 결국 처음에 받은 조언과 같은 맥락이다. 하지만 느끼는 시각을 다르게 해 주었다. 내가 돈내고 쓰고있는 어플리케이션에 대해 알아보는 시간과 어떻게 구현되었을까에 대한 호기심이 소스코드를 들여다보게 만드는 원동력이 되어주었다. 검색경로 hacktoberfest 오픈소스를 프로젝트 찾기를 검색하다보면 가장 먼제 눈에 띄는 페이지 중 하나가 핵토버페스트 이다. Details 페이지에 접속해보면, 친절하게 PR을 날리는 방법 어디서 어떻게 날리면 좋은지도 알려준다. ● Up For Grabs ● Issuehub.io ● First Timers Only ● Your First PR ● Awesome for Beginners ● This is another great guide Github Issue

[swift] table view를 처음 써보고 남기는 글

이미지
[swift] table view basic TableView Main.storyboard에서 Library(⌘ + ⇧ + L)를 열어서 Table view controller를 추가한다. 처음에 만들면, 진입 포인트가 없기 때문에 Attribute inspector에서 is initial view controller 를 체크해 최초 진입 포인트로 지정해준다. table view cell은 만들어 놓고 재 사용할 수 있다. cell은 identifier를 이용해 식별 할 수 있다. identifier에 이름을 줘보자. 이제 테이블을 구현해보자. 먼저 테이블의 줄 수를 정한다. // 1000 줄짜리 테이블을 그려준다. override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1000 } 빈칸이 무수한 테이블이 생겼다. 이제 내용을 채워주자 // 테이블의 셀에 내용을 채워주지 않아 아무것도 그려지지 않는다. // Attribute inspector의 Accessory에서 checkmark를 선택해준다. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath) return cell } indexPath는 행을 식별하기 위한 식별자이다. [section,row]의 형태로 이루어져있다. section은 table을 나누는 기준 중 하나이다. row는 의미 그대로 테이블의 행이다. // 특정 조건을 줘서 출력해보자. override fun

[git] git을 사용하는데 필요한 기본 개념과 기본 용어 정리

이미지
[dev] git 다루기 깃 개념 정리 깃을 알고 있다고 생각하고 쓰면서, 평소와 다른 문제가 일어나면서 깃에 대한 개념이 부족하다고 생각되어 찾아 본 내용들을 정리했다. 자세한 내용은 블로그 보다는 Git book 정독하는 것을 추천한다. 기본 사용 플로우 리모트에 있는 소스코드를 받거나(clone), 새로운 프로젝트를 시작한다. 변경사항을 저장(commit)하고, 리모트에 반영(push)한다. 이미 존재하는 소스코에서 독립적으로 작업을 진행해야 하는 경우에는 새로운 브랜치(branch)를 생성해 작업을 한다. 작업이 완료 된 후에, 갈라져 나온 origin branch에 merge되거나 rebase를 한다. Merge and Rebase mrege는 기존 존재하던 브랜치에 병합(merge)하는 기능이다. 기존 브랜치에 작업 내용이 없다면, fast-forward merge를 이용해 병합을 하거나 기존의 브랜치에도 작업 내용이 있다면, 3-way-merge 방식으로 각각의 브랜치의 작업 내용을 남겨놓고 하나의 브랜치로 병합한다. master 에서 slave를 merge해주면, master브랜치로 slave가 병합된다. rebase는 커밋 내역을 재정렬 해서 하나의 브랜치로 합쳐준다. 결과적으로는 한 갈래의 브랜치를 만들어준다. rebase해준 최신의 커밋으로 정렬되고 checkout 되어있던 브런치의 커밋이 먼저 정렬된다. slave 에서 master를 rebase해주면, master브랜치로 slave가 병합된다. Stash 아직 마무리 하지 않은 작업이 있지만, 다른 작업을 해야해서 변경사항을 저장해야 할 때는 어떻게 해야할까? 커밋해서 저장하기에는 내키지 않는다. 이럴 때 쓰는 명령어가 Stash 이다. 아직 마무리하지 않은 작업을 스택에 잠시 저장할 수 있도록 하는 명령어이다. 다음과 같은 파일을 Stash할 수 있다. Modified이면서 Tracked 상태인 파일 Stagi

[IOS] Image Notification Push 구현하기

이미지
[IOS] Image Notification Push 구현하기 APNs를 이용해서 푸쉬 를 보낼 수 있다는 가정하게 작성된 글 입니다. Image Push Notification 만들기 (Using Notification Service Extension and Notification Content Extension). 기본적인 알림 기능 이 동작하고 있다고 가정하고 설명합니다. service extension과 content extension을 추가해줍니다. Service extension은 Service라는 이름으로, Content extension은 Content라는 이름으로 추가 해 줍니다. xcode > Editor > Add Target > Notification Service Extension > productname : "Service" > Next > Finish xcode > Editor > Add Target > Notification Content Extension > productname : "Content" > Next > Finish 추가 후 결과 화면은 다음과 같습니다. Service > NotificationService.swift는 다음과 같습니다. import UserNotifications class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler conten

[dev] 이펙티브 엔지니어

이미지
[dev] 이펙티브 엔지니어 원문 : https://gist.github.com/rondy/af1dee1d28c02e9a225ae55da2674a6f 읽기전에 : 저는 여기에 제시된 내용(에드몬드 라우의 책의 개요)을 제작하지 않았습니다. 인터넷 어딘가에서 복사하여 붙여 넣었지만 원본 소스가 정확히 무엇인지 기억나지 않습니다. 또한 저자의 이름을 찾을 수 없었기 때문에 적절한 크레딧을 줄 수 없습니다. 이펙티브 엔지니어 에드먼드 라우 매우 추천 👍 http://www.theeffectiveengineer.com/ 이펙티브 엔지니어란? 이펙티브 엔지니어란 일을 제대로 끝내는 사람들입니다. 그들은 결과를 산출합니다. 올바른 사고 방식 채택 큰 영향을 미치는 일에 집중하라 레버리지 = 생성된 임팩트 / 투자한 시간 레버리지을 효율성의 척도로 사용하세요. 임팩트의 80%는 작업의 20%에서 발생합니다. 쉬운 승리 만이 아니라 높은 레버리지에 집중하십시오. 학습을위한 최적화 필요한 경우 작업을 변경하십시오. 학습 최적화는 높은 레버리지를 가져옵니다. 성장을 위한 사고 방식을 채택하십시오. 사람들과 대화하세요. 스토리 텔링에 능숙해지세요. 시간을 들일수록 나아집니다. 성장을 위한 사고 방식을 가진 사람들은 노력을 통해 지식과 기술을 습득하고 발전시킬 수 있다고 생각합니다. 당신의 이야기를 만드세요. 학습 속도에 투자 다양한 분야를 학습하세요. 다양한 분야에 대한 학습은 기하 급수적인 성장으로 이어집니다. 학습은 빨리 시작 될수록 좋습니다. 쉬운 작업을 수행하는 것은 엄청난 기회 비용입니다. 복합 학습의 기회를 놓칠 수 있습니다. 수익성보다는 학습을 우선시하십시오. 학습속도가 가장 높은 활동에 시간을 투자하십시오. 학습에 도움이되는 작업 환경을 찾으십시오. 빠른 성장을 할 수 있는 회사 (# 문제 수 >> # 자원). 해결했을 떄 영향력이 큰 문제를 선택할 수

[IOS] Notification Push 구현하기

이미지
[IOS] Notification Push 구현하기 순서 푸쉬계졍 생성 (apple-membership) 어플리케이션 제작 Push Notifications(푸쉬를 날려줄 도구) 1. 푸쉬계졍 생성 참고 블로그 : https://faith-developer.tistory.com/153 푸쉬를 위해서는 계정이 필요하다. a. 인증서 생성 b. App ID 생성 (Identifiers) c. Push 인증서 등 록 (Certificates) a. 인증서 생성 키체인 접근 > 인증서 지원 > 인증 기관에 인증서 요청 > 이메일주소입력 > 디스크에 저장 > CertificateSigningRequest.certSigningRequest 파일 저장 b. App ID 생성 identifiers > +버튼 > appId > bundleId 입력 > Push Notifications 선택 > Continue > Register c. Push 인증서 등록 identifiers > bundleId 선택 > Configure > Development SSL Certificate > Create Certificate > 위에서 생성한 CertificateSigningRequest.certSigningRequest 파일 업로드 > Countinue > Download > aps_development.cer 다운로드 다운받은 aps_development.cer를 실행하면 키체인에 등록된다. 등록된 키 체인에서 push_cert.p12 파일로 내보내준다. 이 파일은 후에 메시지를 전송하는데 쓰인다. 2. 어플리케이션 제작 참고 블로그 : https://www.raywenderlich.com/8164-push-notifications-tutorial-gettin

[dev] 구글링 할 때의 팁

이미지
[dev] 구글링 할 때의 팁 코딩을 하다가 에러메시지를 마주 했을 때 나에게 맞는 해결방법을 검색하는 방법의 팁에 대해 정리한다. * 사용하기 검색은 에러를 마주하면서 시작된다. 하지만 에러메시지를 그대로 복사 붙여넣기 해서는 나에게 필요한 질문과 답을 찾을 수 없다. 예를들면 could not cast value of type 'Test.Home ViewController' to 'Test.List ListController' 라는 에러메시지를 보고 해결하려고 전체를 복사 붙여넣기를 하면 이상한 결과가 나올 수 있다. 나의 코드에만 존재하는 키워드들이 들어있기 때문이다. Test.Home 나 ListController 와 같은 것들이다. 그럴 때는 * 를 활용해서 wildcard를 넣을 수 있다. 다음과 같은 검색어가 된다. could not cast value of type * to * . 이렇게 하면 나의 코드에만 있는 부분을 포함해서 검색할 수 있다. 특정 도메인의 활용 코드에서 발생한 대부분의 에러에 대한 질문과 답변을 stack overflow와 같은 곳에서 검색하고 싶다면, site : [domain] 과 같은 키워드를 사용해보자. site : stackoverflow.com could not cast value of type * to * 이전 검색어가 다양한 곳에서의 질의 응답 결과를 보여줬다면, 이번 검색 결과는 stackoverflow의 검색 결과만 보여준다. “swift” 같은 추가적인 키워드 활용 stackoverflow에 있는 질의 응답 중에서도 “swift” 질문들만 보고 싶을 수 있다. 이럴 키워드를 하나 추가해주자. site : stackoverflow.com swift could not cast value of type * to * 나에게 필요한 키워드 들을 추가함으로써 검색의 정확도를 올릴 수 있다. stackoverflow와 같은

[git] Github 이슈 라벨(issue labels)

이미지
[dev] Github issue labels Github에서 프로젝트의 문제점을 알리거나 기여를 할 때 이 issue label을 달거나 읽어야 할 일이 생긴다. 해당 이슈에 알맞은 라벨을 선택하고, 의미를 파악하기 위해 알아두자. keyword 의미 bug 예기치 않은 문제 또는 의도하지 않은 동작(버그)을 나타냅니다. documentation 문서를 개선하거나 추가 할 필요가 있음을 나타냅니다. duplicate 해당이슈 또는 PR이 기존에 있음을 나타냅니다. enhancement 새로운 기능 요청을 나타냅니다. good first issue 처음 기여해볼 사람에게 좋은 문제를 나타냅니다. help wanted 관리자가 문제 또는 PR 요청에 대한 도움을 원함을 나타냅니다. invalid 이슈 또는 PR 요청이 더 이상 관련이 없음을 나타냅니다. question 이슈 또는 풀 요청에 추가 정보가 필요함을 나타냅니다. wontfix 문제 나 PR 요청에서 작업이 계속되지 않음을 나타냅니다. 참고 : https://help.github.com/en/github/managing-your-work-on-github/about-labels

[swift] 메모리 관리 - Retain Cycle : strong, weak, unowned

이미지
[swift] Retain Cycle : strong, weak, unowned strong, weak, unowned 사용 방법 클래스의 객체를 가리키는 참조의 기본값은 강한 참조이다. 그리고 적어도 하나의 강한 참조가 있다면 객체의 메모리는 ARC(Automatic reference counting)에 의해서 해제되지 않는다. 아래 예제를 통해 살펴보자 // Case1 : 일반 참조와 해제 class TestClass { init(){ print("init") } deinit{ print("deinit") } } var testClass: TestClass? = TestClass() print("Instance is created!") testClass = nil // print init Instance is created! deinit TestClass 객체가 생성되면서 init 을 출력한다. 그 다음에 "Instance is created!" 를 출력한다. testClass 변수에 nil을 할당하면서 참조의 갯수가 0이 되고 deinit 을 출력한 뒤 메모리에서 해제된다. 다음 예제를 통해 ARC가 동작하지 않아 메모리에서 해제되지 않는 상황을 살펴보자. // Case 2 : 강한 상호참조 class TestClass{ var testClass: TestClass? = nil init(){ print("init") } deinit{ print("deinit") } } var testClass1: TestClass? = TestClass() var testClass2: TestClass? = TestClass() testClass1?.testClass = testClass2

Google Blogger 검색 노출 방법

이미지
Google Blogger 검색 노출 방법 블로그를 한참동안아니 했는데, 방문자수가 너무 적어서 시들해지고 있을 무렵 글을 작성하는 것 만으로 사람들에게 노출되는 것이 아니라는 것을 알았다. 구글 서치 콘솔 에서 내 블로그의 URL을 크롤링 해 갈 수 있게 설정 해주어야 한다. 왼쪽 상단 아래 화실표를 클릭해서 속성 추가를 눌러준다. 일단 블로그의 주소를 등록해 주어야 한다. 속성이 추가 되었으면, Sitemaps를 등록해 홈페이지의 구조를 알려주어야 한다. 새 사이트 뱁 추가 입력란에 sitemap.xml feeds/posts/default?alt=rss 이 두개를 입력해 제출한다. 정상적으로 성공했다면. 상태에 성공이 표시된다.

[dev] 터미널 사용 입문

이미지
[dev] 터미널 사용 입문 개발자를 위한 터미널 입문 개발을 하다보면 원치않아도 터미널을 사용해야하는 경우를 마주하게 된다. Git이나 PackageManager를 다룰 때에도 터미널이 필요하다. 터미널을 쓰는 것에 두려움을 느끼지 말고 익혀두자. 터미널을 잘 다루는 것은 개발효율성을 높이는 방법중에 하나이다. 터미널에서 할 수 있는 것 터미널은 텍스트 기반이며 명령어를 입력할 수 있는 CLI(command-line interface)역할을 한다. 깃(GUI)버젼을 사용해본 사용자라면 왜 터미널을 사용해야 하는가에 의문을 가질 수 있다. GUI는 명령어를 버튼과 같은 시각적인 도구로 입력하는 방법이다. 그렇기 때문 모든 명령어를 구현하지 않는다. 터미널을 사용해 명령어를 입력할 수 있다면, 원하는 결과를 이끌어 내기 위한 입력을 할 수 있다. 터미널 실행하기 Mac OS는 Spotlight ( ⌘ + Space )를 불러 “Terminal”을 찾아 실행할 수 있다. Linux는 “terminal” 을 찾아 실행하면 된다. 단축기 Ctrl + Alt + T 를 이용해 실행할 수 있다. Windows 10은, PowerShell 이라는 터미널을 실행한다. 기본 명령어 터미널의 기본 명령어는 다음과 같다. ls # 파일 list 나열 cat # 파일의 내용을 보여주기 cd # 디렉토리 변경 mv # 파일, 디렉토리 이동과 이름변경 cp # 파일, 디렉토리 복사 mkdir # 디렉토리 생성 rm # 파일, 디렉토리 제거 pwd # 현재 디렉토리 경로 위 명령어들의 사용 방법은 다양하다. 사용방법 중 인자들을 입력해야 하기도 하다. cp 명령어를 입력해보자. LT1066ui-MacBook-Pro:test hyunho.lee$ cp usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvXc]

오픈소스 라이선스 정리

이미지
오픈소스 라이선스 정리 오픈소스 라이선스 정리 소프트웨어를 개발하다 보면, 오픈소스는 자연스럽게 접하게 된다. 처음에는 마냥 무료인 줄 알고 가져다 쓰던 오픈소스애도 여러종류가 있고 지켜야 하는 부분에 대해 법적인 책임을 지지 않기 위해 남겨둔다. 오픈소스 라이선스 고려사항 오픈소스 라이선스 비교 표를 보면서 어떠한 해당사항과 주의해야 하는 사항이 있는지 참고한다. 참고 : 오픈소스 라이선스 비교 표 복제, 배포, 수정의 권한허용 해당 소스코드를 복제하고 배포하고 수정할 수 있다. 배포시 라이선스 사본첨부 라이선스의 소스코드를 배포한다면 라이선스 사본을 배포하여 해야 한다. 저작권 고지사항 또는 Attribution 고지사항 유지 코드의 상단에 삽입되어 있는 원작자의 저작권 고지사항을 지우면 안된다. 다만, 네트워크를 이용한 서비스의 경우 배포로 보지 않기 때문에 의무사항 자체가 발생하지 않는다. 배포시 소스코드 제공의무와 범위 해당라이선스의 소스를 사용하여 개발할 경우, 개발 된 소스코드를 사용자에게 제공해야 하는지에 대한 의무와 범위이다. Work Based on the Code 제공의무: 원 저작물의 소스코드를 원본 그대로, 혹은 수정하여 새로운 SW에 포함하였을 경우 제공범위: 원 저작물의 소스코드가 포함되어, 파생 저작물로 인정되는 범위내의 모든 소스코드 GNU GPL, GNU AGPL 등 Derivative Work 제공의무: 원 저작물의 소스코드를 수정하여 사용한 경우 제공의무가 존재하며, 수정 없이 그대로 사용하였을 경우에는 소스코드를 제공하지 않아도 됨 제공범위: 원 저작물을 사용함에 있어 수정을 거쳤다면, 원 저작물의 소스코드에서부터 존재하던 파일을 모두 공개해야 하며, 파생 저작물의 저작자가 추가적으로 생성한 부분에 대해서는 공개하지 않아도 됨 GNU LGPL, NASA Open Source Agreement, Simple Public License 등