2018년 12월 25일 화요일

Elastic Stack 6.5 업데이트.

사용할 계획은 없지만 관심은 항상 있는 Elastic Stack의 6.5 업데이트 소식.
마이너 버전 업이지만 마이너한 것은 없는 릴리즈라는 개발사의 얘기처럼 방대한 양의 기능 업데이트가 있었다.

https://www.elastic.co/kr/blog/elastic-stack-6-5-0-released


Cross-Cluster Replication (Beta | Platinum)

한 클러스터의 인덱스를 다른 클러스터로 이중화(replicate) 해준다. 기존의 다른 클러스터 이중화 기법들보다 오버헤드가 적고, 추가적인 자원(임시 저장장치 등)이 필요하지 않으며 시스템 복잡성도 낮다. Follower가 Leader를 실시간 룩업, 인덱스 변화를 관찰하여 변경점을 복제한다.

이 기능을 활용함으로서 장애 복구(Disaster Recovery), 글로벌 서비스의 경우 지역별로 복제본을 두어 시스템 응답성을 높일 수 있다. (Data Locality) 그리고 여러개로 나누어져 운용되는 클러스터의 데이터를 한군데로 모아 통합 쿼리를 수행하거나 리포트를 만들 수도 있다. (Central Reporting Center)


_source Only Snapshot (데이터 복원 기능)

전체 풀 스냅샷 대비 50%정도의 저장 공간을 차지한다. 소스만 저장하고 복원하는 방식이기 때문에 복원(restore)하는데 재색인을 필요로 한다. 긴 복원 시간과 적은 저장 공간의 trade off.


Canvas !! (Beta | Basic)

Kibana의 신규 기능으로 Canvas는 기존 대비 향상된, 마치 파워포인트를 이용해 페이지를 만드는 것과 유사한 경험을 가져다 준다. 데이터의 라이브 쇼케이스 기능으로 나만의 방식으로 데이터에 대한 스토리텔링을 할 수 있다. Elasticsearch SQL을 지원하고 보고서 파일 생성이 가능.


Rollups in Kibana (Beta | Basic)

자동으로 데이터를 집계가 필요한 부분만 roll up 해서 관리한다. 통계성 데이터만 저장하므로 데이터의 저장 공간이 절약되고 적은 양의 데이터를 대상으로 하기 때문에 집계 쿼리가 빨라진다.

기타 6.5엔 Beats를 중앙에서 관리하는 도구인 Beats Central Management, 서버리스 아키텍쳐의 function 레벨로 사용가능한 새로운 타입의 Beat은 Functionbeat. Metric Beat와 연동하여 수많은 인프라 기반의 동작 데이터를 한 눈에 볼 수 있는 큐레이션 도구인 Infrastructure UI 등의 신규 기능이 도입되었다. Basic 라이센스로 제공되는 Machine Learning의 Data Visualizer는 사용자가 업로드하는 데이터 파일의 구조를 시각화해준다. 대략적인 데이터의 속성과 분포를 알려주는 것 뿐만 아니라 잘 아는 형식에 대해선 Grok pattern도 제공해주고 있다.

Java 11 버전을 지원하며 G1 가비지 컬렉터를 사용할 수 있게 되었으며 이번 업데이트를 통해선 6.3에서 지원하던 JDBC 드라이버 뿐만 아니라 ODBC 드라이버도 지원한다. Elastic Stack은 데이터를 다루는 솔루션이 제공해야할 기능의 모범사례를 누구보다 빠르고 적확하게 제공하기 때문에 데이터 관련된 일을 하는 사람이라면 Elastic Stack을 사용하지 않더라도 변경점에 대해서 관심을 가져야 할 것이란 생각이 든다.


2018년 12월 19일 수요일

시리얼 통신 (RS-232)

시리얼 통신

1. 직렬 통신은 하나 또는 두 개의 전송 라인을 사용하여 한 번에 한 비트씩 데이터를 지속적으로 송수신하는 통신 방법이다.

2. 직렬 통신에서 데이터는 하나의 신호선을 사용해 한번에 한비트씩 전송되므로, 수신측에서 데이터를 정확하게 수신하려면 송신측에서 비트를 어떤 속도로 전송하는지 알고 있어야 한다.

