0%

Toy Project?

음…

사실 개발자라면 쉬는 날에 다른 일도 할 수 있겠지만,
본인의 역량 강화 또는 무언가 필요에 의해 본업 개발 외에 다른 개발 프로젝트를 시작하기도 합니다.

이런걸 Toy Project라고도 표현을 하는데,
이번에 나도 본격적으로 진행하려 기획을 하고 설계 및 개발을 진행하기로 하였습니다.
(사실 해보고 싶은게 넘 많은게 문제지만…)


주제

일단 Toy Project를 진행하게 된 계기는 매우 간단했습니다.

지금 제가 일하는 곳은 아주 작은 규모의 스타트업으로써, 아직 회사의 전반적인 프로세스나 시스템을 갖추는 중입니다.

그런데 회사 특성 상 소프트웨어와 하드웨어(제조관련)가 맞물려 있어서, 소프트웨어적인 업무 프로세스를 갖추지 못하였습니다.

그 중 하나가 사내정보시스템입니다.

사내 공지사항이나 근태, 급여내역 등을 아직 오프라인 또는 구두로 진행을 하여 많이 불편하습니다.

대기업에 있다가 아주 작은 시작 단계의 회사로 내려와보니 필요한 체제나 시스템이 많이 보였습니다.
(여담이지만, 삼성전자에서 소프트웨어적으론 배울게 단 1도 없었지만…이런 근무체제나 회사 프로세스는 많이 배운것 같네요 ^^;)

그래서 이번에 오픈소스 프로젝트로 사내정보시스템을 만들어보기로 하였습니다.


Company Board

이번 프로젝트 이름은 뭐로 작명을 할까? 라는 쓰잘머리 없는 고민을 하다가..

그냥 ‘회사 게시판? 음..’ 이라고 하여 Company Board로 만들었습니다.
진짜 작명때문에 고통받지요…작명이 뭐길래..

일단 Front-end 부분은 Bootstrap과 제가 제일 좋아하는 AdminLTE 를 사용하여 만들기로 했고,
Back-end는 Spring Boot와 JPA, JWT 및 기타 등등등 을 조합하여 개발하기로 하였습니다..

일단은 웹 전용으로 만들어보고, 향후 오픈 후 Rest api를 이용한 모바일 앱으로까지 지원하는 것을 목표로 하였습니다.

작심삼일, 용두사미가 되면 안되기에…

빠르게 목표를 정하고 GTD 기반으로 개발을 진행하여 프로젝트를 완성시켜봐야 겠습니다.

일단 초창기는 내부 버전관리를 이용하고, 어느정도 완성이 되면 Github에 오픈소스화 시켜볼 예정입니다..

마무리로 진행하는 화면을 올리고…오늘의 개발일지 끄읏~


오늘의 주제

근무하는 회사에서 Android 앱 개발과 앱에서 사용하는 데이터를 위해 서버에서 Rest api 부분을 개발하였습니다.

또한 알림 부분도 구현을 해야 해서 FCM을 사용하였습니다.

근데 Android에서 FCM을 사용하면 토큰을 생성하여 서버에 전달을 하게 되는데,
이 토큰이 갱신이 되거나 새로운 기기에서 설치 시 토큰의 유효성을 검사해야 했었습니다.

모두 공개하기는 힘들지만 서버에 클라이언트의 FCM토큰을 받아서 저장을 하는데,
만약 유효하지 않은 토큰까지 계속 저장할 경우 향후에 문제가 될 것 같았습니다.

그래서 FCM 토큰의 유효성을 체크하는 것을 알아봤고, 두 가지 주제에 대해 포스팅해보고자 합니다.

1. FCM 토큰 유효성 검사
2. Spring에서 Http Request

그리고 주제를 통해 달성할 최종 목표는 스케쥴러를 활용하여 일정시간이 되면 미사용 토큰 제거입니다.


FCM 토큰 유효성 검사

토큰 유효성은 이곳에서 참고했습니다.

이 부분은 자세하게 포스팅하여 해당 문서와 함께 업데이트 예정입니다.

여기서 토큰을 전달하여 유효성을 체크하는 부분은 방법이 생겼습니다.

하지만 Spring boot에서 어떤 식으로 Http 통신을 해야 할지가 다음 문제였습니다.


Spring에서 Http 요청

이 주제는 Spring Framework의 RestTemplate를 사용하여 해결하게 되었습니다.

