[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 등

[iOS] 간단한 키체인과 해싱으로 보안 강화 (Basic iOS Security: Keychain and Hashing)

이미지
[iOS] 간단한 키체인과 해싱으로 보안 강화 (Basic iOS Security: Keychain and Hashing) 민감한 데이터를 저장하고, 저장된 데이터를 안전하게 꺼내어 사용자 인증 하는 과정을 Keychain을 이용하여 구현하는 방법을 소개합니다. 해당 포스트의 원문은 다음과 같습니다 : https://www.raywenderlich.com/129-basic-ios-security-keychain-and-hashing 소스코드 다운로드 AuthViewController.signInButtonPressed() 로그인 버튼이 눌렸을 떄 호출 AuthViewController.signIn() 함수 호출 AuthViewController.signIn() 사용자의 입력 종료 이메일, 비밀번호 입력 받은 데이터 검증 디바이스의 이름 가져오기 이름, 이메일, 비밀번호로 User 데이터 만들기 AuthController.signIn() 로그인 함수 호출 AuthController.signIn() class func passwordHash(from email: String, password: String) -> String { let salt = "x4vV8bGgqqmQwgCoyXFQj+(o.nUNQhVP7ND" return "\(password).\(email).\(salt)".sha256() } 입력받은 이메일과 비밀번호를 넘겨줘 AuthController.passwordHash()로 해싱 키체인(Keychain)에서 앱의 데이터를 식별하는데 사용되는 서비스 이름을 상단에 정의 KeychainPasswordItem.savePassword()로 암호 키체인에 저장 UserDefaults에 현재 유저정보 저장 KeychainPasswordItem(service: serviceName, account: user.email).s

[swift] 구조체(struct)와 클래스(class)의 비교

이미지
[swift] 구조체(struct)와 클래스(class) 구조체와 클래스는 코드블럭을 만들 때 쓰이고 그 문법 또한 매우 닮았다. 하지만 다른점이 있기 때문에 그 특성을 잘 파악하고, 필요한 부분에서 활용할 수 있도록 정리한다. 정의 방법 (Definition) 구조체는 struct , 클래스는 class 라는 키워드를 사용하여 정의한다. struct Student{ // properties and methods } class Student { // properties and methods } 프로퍼티와 메소드 (Properties and Methods) 이 예제에서는 학생의 구조체와 클래스의 정의 예제이다. SomeStudent struct 와 AnotherStudent class 모두 firstName, lastName, grade라는 properties를 가지고 grade를 출력해주는 printGrade() 메소드를 가진다. 다른 점은 클래스에서는 init() 함수를 따로 정의 해줘야 한다. struct SomeStudent{ // properties let firstName: String let lastName: String var grade: Int // methods func printGrade(){ print("grade is \(grade)") } } class AnotherStudent { // properties let firstName: String let lastName: String var grade: Int // methods init(firstName: String, lastName: String, grade: Int){ self.firstName = firstName self.lastName = lastName self.grade = grade } func printGrade

[swift] 함수(fuction)의 기본 개념정리

이미지
[swift] 함수(fuction) 정리 같은 코드를 복사 붙여넣기 하면서 쓰지 않기 위해 함수를 사용한다. 함수의 기능에 대해 정리하면서 남긴 기록. 정의하는 방법 사용법은 간단하다 func 키워드 뒤에 함수 이름과 ()를 붙여주면된다. func printHello(){ print("hello") } 사용하는 방법 간단하다 함수이름과 빈()를 붙여주면 된다. printHello() // hello 출력 인자 넘겨주기 ()사이에 이름과 타입을 명시해주면 된다. let speedLimit = 100 let mySpeed = 80 func printSpeedViolationStatus(speed: Int){ print(speed > speedLimit ? 'Speed violation!' : 'Keep driving.') } printSpeedViolationStatus(speed: mySpeed) // Keep driving. 여러개의 인자를 넘겨주는 방법은 , 로 추가해서 넘겨준다 let speedLimit = 80 let mySpeed = 100 func printSpeedViolationStatus(speed: Int, speedLimit: Int){ print(speed > speedLimit ? 'Speed violation!' : 'Keep driving.') } printSpeedViolationStatus(speed: mySpeed, speedLimit: speedLimit) // Speed violation! 인자 기본 값(Default Parameter Values) 기본값을 넣을 수 있다. speedLimit: Int = lowLimit 와 같이 작성한다. let mySpeed = 100 let lowLimit = 80 func printSpeedViolationStatus