3. 전송 표준으로 RS-232C, RS-422A, RS-485가 있다.

4. 커넥터는 주로 D-sub 25핀, D-sub 9핀이 사용된다.
 DTR: Data Terminal Ready, 데이터 터미널 준비
 TXD: Transmit Data, 전송 데이터
 RXD: Receive Data, 수신 데이터
 RI: Ring Indicator, 착신 표시
 CTS: Clear to to Send, 송신 허가
 RTS: Request to Send, 송신 요구
 DSR: Data Set Ready, 데이터 세트 준비
 ,..... 기타

5. 설정 값.
 5.1 전송 속도: 초당 보낼 비트 수를 지정한다. (Baudrate)
 5.2 정지 비트 길이: 데이터의 끝을 나타내는 비트의 길이. 일반적으로 1, 1.5, 2비트.
 5.3 데이터 비트 길이: 일반적으로 영숫자 및 기호에는 7비트, 1바이트 이진 데이터에는 8비트.
 5.4 패리티 체크 설정: 데이터에서 오류를 찾는 기능. 짝수 패리티, 홀수 패리티, 패리티 없음 중 하나.

시리얼 통신은 Com Port를 통해 Read Write하는 단순한 구조기 때문에 Open, Close, Read, Write의 4가지 명령을 통해 작업을 제어하게 된다.

.Net Framework 환경에서의 프로그래밍

SerialPort 클래스가 정의되어 있고, 데이터 수신, 에러 수신, 핀 체인지에 대한 이벤트 설정을 할 수 있게 되어 있다. {System.IO.Ports (Assemblies: System.dll, System.IO.Ports.dll)}

설명 및 예시:
https://docs.microsoft.com/ko-kr/dotnet/api/system.io.ports.serialport?view=netframework-4.7.2


Win32 API 환경에서의 프로그래밍

파일 다루듯 다루어진다.

 1. 포트 열기: CreateFile
 2. 포트 구성: SetCommState, SetCommTimeouts
 3. 데이터 전송: WriteFile
 4. 데이터 수신: ReadFile
 5. 장치 모니터링: SetCommMask

써야되는지 알고 식겁했다.

2018년 12월 10일 월요일

[Spring] Configuration, Bean 어노테이션

org.springframework.context.annotation의 Configuration 어노테이션과 Bean 어노테이션을 이용하면 Spring Container에 새로운 Bean 객체를 제공할 수 있다.

@Configuration
public class AppConfig {
  @Bean
  public MyBean myBean() {
    // instantiate, configure and return bean ...
  }
}

초기화 과정에서 특정 값을 지정할 경우엔 다음과 같이 할 수 있을 것이다. (@Value, @Autowired, ..)

@Configuration
@PropertySource("classpath:/com/acme/app.properties")
public class AppConfig {
  @Inject Environment env;

  @Value("${bean.name}") String beanName;

  @Bean
  public MyBean myBean() {
    // return new MyBean(env.getProperty("bean.name"));
    // or
    // return new MyBean(beanName);
  }
}

여러 개의 @Configuration 간 의존 관계는 @Autowired나 클래스 상단에 @Import 구문을 이용해 지정할 수 있다.

@Configuration을 <XML>로 표현하면 다음과 같다.
<beans>
  <context:annotation-config/> <!-- enable ConfigurationClassPostProcessor -->
  <bean class="com.acme.AppConfig"/>
</beans>

참고로 @Configuration 어노테이션을 사용한 클래스에서 @Bean 어노테이션을 사용한 함수가 리턴하는 객체는 Singleton으로 관리된다.

적용된 내용은 AnnotationConfigApplicationContext로 가져올 수 있다.

ApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();

MyBean myBean = ctx.getBean(MyBean.class);
// use myBean...

@Bean 어노테이션과 함께 initMethod, destroyMethod를 지정할 수 있는데 이는 각각 초기화/종료 메서드에 대한 것이다.
@Configuration과 @Bean은 @Profile 어노테이션과 결합하여 'production', 'development' 등 환경에 따라 다르게 동작하게끔 할 수 있다.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html

JPA 기본 골격.