Java에서 Http 통신을 하기 위한 방법은 다양했지만, Spring에서 제공하는 기능을 이용하는게 더 빠를것 같아서 RestTemplate를 사용하게 되었습니다.

참고로 요청 시 Header 정보에 Authorization 정보를 담아야 하는데 이 부분은 아래와 같이 입력해야 됩니다. (Key-value 형식)

“Authorization”, “key=[Your api key]”


최종 목표?

스케쥴러를 담당하는 서비스로직에서 쉽게 구현을 하였습니다.

그런데 API를 PostMan 등으로 요청해보면 유효할 경우 Http Ok(200)과 함께 Json 형식으로 정보가 응답됩니다.

하지만 유효하지 않은 토큰일 경우 404가 오고 잘못된 경우 400이 옵니다.

200은 괜찮지만 200이 아닌 400, 404 등의 응답은 try catch로 받아서 처리해야 했습니다.

아래의 코드를 참고해주시길…
(자세한 설명은 향후 포스팅 업데이트에서 다룰 예정입니다.)

1
2
3
4
try{ new RestTemplate().exchange(checkUrl+token.getToken(), HttpMethod.GET, new HttpEntity<>(headers), String.class); }
catch (RestClientException e) {
//FCM 토큰이 존재하지 않거나 문제가 있는 경우 -> 삭제
}

개발 연구 일지?

회사에서 개발업무를 진행하면서 내가 배우거나 또는 알고 있는 내용을 정리해야 할 필요성이 생겼습니다.

사실 처음에는 Mac용 어플리케이션인 Quiver를 이용하여 정리를 했었습니다.

그런데 개발 블로그를 시작하기로 결정하면서 내가 학습하거나, 배운, 그리고 시행착오 등을 정리하여 올려도 괜찮을 것 같다는 생각이 들었고, 이것을 정리하여 포스팅 하기로 하였습니다.

또한 개발자라면 자신의 연구노트 같은 기술 블로그를 만들어서 운영하는 것도 좋은 선택인 것 같습니다.

아마 다음과 같은 용도로 사용하게 될 것 같습니다.

  • 개발을 진행하다가 같은 (또는 비슷한) 케이스로 고민하시는 분들.
  • 미래의 내가(?) 과거의 이력을 확인하고 싶을 때.
  • 이직 시 포트폴리오 사이트의 경력사항을 뒷받침할 때.

이렇게 쓰고 나니 정리하여 포스팅할 것이 산더미처럼 쌓여있네요..

PS : 혹시 기록을 보고싶으신 분은 Tag의 DevNote를 참고해주세요~

Mac에서 Ubuntu 설치 USB 만들기

처음으로 Docker를 써보게 되어서 Docker 실습환경을 만들기 위해서 우분투 환경이 필요했습니다.

그래서 사용하지 않는 노트북에 USB로 우분투를 설치하기 위해 설치 USB를 만들어야 했습니다.

내가 사용하는 Mac OS에서는 어떻게 만들어야 하나 찾아보았고, 향후를 위해 이곳에 정리하게 되었습니다.


준비물

  1. Ubuntu 이미지(iso) (우분투 사이트)
  2. 설치할 USB (포멧 등을 통해서 비워둔 USB)

터미널 작업

터미널을 열고 다음의 명령어를 진행합니다.

hdiutil convert -format UDRW -o [생성할 dmg 경로 및 파일명] [변환할 파일명].iso

Ex :

hdiutil convert -format UDRW -o ~/Desktop/ubuntu ~/Downloads/ubuntu-16.04.3-desktop-amd64.iso

이렇게 하면 생성 경로 및 파일명에 맞게 dmg파일이 생성되어 있을 것입니다. (사진 참고)

그 후 준비된 USB를 연결하고 Finder에서 Unmount를 해줍니다.

diskutil list

를 통해서 확인하면 아래와 같이 연결된 정보를 확인할 수 있습니다.

usb가 마운트 해제된 상태에서 아래와 같은 명령어를 사용합니다.
만약 마운트를 해제 안하고 진행하면 Resource busy 맨트가 뜬다.

sudo dd if=./[생성한 이미지 경로 및 파일].dmg of=[USB 드라이브 마운트 경로]

Ex :

sudo dd if=~/Desktop/ubuntu.dmg of=/dev/disk2

터미널 창에는 아무것도 안뜨지만 진행되고 있으니 기다려봅니다