// Entity
@Entity
@Data
@NoArgsConstructor
public class Member {
 @Id // javax.persistence.Id
 @GeneratedValue(strategy=GenerationType.AUTO)
 private long id;

 @Column(nullable = false, length = 30)
 private String name;

 private int age;

 public Member(String name, int age) {
  this.name = name;
  this.age = age;
 }

 @Override
 public String toString() {
  return String.format("Member[id=%d, name='%s', age=%d]", id, name, age);
 }
}

// Repository
public interface MemberRepository extends CrudRepository<Member, Long> {
 List<Member> findbyNameAndAgeLessThan(String name, int age);
 List<Member> findbyNameAndAgeLessThanOrderByAgeDesc(String name, int age);

 @Query("select t from Member t where name=:name and age < :age")
 List<Member> findByNameAndAgeLessThan(@Param("name") String name, @Param("age") int age);
}

// Booter
@EntityScan(basePackages="package.name")
@EnableJpaRepositories(basePackages="another.package.name")
@SpringBootApplication
public class TestJpaApplication {
 public static void main(String[] args) {
  SpringApplication.run(TestJpaApplication.class, args);
 }
}

참고로 JPA가 제공하는 Repository의 상속 계층은 다음과 같다.
CrudRepository만 써도 일반적인 CRUD 작업은 할 수 있다.

1. public interface Repository<T, ID extends Serializable>
2. public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID>
3. public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID>
4. public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>

https://www.concretepage.com/spring-boot/spring-boot-crudrepository-example

2018년 12월 6일 목요일

[BlockChain] 이더리움 2.0

이더리움의 최종 목적지는 Serenity, 이더리움 2.0이라고 불리기도 한다. (* Serenity는 고요함, 맑음의 뜻을 가지고 있다.)



현재는 Metropolis 단계로 Metropolis는 비잔티움과 콘스탄티노플로 세분화되어 있다. 그 다음이 Serenity다. (* 콘스탄티노플은 1월로 연기된 바 있다.)

현 단계에서 이더리움은 UX에 대해서도 고민이 많다고 한다.
예를 들면 '당신의 할머니가 비트코인을 사용할 수 있는가?'에 대한 솔루션을 찾아가는 것이다.

Serenity의 핵심은 Sharding, Casper(PoS, Proof of Stake)로 요약된다.

특정 블록 체인은 Decentralization, Scalability, Safety 3가지를 모두 만족시킬 수 없다 (Blockchain Trielemma). 이더리움은 상대적으로 Scailability에 약점이 있어서 TPS가 낮은 편이다. 이더리움은 Serenity에 Sharding 기법을 적용해서 이를 일부 극복하고자 한다. 그런데 Sharding은 PoW 방식에서 동작하지 않으므로 PoS를 같이 도입할 계획을 가지고 있다.

이더리움이 완전한 PoS로 전환하는 것은 아니고, 현재 동작하는 PoW 네트워크 하위에 PoS 레이어를 둬서 PoW와 PoS를 조합해서 사용하는 방식을 구상중이다. 이를 Casper라고 한다. 4개의 Layered Architecture로 구성되어 있다.

  1. Main Chain (PoW) - 기존의 이더리움 네트워크
  2. Beacon Chain (2019) - 코디네이션 수행. PoS 노드를 샤드에 할당하는 등의 관리 레이어.
  3. Shard Chain (2020) - Data Layer, 여기에 PoS 노드가 위치. 특징으로 30 ETH만 있어도 PoS에 참여 가능. 대쉬의 경우 PoS 노드에 참여하려면 1억 가량이 필요하다고 한다.)
  4. Execution VM (2021) - 잘 모르겠다..


** PoW (Proof Of Work)
PoW는 컴퓨팅 파워를 이용, 새로 생기는 블록의 nonce 값을 찾아내 거래의 유효성을 증명하는 방식. Nonce 값을 찾아낸 사람은 거래의 유효성을 증명해 준 것에 대한 대가로 코인을 받게 된다.

(Difficulty에 따라 선택된 target 데이터 규격을 만족시키는) nonce 값을 풀기 위한 공식은 따로 없으므로 채굴자는 숫자를 하나씩 넣어보는 수 밖에 없다. 블록의 nonce 값을 찾기 위해서는 평균 수천조 번 이상의 시도가 필요하여, 이를 한명이 시도하기는 불가능하다. 이 때문에 특정 단체에 자신의 컴퓨팅 파워를 할당해주고 해당 단체에서 채굴에 성공한 경우 컴퓨터 파워를 할당한 양만큼 코인을 나눠받는 방식이 많이 이용된다. 이 단체를 '마이닝 풀'이라고 부른다. Difficulty는 조절 알고리즘에 의해 변화되며 10분당 1~2개의 블록이 생성되는 것을 보장한다.

** PoS (Proof Of Stake)
PoS는 지분을 이용한 거래 유효성 증명방식이다. 지분을 많이 가진 노드는 데이터를 업데이트할 권한을 더 많이 갖게 된다. 각 노드가 옳다고 생각하는 블록에 동의를 하면서 자신이 가진 지분을 해당 블록에 보여주고 증명하는 것이고, 과반수의 자산이 동의한 블록이 더 빠르고 더 길게 블록을 형성하게 된다.

거래 수수료는 블록을 생성한 노드가 가져간다. 다른 참여자에게는 이자와 유사한 방식으로 코인이 지급되며 일정한 양 이상의 코인을 보관하고 있는 지갑을 블록체인 네트워크와 연결시킬 경우 보상을 받을 수 있다.


Price 상 나쁜 상황이지만 이더리움은 로드맵을 충실히 따라가고 있을 뿐이다.

의식의 흐름을 따라가면서 정리한 Auth.

Authentication : A client must provide some evidence of who they are. This might involve signed certificates or it might involve credentials like a username and password. It might involve multiple factors, such as an sms message to a phone that the user should have access to. The web server must validate this authentication.
→ 특정 서비스의 서버는 사용자가 누구인지 식별할 수 있어야 한다.

Authorization : A server must define areas of authority and allocate these to groups of users. Furthermore, individual users must be defined as members of the authorization groups.
→ 클라이언트가 서비스에서 이용 가능한 기능의 범위. 권한에 대한 영역을 설정하고 각각의 사용자를 특정 권한 그룹에 포함시키는 것이 일반적.

인증 정보를 제공하는 다양한 방법이 있다.
  1. 인증서: 암호화된 인증서로 디지털 서명 뿐만 아니라 인증 기관에 대한 참조를 포함한다. 이러한 인증서는 SSL(Secure Socket Layer)를 통해 교환된다. 일반적으론 서버 측에서 단방향으로 제공되는 정보이지만 특정 환경에서는 클라이언트와 서버가 모두 상호 인증에 사용되는 인증서를 갖고 있어야 하는 경우도 있다.
  2. API 키 / 토큰: 웹 서비스는 특정 리소스에 접근 가능한 키를 제공할 수 있다. 키에 라이프-타임을 지정할 수도 있을 것이다.
  3. 사용자 이름 / 비밀번호: 웹 서버는 사용자 이름과 비밀번호를 통해 사용자를 식별할 수 있다. e-mail, SMS 인증 단계가 추가될 수 있다.
  4. 타사(Third-party) 인증: OpenID와 같은 서비스. 모든 사이트에 방문할 때마다 새로운 계정을 만들고 관리할 필요가 없다. 특정 사이트(Relying Party)는 OpenID Provider에게 인증을 위임하게 된다.


HTTP 인증

  1. HTTP "Basic" 인증: 사용자 계정과 패스워드를 전송하는 방식. Base64 인코딩을 이용한다. 클라이언트 서버 간의 안전한 데이터 교환(암호화)을 위해 SSL(Secure Socket Layer)을 사용하며 각 요청에 Authorization 헤더가 포함된다.
https://developer.mozilla.org/ko/docs/Web/HTTP/Authentication
  2. HTTP "Digest" 인증: 클라이언트가 서버에 특정 페이지를 요청하면 서버는 Digest 인증이 필요하다고 통보하면서 nonce(자주 바뀌는 증표) 값 등의 서버 정보를 함께 전달한다. 클라이언트는 전달받은 nonce와 클라이언트 정보를 결합해 MD5(권장 알고리즘) 암호화하여 전송하고 서버는 이를 검증한다.