다 진행이 되면 디스크 알림이 뜨고 끝납니다.

Android Studio에서 Master Password

안드로이드 스튜디오에서 스토어 배포를 위해 서명을 할 때 앱 서명을 하려 하면 Master Password 암호 관련을 물어봅니다.

Master PasswordKeyStore와는 무관하며, Android Studio 사용자 인증을 위해서 사용하는 암호입니다.

근데 Master Password를 설정한 뒤 KeyStore를 사용한 경우 서명을 할 때마다 물어보게 됩니다.

문제는 이 Master Password를 잊은 경우 서명이 불가하며, 리셋을 할 경우 KeyStore암호를 입력해도 사용이 불가능해집니다.

사실 개인적으로 사용하는 컴퓨터라 이런 기능을 사용할 필요가 없어서 비활성화를 찾아봤지만 어떻게 하는지 몰라서 결국 구글행…


Master Password 비활성(Disable) 방법.

  1. **Preferences(설정)**을 들어갑니다.
  2. Appearance & Behavior -> System Settings -> Passwords 를 들어갑니다.
  3. 위 그림에서처럼 Password storage policy를 **Do not…**으로 맞추고 Master Password를 클릭하면 패스워드 설정이 나옵니다.
  4. 기존의 패스워드를 사용한다면 입력 후 새로운 암호를 공백으로 두면 Disable이 됩니다.

(미세팁) Master Password가 자꾸 틀리다고 나올 경우.

이건 간단한 팁이지만 Master Password가 자꾸 틀리다고 할때 한/영을 확인해봅시다.

이거 때문에 몇번 아주 고생을 했었…

문서를 시작하면서…

Java를 사용할 때 본인의 경우 가장 많이 사용하는 클래스는 아무래도 String이 아닐까 싶습니다.

String을 쓰다보면 문자열을 새로 문자열을 넣거나 또는 변경을 하는 경우 subString() 또는 split() 를 주로 사용합니다.

이것을 찾다보면 같이 마주치는 것은 StringBuffer 또는 StringBuilder가 있을 것입니다.

아마 면접질문 (신입 또는 주니어급 개발자)으로 저 세 가지의 차이점을 물어보는 경우가 많을 것입니다.

이번 포스팅을 통해서 한번 정리를 해보려 합니다.


Java의 String.

이번 포스팅에서는 Java의 String을 집중적으로 포커싱을 하는 글은 아니니 간략하게만 확인하고 넘어가도록 하겠습니다.

String은 일단 **불가변적(Immutable)**입니다.

이걸 쉽게 설명하자면 값을 변경하는 것이 불가능하다는 이야기입니다.

하지만 우리는 이런 사실을 잊고 아래와 같이 자연스럽게 사용합니다.

1
2
String testStr = "Hello World";
testStr = "Hello One";

위 선언 중 첫 번째 줄에서는 testStr에 “Hello World”라는 문자열의 값이 들어가게 됩니다.

하지만 두번 째 라인에서는 testStr에는 “Hello One” 문자열이 들어갑니다.

위와 같은 작업을 할 때는 기존의 testStr 객체의 메모리 공간에 “Hello World”의 내용을 변경하는 것이 아닌,
기존의 공간에서 새로운 공간을 할당한 후 문자열을 생성합니다.

결국 저장된 문자열을 변경하는 것이 아닌 새로운 객체를 만들어서 반환하는 것입니다.

이것을 가리켜 불가변적(Immutable) 이다 라고 표현합니다.

물론 이 불가변적(Immutable)인 객체는 사용이 간단하고, 멀티 쓰레드 환경에서 자유롭게 쓸 수 있는 장점이 있지만,
엄청난 양의 문자열을 변경하거나 치환을 하는 작업을 하게 될 경우 효율에 문제가 생길 수 있음을 예상할 수 있습니다.

이런 문제를 봉착하게 되면 우리는 검색할 때 다음의 키워드를 확인하게 됩니다.


StringBuffer, StringBuilder. 우리는 String의 친척

위에서 확인한 String 의 경우 문자열 변경을 하는 것이 아닌 새로 객체를 생성하여 반환함을 확인하였습니다.

만약 당신이 엄청난 문자열 연산을 하게 될 예정이라면 지금 소개하는 StringBuffer 또는 StringBuilder를 사용하면 됩니다.