OpenSSL

OpenSSL은 Self-signed certificate를 만들 수 있는 툴이다. 프로덕션 레벨 전 단계에서 테스트 목적의 인증서를 발급하기 위해 주로 쓰인다. 프로덕션 레벨에서 쓰이는 공인 SSL 인증서의 경우엔 비용이 발생한다.
(* SSL, 인증서: SSL은 웹 서버와 클라이언트(브라우저) 사이의 보안을 위한 프로토콜이다. SSL은 대칭키를 이용한 암호화 방식을 채택하고 있는데 이러한 암호화 통신(https)을 하기 위해선 SSL 인증서가 필요하다. 인증서에는 인증서 소유자의 정보, 용도, 유효기간, 공개 키 등의 정보가 포함되어 있다. 인증서가 유효한지는 CA가 보증해준다. 그리고 공인된 CA 목록은 이미 브라우저가 알고 있다.)
  1. private key file을 만든다. 파일명은 ssl.key
→ openssl genrsa 1024 > ssl.key
  2. [1]에서 생성한 key file을 가지고 certificate를 만든다. 파일명은 ssl.cert
→ openssl req -new -x509 -nodes -sha1 -days 365 -key ssl.key > ssl.cert


OAuth

OAuth는 인증을 위한 오픈 스탠더드 프로토콜. 버전 1.0, 1.0 A, 그리고 2.0 버전이 있는데 1.0 버전과 2.0 버전은 호환되지 않는다.

OAuth에서 Auth는 Authentication 과정도 포함하지만 주 목적은 특정 기능에 접근하려는 사용자에게 해당 권한(Authorization)이 있는지를 확인하는 것이다. 그렇기 때문에 OAuth 인증을 진행할 때 해당 서비스 제공자는 '제3자가 어떤 정보나 서비스에 사용자의 권한으로 접근하려 하는데 허용하겠느냐'라는 안내 메시지를 보여주고 있다.

OAuth는 방문증을 수령하는 과정에 비유할 수 있다. 방문증은 사원증과 다르다. 예를 들면, 방문증을 가진 사람이 출입할 수 있는 곳은 제한적일 수 있다.

OAuth 1.0에 대한 개념 용어.
  1. User: Service Provider에 계정을 가지고 있으면서, Consumer를 이용하려는 사용자.
  2. Service Provider: OAuth를 사용하는 Open API를 제공하는 서비스 (Service Provider는 Open API를 제공함으로써 자연스러운 서비스 홍보 효과를 기대할 수 있다.)
  3. Consumer: OAuth 인증을 사용해 Service Provider의 기능을 사용하려는 애플리케이션이나 웹 서비스
  4. Request Token: Consumer가 Service Provider에게 접근 권한을 인증받기 위해 사용하는 값. 인증이 완료된 후에는 Access Token으로 교환한다.
  5. Access Token: 인증 후 Consumer가 Service Provider의 자원에 접근하기 위한 키를 포함한 값. (* 방문증 예시를 떠올리면 방문증이 Access Token 이다.)

OAuth 1.0 vs OAuth 2.0
  1. OAuth 1.0은 웹 애플리케이션에 특화되어 있다면 OAuth 2.0은 다양한 형태의 애플리케이션에 대한 지원을 강화했다.
  2. OAuth 2.0은 HTTPS를 사용하고 암호화 과정이 필요하지 않다.
  3. OAuth 2.0은 보안 강화를 위해 Access Token의 Life-time을 지정할 수 있도록 했다.

이어지는 내용은 게으름으로. 링크만.

OAuth 2.0 정리글.
http://blog.weirdx.io/post/39955

토큰 기반 인증에 대한 정리글.
https://velopert.com/2350
https://velopert.com/2389



직장생활, 돈에 대한 뼈때리는 글.

하루종일 일만하는 사람은 돈 벌 시간이 없다.
- 존 D 록펠러

원문 링크.
https://m.blog.naver.com/huridam/221413264325

돈과 직업에 대한 가치관을 먼저 정립하자.
직장인, 회사원의 삶 만이 전형적인 삶의 모습이 아니다.

연봉 7천과 1억은 월소득으로 50만원 이하로 차이가 난다.
월급 150과 200은 큰 차이인데, 300만원이나 350만원은 별 체감상 차이가 없다.

세상에 돈을 버는 길은 직장인 만이 아니라는 사실을, 성적과 학벌은 돈을 버는 것과 상관관계는 있을지언정, 인과관계가 있는 것은 아니라는 것을 받아들이자.

나는 과연 무엇을 해서 얼마나 돈을 벌고 싶은가에 대해 생각해볼 지점이다.
인생의 테크트리는 결국 치킨집이라는 얘기가 있다. 저런거 보고 쓴웃음 짓고 그냥 넘어가면 안된다. 냉정하게 생각해보자. 내 20년 후가 저렇다는 것을 받아들일거면 지금 이 시점에 회사를 다녀야 할 이유는 무엇일까.

무엇을 해서 돈을 벌고, 어떤 직업을 가질 것인지, 거기에 지금 내가 다니는 대학이, 하는 공부가 도움이 되는 것인지 고민해봐야 한다. 내 의지대로 내 시간을 쓰면서 살기 위해서 준비가 필요하다. 돈버는 것에 대한 공부. 치킨집을 하더라도 떠밀려서 차리는 경우와 공부하고 준비해서 차리는 경우는 결과가 다르다.

어쨌든 최소한, 남들에게 등떠밀려서, 무리에 섞여서 직장인이 되지는 말고 직장인의 삶이 무엇인지 알고, 다른 돈벌이가 있다는 것도 알고 내 손으로 자발적으로 그 길을 선택하자.

2018년 12월 5일 수요일

윤종신 - 계절은 너에게 배웠어.

좋아하는 가수가 있고, 따라부를 수 있는 노래가 있다는 건 큰 힘이 된다. 윤종신 굿즈 '계절은 너에게 배웠어'를 출퇴근 하면서 읽었다. 가사가 절반이라 금새 읽을 수 있다. 읽기 전엔 윤종신의 생각과 개인사에 대해 들여다볼 수 있겠구나 하는 기대가 있었다. 하지만 개인사보단 '사랑, 이별'에 관한 노랫말 비중이 컸고, 가사를 적었을 때의 느낌과 생각을 위주로 서술하고 있었기 때문에 기대완 결이 조금 달랐던 책이다.

69p

저는 좋은 가사란 구체적이면서도 구체적이지 않은 가사라고 생각합니다. ... 노래를 듣는 이가 머릿속에 그림을 그려나갈 수 있도록 충분히 구체적이되, 사람마다 각기 다른 그림을 상상할 수 있도록 적당히 여백이 있어야 한다는 말입니다.


82p

사랑 이야기는 응당 어떠해야 한다는 서사적 경계에 갇히지 말았으면 좋겠어요. 그리고 사랑 이야기라고 해서 감정을 직접 서술해야 한다는 고정관념에서 벗어났으면 좋겠어요.


157p

...

그저 노래가 좋아 부르다
남들보다 늦게 떠나기에
조금은 이르게 뒤돌아보는 소중한
나의 이십대


164p

삼십대는 불안한 시기입니다. 아예 모르면 괜찮을 텐데 뭔가를 좀 알게 됐기 때문에 더욱더 불안해지는 시기죠. 지금 여기서 잘못되면 끝이라는 압박 때문에 필사적이고, 지금 이 기회를 무조건 움켜쥐어야 한다는 강박 때문에 고통스럽습니다. 삼십대를 치열하게 보내야 남은 인생에서 고생하지 않는다는 암묵적인 분위기 때문에 마음고생도 심하고, 이제 더는 어리지 않다는, 누구도 봐주지 않는다는, 진짜 어른이 되어야 한다는 자각 때문에 어깨도 무겁습니다. ... 각자 나이를 먹어가면서 단단해진 가치관이 부딪히는 건 피할 수가 없습니다.


180p

...
이렇게 노래의 힘을 빌어
한번 말해본다
기어코
행복하게 해준다.


182p