1
2
StringBuffer testStr = new StringBuffer("Hello Wolrd";);
testStr.delete(5,10);

위의 경우는 StringBuffer로 생성한 testStr을 delete 메서드를 사용하여 문자열을 변경한 예제입니다.

testStr의 경우 결국 “Hello” 라는 문자열만 남게 될 것입니다.

즉 새롭게 생성을 하는 것이 아닌 기존의 객체에서 문자열 변경을 하는 것입니다.

StringBufferStringBuilder의 경우 문자열 연산을 진행하며 버퍼 공간이 부족한 경우, 기존의 버퍼 크기를 늘리며 동작합니다.

만약 작은 규모의 String의 문자열 변경의 경우 자꾸 변경할 경우 문자열 객체를 만들고 지우고를 반복하니
성능에 문제가 있지 않을까 싶지만…

이런 경우 그냥 String을 사용해도 무방합니다.

변경을 위한 연산을 진행하는 비용보다 새로 메모리 공간을 할당해서 사용하는 비용이 더 낮기 때문입니다.

위에서도 이야기 하였지만 엄청난 문자열 변경 연산을 할 경우에만 StringBuffer, StringBuilder를 사용하는 것이 좋습니다.


StringBuffer, StringBuilder 너희 둘의 차이점?

그런데 이 두 가지의 차이점은 무엇일까요?

StringBuffer의 경우 동기화(Synchronization)를 보장하고,
StringBuilder의 경우 동기화(Synchronization)를 보장하지 않습니다..

Multi Thread 환경에서는 StringBuffer 를 사용하고,
Single Thread 환경에서는 StringBuilder를 사용하면 됩니다.


새로운 부분

과거 JDK 1.5 버전에서는 String에서 문자열 연산(+, concat 등)을 할 때 성능상의 이슈가 있었지만,
JDK1.5 버전 이후부터는 컴파일 단계에서 String 객체의 문자열 연산을 사용할 경우 StringBuilder로 컴파일 되도록 변경되었습니다.


결론

String은 짧은 문자열을 더하거나, 간단한 문자열 처리를 할 때 사용하고,
StringBuffer는 쓰레드에 안전한 프로그램이 필요할 때나, 개발 중인 시스템의 부분이 쓰레드에 안전한지 모를 경우 사용합니다.
StringBuilder는 쓰레드에 안전성 여부에 관계가 없는 소프트웨어를 개발할 때 사용합니다.

Java Bean 이란?

처음 자바 개발을 하다가 Java Bean이란 용어를 듣게 되었습니다.
구글에서 다양한 블로그에서 검색을 하여 찾아보았고, 이것을 정리하여 블로그 포스팅을 하게 되었습니다.


Java Bean의 정의

  • 데이터를 표현하는 것을 목적으로 하는 자바 클래스.
  • 컴포넌트와 비슷한 의미로도 사용된다.
  • JavaBean 규격서에 따라 작성된 자바 클래스를 가리킨다.

Java Bean의 규격

  • 클래스는 패키지화 하여야 한다.
  • 멤버변수는 프로퍼티(Property)라 칭한다.
  • 클래스는 필요에 따라 직렬화가 가능하다.
  • 프로퍼티의 접근자는 private이다.
  • 프로퍼티마다 getter/setter 가 존재해야 하며, 그 이름은 각각 get/set으로 시작해야 한다.
  • 위의 프로퍼티 getter/setter 메서드의 접근자는 public이어야 한다.
  • 외부에서 프로퍼티에 접근은 메서드를 통해서 접근한다.
  • 프로퍼티는 반드시 읽기/쓰기가 가능해야 하지만, 읽기 전용인 경우 getter만 정의할 수 있다.
  • getter의 경우 파라미터가 존재하지 않아야 하고, setter의 경우 한 개 이상의 파라미터가 존재한다.
  • 프로퍼티의 형이 boolean일 경우 get 메서드 대신 is메서드를 사용해도 된다.

Java Bean의 형태 예제

형태는 아래의 소스코드를 참고해주시길…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 패키지_명;

[import 패키지_명;]

public class Bean_ClassName [ implements java.io.Serializable ] {
private String name; // 값을 저장하는 속성 정의(필드)
public Bean_ClassName() { } // 기본 생성자

public String getName() { // 필드 값을 읽어오는 메소드
return name;
}
public void setName(String name) { // 필드 값을 저장하는 메소드
this.name = name;
}
}