저는 아이들 때문에 희생하는 부모는 되고 싶지 않습니다. 제 아이들 역시 부모에게 종속되지 않기를 바라고요. ... 각각의 소중한 개인으로 성장하기를 바랍니다. ... 자기 자신을 위해 살아가는 개인이 되는 것. 제가 아이들에게 바라는 건 그것뿐입니다.


206p

이제 지난 삶을 조금은 관조할 수 있는 나이가 되었기 때문일까요, 저는 제가 그런 사람이라는 게 못내 아쉽습니다. 특히 젊은 시절을 떠올리면 안타까운 마음이 커지는데, 뭐랄까 저는 좀 퍼져 있었거든요. 약간의 패배주의와 막연한 기대감에 젖어서 공상만 많이 했어요. ... 그때 내가 겁없이 돌아다니고 원 없이 배웠다면 어땠을까, 좀더 진취적이고 활동적이고 오픈 마인드인 사람이면 어땠을까, 하는 생각을 지금도 가끔 해요. 떠나지 못했다는 아쉬움이 늘 가슴 한쪽에 남아 있는 거죠.


258p

제 장례식에서는 술을 마음껏 마실 수 있었으면 좋겠어요. 소주나 맥주뿐만 아니라 막걸리도 있었으면 좋겠고, 와인이나 양주도 마실 수 있으면 좋겠습니다. 파티처럼 다들 자기가 마시고 싶은 술을 직접 들고 오면 좋을 것 같아요. 그리고 저를 기억하면서 마음껏 건배해줬으면 좋겠습니다. 저에 대해 섭섭했던 것들, 아쉬웠던 것들, 인상적이었던 것들, 좋았던 것들을 떠올리면서 웃고 떠들었으면 좋겠어요.


263p

제 말이 활자화되는 것도 부담스러운 게 사실입니다. 한번 활자화되면 오랜 시간이 지나도 남기 때문에 그게 제 의지와는 상관없이 또다른 저를 만드는 것 같거든요. ... 아마도 저는 이 책 안에서 그 모든 실수를 했을 겁니다. 어떤 부분에서는 실제의 저보다 훨씬 더 근사해 보였을 거고, 또 어떤 부분에서는 실제의 저보다 훨씬 못나 보였을 거에요.

2018년 12월 2일 일요일

[MS-SQL] 날짜 변환 함수, CONVERT

MS-SQL의 CONVERT 함수는 CAST 함수와 비슷하지만
DATE 형식을 변환할 때 세부 변환 스타일을 지정해줄 수 있어서 날짜 변환 연산이 필요한 경우엔 CONVERT 함수를 사용하는 것이 낫다.

CONVERT와 CAST의 형식은 아래와 같다.
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
CAST ( expression AS data_type [ ( length ) ] )

현재 시간을 문자열 형식으로 바꾸는데, 마지막 'style' 파라미터를 이용해 변환 형식을 지정할 수 있다.
우리나라 사람은 '년-월-일' 표현이나 '시:분:초' 표현에 익숙하기 때문에 자주쓰게 되는 형식은 다음과 같다.
참고로 형식 2가 'yy' 버전이라면 형식에 100을 더한 102가 'yyyy' 버전이 된다.

SELECT CONVERT(VARCHAR, GETDATE(), 2) -- 18.02.03 (yy.mm.dd, ANSI 표준)
SELECT CONVERT(VARCHAR, GETDATE(), 102) -- 2018.02.03 (yyyy.mm.dd, ANSI 표준)
SELECT CONVERT(VARCHAR, GETDATE(), 11) -- 18/12/03 (yy/mm/dd, 일본 표준)
SELECT CONVERT(VARCHAR, GETDATE(), 111) -- 2018/12/03 (yy/mm/dd, 일본 표준)
SELECT CONVERT(VARCHAR, GETDATE(), 12) -- 181203 (yymmdd, ISO 표준)
SELECT CONVERT(VARCHAR, GETDATE(), 112) -- 20181203 (yyyymmdd, ISO 표준)
SELECT CONVERT(VARCHAR, GETDATE(), 20 or 120) -- 2018-12-03 10:54:34 (yyyy-mm-dd hh:mi:ss(24h), ODBC canonical 표준)

[MSDN: https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-2017]