[SCIT마스터 작문] 2017年10月30日

유연근무제를 도입하고 있는 기업이 있습니다만, 이 제도에 대해 당신의 의견을 서술해주세요.

일러두기

  • 이 주장은 논리 전개를 위해 선택된 것으로 자신의 생각과 일치하다고 할 수 없습니다.
  • 일본어로 쓴 다음, 한국어로 옮긴 글입니다.

作文

フレックス制を導入している企業が増えているなか、私はそのメリットが知られてなくて、まだ多くの会社が導入してないことが残念な事実だと思います。

なぜなら、通勤ラッシュも避けられるし、自分に合う時間を選んで働くことで人それぞれである活動時間に集中していい結果に繋がるからです。私も学校のバイトをしてしていたとき、午後を選んで、通勤時間を避け、ストレスなく働いたことがあります。

たしかに、会社の中で連絡が難しくなるこおはあると思います。しかし、これはメッセンジャーなどの機能を使えば、簡単に対処できます。

ですから、私はフレックス制の導入をより進めた方がいいと思います。

 

작문

유연근무제를 도입하고 있는 기업이 늘고 있는 요즘, 저는 그 장점이 알려지지 않아서, 아직 많은 기업이 도입하지 않고 있는 것이 안타까운 사실이라고 생각합니다.

왜냐하면, 통근 러시아워도 피할 수 있고, 자신에게 맞는 시간을 골라서 일하는 것으로 사람들 제각각인 활동 시간에 집중해서 좋은 결과로 이어질 수 있기 때문입니다. 저도 학교에서 아르바이트를 했을 때, 오후를 골라서 통근 시간을 피해서 스트레스 없이 일한 적이 있습니다.

물론 회사에서 연락이 어려워지는 문제가 있으리라 생각합니다. 그러나 이것은 메신저 등의 기능을 사용하면 간단히 대처할 수 있습니다.

그러므로, 저는 유연근무제의 도입을 더욱 진행하는 편이 좋다고 생각합니다.

감상

지난주 문장의 속편 같이 닮은 경험입니다. 하지만 근거편은 별로 발전하지 않은 것 같다는 생각이 듭니다. 어디에 있어도, 언제 출근해도 괜찮아지려면, 출세를 해야지요.

프로그래밍이란?

사람이 프로그래밍 언어로 명령하여 컴퓨터를 기동하는 기술

하나 이상의 추상 알고리즘을 특정 프로그래밍 언어를 사용하여, 상세한 컴퓨터 프로그래밍으로 실체화하는 기술을 말한다.

소스 코드 → 컴파일러 → 기계어

JAVA의 탄생 배경

  • 1991년 Sun사에서 제임스 고슬린을 중심으로 가전제품에 사용하기 위한 언어의 제작
  • 특정 CPU에 의존하지 않기 위해 가상 머신을 사용하게 됨
  • 넷 발달과 함께 웹에 사용할 수 있는 언어가 되었다.

[SCIT마스터 작문] 2017年10月23日

당신에게 지금 100만 엔의 여유가 있다면, 저금하시겠습니까? 투자하시겠습니까?

일러두기

  • 이 주장은 논리 전개를 위해 선택된 것으로 자신의 생각과 일치하다고 할 수 없습니다.
  • 일본어로 쓴 다음, 한국어로 옮긴 글입니다.

작문

돈에 여유가 있다면, 저금을 할 것인가, 아니면 투자를 할 것인가. 거기에는 반드시 옳은 정답은 없습니다. 그렇지만, 스스로의 기준만 있다면, 앞으로 어떻게 할지는 정할 수 있습니다. 그래서 저는 저금을 50%, 또 투자를 50%로 절반씩 나누었습니다.

왜냐하면, 저금의 이점인 재산의 보장과 투자의 이점은 높은 이익, 양쪽을 얻을 수 있기 때문입니다. 최근에는 10년간 계속된 불황도 끝이 예측되고 있고, 각국에서는 제각기 투자를 서두르고 있다고 합니다. 금리도 한국에서는 미국처럼 앞으로 오를 것이며, 투자의 이익도 경제와 연결되어 있기 때문입니다.

물론, 일본은 아직 제로 금리고, 투자 방법에 따라서 실패하기 쉽다는 점도 있습니다. 그러나 저도 5년 정도 전부터 투자 펀드가 10% 정도의 이익을 얻었으므로, 평소 투자하기 때문에야말로, 자신의 방법을 익힐 수 있다고 할 수 있습니다.

그러므로 만약 제게 100만 엔이 생긴다면, 저금과 투자를 절반씩 하려고 생각합니다.

선생님의 코멘트

세세한 문법 사용의 실수가 신경 쓰입니다.

감상

애매한 문장에 애매한 근거, 그런 곳엔 애매한 매력이 깃드는 법입니다. 적어도 한 가지로 입장을 정해서 썼다면, 읽는 쪽도 즐길 수 있는 문장이 되지 않았을까, 하고 생각해봅니다.

TickCount 탐구

발단

이 의문이 시작된 것은 단순히 String(또는 C#과 같은 언어에서는 string으로 간소화되기도 하죠, 이하 string)과 StringBuilder, StringBuffer의 성능 차이에 대한 초급적인 언급이었습니다.

string은 실제로는 읽기 전용처럼 쓰인다는 건 초보 빼고는 다 알고 있는 사실입니다. immutable이라고 하던데, 변하지 않는다는 말이죠. 따라서 우리가 자유롭게 +나 concat을 하면 string은 그 때마다 새로운 개체를 반환하게 됩니다.

C++에서는 strcat()으로 문자열을 수정할 때 큰 영역을 미리 할당해두면 속도가 비약적으로 증가한다고 하지만, C#과 Java에서는 문자열의 수정이 어렵기 때문에 다른 방법이 필요하다는 것이고, 그 내용은 MSDN에도 잘 나와 있습니다. Java랑 C#이 판박이인 점은 코드를 복붙해보면 쉽게 알 수 있는 내용이더군요.

효과 검증

그래서 이걸 어떻게 알 수 있을까요. Java 선생님은 문자열을 파바바박 쏟아내는 반복문을 짜고, “어라, 별 차이가 없는데” 하셨지만, 실제로 큰 차이가 발생하는 것은 어느 정도 코드를 통해서도 쉽게 파악할 수 있었습니다.

 

/* string performance in C# */
            string me = "";
            Console.WriteLine("String START");
            var cnt = Environment.TickCount;
            for (int i = 0; i < 100000; i++)
            {
                me += "a";
            }
            Console.WriteLine("Time: "+(Environment.TickCount - cnt).ToString());
            Console.WriteLine("END");
            //Console.WriteLine(me);

            StringBuilder sb = new StringBuilder();
            Console.WriteLine("StringBuilder START");
            cnt = Environment.TickCount;
            for (int i = 0; i < 100000; i++)
            {
                sb.Append("a");
            }
            Console.WriteLine("Time: " + (Environment.TickCount - cnt).ToString());
            Console.WriteLine("END");

C# 코드

/* string performance */
        String me = "";
        System.out.println("String START");
        long cnt = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++)
        {
            me += "a";
        }
        System.out.println("Time: "+(System.currentTimeMillis() - cnt));
        System.out.println("END");

        StringBuffer sb = new StringBuffer();
        System.out.println("StringBuffer START");
        System.out.printf("capacity: %d, length: %d\n", sb.capacity(), sb.length());
        cnt = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++)
        {
            sb.append("a");
        }
        System.out.println("Time: " + (System.currentTimeMillis() - cnt));
        System.out.printf("capacity: %d, length: %d\n", sb.capacity(), sb.length());
        System.out.println("END");

Java코드는 다음과 같은 결과가 나왔습니다.

String START
Time: 7467
END
StringBuffer START
capacity: 16, length: 0
Time: 9
capacity: 294910, length: 200000
END

어마어마한 차이네요. 10만 개의 String을 붙이면서 7초 넘게 소요되었습니다. 한편, C#은 그나마 5초 내외로 되는게 코드 최적화의 힘인가 싶습니다. StringBuffer와 StringBuilder 모두 일의 자리나 심지어 0ms로, 찰나에 가까운 수준이라 극명한 차이를 보여주더군요.

역시 이미 사용된 Heap을 얼마나 유용하게 사용하고, 새로운 메모리 할당을 피하는 것이 중요한지 알게 되는 실험이었습니다.

새로운 의문

흥미로운 점은 Java의 StringBuffer와 달리 C#의 StringBuilder 소요 시간이 0ms라고 출력된 점입니다. 코드 한 줄도 아니고 10만인데 그게 가능한 걸까? 오차는 아닐까? 궁금해졌습니다.

당장, Environment.TickCount를 의심하기 시작했습니다. 사실 TickCount로 코드 속도를 비교하는 시대는 멀티 프로세서 시대의 도래로 종말을 맞았다는 이야기도 있습니다. 코드의 선후 관계는 보존되더라도 코드가 동시에 실행되는 타이밍의 차이는 충분히 있을 수 있다는, 쓰레드 위험이 일상화된 멀티 프로세싱의 시대니까요.

그래서 당장 C# 유저들은 무슨 방법을 쓰는가 알아보았습니다.

  • Environment.TickCount
  • GetTickCount / GetTickCount64
  • DateTime.Now(UtcNow).Ticks
  • Stopwatch
  • static Stopwatch.GetTimestamp

Environment.TickCount

가장 편하게 쓸 수 있는 Environment static class의 멤버 TickCount입니다. 컴퓨터의 UpTime을 보여주는 GetTickCount()와 다를 게 없는 특성으로, 부호 있는 정수(int)인지라, 차를 구할 때 24.9일 이상 켜진 컴퓨터에서는 특별한 조치가 필요합니다. MSDN에서는 Int32.MaxValue와 & 연산을 하여 해결하였습니다. (부호만 제거되겠군요)

GetTickCount64

Vista부터 쓸 수 있는 Win32 API인 GetTickCount64는 부호 없는 long 타입으로 반환합니다. 시스템이 켜진 시간으로부터 출력되는 밀리세컨드 값을 담기에 충분한 용량이죠. 다만, 실제로 놀지 않고 컴퓨터가 일한 시간을 구하려면 QueryUnbiasedInterruptTime을 사용해야 합니다.

DateTime.Now(UtcNow).Ticks

서기 1년 1월 1일 자정부터 100나노세컨드로 지난 시간을 나타냅니다. 윤초 같은 보정은 없다고 합니다.

Stopwatch

Stopwatch는 new 키워드 없이 인스턴스화가 가능한 Static 메소드 StartNew()를 통해 시간을 재기 시작하여 Stop()을 호출한 다음, ElapsedMilliseconds와 같은 속성으로 경과 시간을 측정할 수 있습니다.

  • IsHighResolution 속성에서 현재 컴퓨터의 하드웨어가 별도의 고해상도 성능 카운터 기능이 있는지 알 수 있는데, 현세대 컴퓨터는 대체로 True를 반환하는 것 같습니다.
  • Frequency 속성은 타이머의 틱 주기를 반환합니다.
    long frequency = Stopwatch.Frequency;
        Console.WriteLine("  Timer frequency in ticks per second = {0}",
            frequency);
        long nanosecPerTick = (1000L*1000L*1000L) / frequency;
        Console.WriteLine("  Timer is accurate within {0} nanoseconds", 
            nanosecPerTick);
    • 이와 같은 코드에서 Stopwatch 타이머의 정확도가 나타납니다.
        Timer frequency in ticks per second = 2343750
        Timer is accurate within 426 nanoseconds

static Stopwatch.GetTimestamp

Stopwatch의 인스턴스화 후 계산하는 시간을 아까워한 일부 유저는 GetTimestamp static 메소드의 성능이 더 좋지 않을까 생각하더군요.

  • 고해상도 성능 카운터가 활성화된 상태에선, 현재값을 출력합니다.
  • 일반 시스템 시계를 쓰는 경우, DateTime.Ticks와 동일한 값을 출력합니다.

벤치마킹

Repeating measurement 3 times in loop of 10,000,000:

Measured: GetTickCount64() [ms]: 228
Measured: Environment.TickCount [ms]: 50
Measured: DateTime.UtcNow.Ticks [ms]: 83
Measured: Stopwatch: .ElapsedMilliseconds [ms]: 856
Measured: static Stopwatch.GetTimestamp [ms]: 476
Measured: Stopwatch+conversion to DateTime [ms]:  811

Measured: GetTickCount64() [ms]: 219
Measured: Environment.TickCount [ms]: 50
Measured: DateTime.UtcNow.Ticks [ms]: 84
Measured: Stopwatch: .ElapsedMilliseconds [ms]: 847
Measured: static Stopwatch.GetTimestamp [ms]: 465
Measured: Stopwatch+conversion to DateTime [ms]:  799

Measured: GetTickCount64() [ms]: 235
Measured: Environment.TickCount [ms]: 51
Measured: DateTime.UtcNow.Ticks [ms]: 84
Measured: Stopwatch: .ElapsedMilliseconds [ms]: 851
Measured: static Stopwatch.GetTimestamp [ms]: 470
Measured: Stopwatch+conversion to DateTime [ms]:  791

Compare that with DateTime.Now.Ticks [ms]: 1150

General Stopwatch information:
- Using high-resolution performance counter for Stopwatch class.
- Stopwatch accuracy- ticks per microsecond (1000 ms): 2.3
 (Max. tick resolution normally is 100 nanoseconds, this is 10 ticks/microsecond.)
- Approximated capacity (maxtime) of TickCount [dd:hh:mm:ss] 25:20:31:23

Done.

단일 스레드만 쓰도록 프로세스 설정한 다음, 스레드 우선 순위를 높이고, Stopwatch를 활용하여 1000만 번 각각 호출하는데 걸린 시간입니다.

TickCount가 공통적으로 빠르지 않냐 싶은데, Stopwatch는 ElapsedMilliseconds 표시를 위해 추가로 계산하는 시간도 고려해야 할 듯 합니다.
개인적으로는 Start() Stop()을 반복하는 게 더 의미 있는 행동이 아닌가 싶기도 한데 말이죠.

 

벤치마킹 소스 코드 참고: https://stackoverflow.com/questions/243351/environment-tickcount-vs-datetime-now

결론

GetTickCount는 혼돈과 혼돈입니다. 설마 20여 일 동안 컴퓨터를 켜고 있을 멍청이가 있으리라 생각했을까요. DWORD로 부호 없애봐야 40여 일이군요.

쓰라는 거 써서 큰 이상이 생길 것 같진 않습니다. 하지만, 무엇이 오래 걸리는지 메소드와 클래스별 특징을 잘 알고 있다면, 오래 걸리는 작업을 최대한 회피하거나 미루는 방식으로 퍼포먼스를 더 향상시킬 수 있겠지요.

앞으로도 궁금한 점이 있으면 직접 실험해야겠다 마음 먹게 되는 주제였습니다.

프로그램의 기초

프로그램이란

컴퓨터가 범용적인 기계가 된 것은 바로 프로그램(program) 때문이다. 프로그램은 컴퓨터를 위한 작업 지시서로서, 구체적으로 컴퓨터가 특정한 작업을 하기 위하 명령어의 리스트이다. 명령어란 CPU가 수행하는 기초적인 연산이다.

프로그래밍 언어

  • 소스 코드(source code): 원하는 작업을 텍스트로 기술한 것
  • 소스 파일(source file): 소스 코드가 파일에 저장된 것
  • 오브젝트 파일(object file): 컴파일러가 기계어로 변환하여 파일에 저장한 것

[SCIT마스터 작문] 2017年10月16日

스스로 사장이 된다면, 어떤 복지 제도를 만들고 싶습니까? 왜 그렇습니까?

일러두기

  • 이 주장은 논리 전개를 위해 선택된 것으로 자신의 생각과 일치하다고 할 수 없습니다.
  • 일본어로 쓴 다음, 한국어로 옮긴 글입니다.

작문

만약 자신이 사장이 된다면 어떤 복지 제도를 만들고 싶은가? 그렇게 생각해서 회사 입장에 서봤습니다. 그렇게 함으로써 견해를 넓일 수 있기 때문입니다. 제가 떠올린 것은, 일하는 장소를 선택할 수 있는 제도입니다.

왜냐하면, 장소를 바꾸는 것이, 떨어진 집중력을 높일 수 있는 최고의 방법이기 때문입니다. 그리고 상상력도 풍부해져서, 효율도 높아집니다.

물론 사원이 여기저기 흩어져서 어디에 있는지 모르게 되니까 좋지 않다고 생각될지도 모르지만, 원격에서 연락은 최근에는 어려운 일이 아닙니다.

그러므로 사원들이 자유롭게 장소를 선택할 수 있는 복지 제도를 만들고 싶다고 생각합니다.

선생님의 코멘트

자신의 경험을 넣으면 훨씬 좋을 것 같네요.

예) 저도 SC 마스터에서 공부할 때, 휴게실에 이동하면 집중할 수 있습니다.

감상

이번 주부터 선생님이 바뀌어서(반 재편성) 제대로 코멘트를 달아주십니다. 연습해서 지적받지 않도록 해야겠다고 생각했습니다.

JAVA 연휴 평가 코드

Q1

import java.util.Scanner;

public class Q1 {

/*
 * 정수를 입력하세요: 8
 * 3의 배수도 5의 배수도 아닙니다.
 * 정수를 입력하세요: 3
 * 3의 배수입니다.
 */
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.print("정수를 입력하세요: ");
		
		int input = sc.nextInt();
		
		boolean is3mul = input % 3 == 0;
		boolean is5mul = input % 5 == 0;
		
		String output = "";
		if(!(is3mul || is5mul)) {
			output = "3의 배수도 5의 배수도 아닙니다.";
		} else {
			output += (is3mul && is5mul ? "3과 " : (is3mul ? "3의 " : ""));
			output += (is5mul ? "5의 " : "");
			output += "배수입니다.";
		}
		
		System.out.println(output);
		sc.close();
	}

}

Q2

import java.util.Scanner;

public class Q2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.print("정수1 입력: ");
		int x = sc.nextInt();
		System.out.print("정수2 입력: ");
		int y = sc.nextInt();
		int min = (x < y) ? x : y;
		int max = (x < y) ? y : x;
		
		for(int i = min; i <= max; i++) {
			System.out.print(i+" ");
		}
		sc.close();
	}

}

Q3

class Account {
	private int num;
	private String name;
	private int balance;
	
	public Account(int num, String name) {
		this.num = num;
		this.name = name;
		this.balance = 0;
	}

	public Account(int num, String name, int balance) {
		this.num = num;
		this.name = name;
		this.balance = balance;
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getBalance() {
		return balance;
	}
	
	public void deposit(int money) {
		this.balance += money;
	}
	
	public void withdraw(int money) {
		this.balance -= money;
	}
	
	public void print() {
		System.out.printf("번호:%d\t이름:%s\t잔액:%d", this.num, this.name, this.balance);
	}
}

public class Q3 {

	public static void main(String[] args) {
		//기본 생성자로는 객체를 생성할 수 없게 한다. 아래의 코드는 에러가 나야 함.
		//Account ac = new Account();
		
		//계좌번호와 이름을 입력받는 생성자를 정의한다. 이 때 잔액은 0
		Account ac1 = new Account(1, "김철수");
		
		//계좌번호와 이름, 잔액을 모두 입력받는 생성자를 정의한다.
		Account ac2 = new Account(2, "이영희", 10000);
		
		//이름을 리턴하는 메소드를 정의한다. 결과는 "이영희" 출력
		System.out.println(ac2.getName());
		
		//잔액은 변경 불가능. 아래 코드 모두 에러
		//ac2.balance = 1000;
		//ac2.setBalance(1000);
		
		//입금을 하면 잔액이 변경된다. 아래는 잔액 1000원 증가
		ac2.deposit(1000);
		System.out.println(ac2.getBalance()); //11000 출력
		
		//출금을 하면 잔액이 변경된다. 아래는 잔액 2000원 감소
		ac2.withdraw(2000);
		System.out.println(ac2.getBalance());
		
		//print() 메소드를 호출하면 전체 정보가 출력된다.
		//아래는 "번호:2 이름:이영희 잔액:9000"라고 출력된다.
		ac2.print();
	}

}

[SCIT마스터 작문] 2017年10月2日

같은 수입이 있다면, 대기업의 일원으로서 일하는 것과, 독립하여 일하는 것, 어느 쪽이 좋다고 생각합니까? 이유는 무엇입니까?

일러두기

  • 이 주장은 논리의 전개를 위해 선택되었으므로, 자신의 견해와 일치한다고 볼 수 없습니다.
  • 일본어를 먼저 쓴 다음 한국어로 번역되었습니다.

작문

저는 같은 수입이 있다면, 대기업의 일원으로서 일하기보다는 독립하여 일하는 것이 좋다고 생각합니다. 대기업에서 일하는 것이 독립해서 일하는 것보다 좋지 않은 점도 있는 것입니다.

왜냐하면, 독립해서 일을 하면 일의 순서와 휴식 시간 등을 스스로 결정할 수 있기 때문입니다.

물론, 대기업에서 연금도 더 받을 수 있고, 수입 이외의 장점도 있다고 보여집니다만, 이것은 개인뿐 아니라 사회 전체적으로 봐도 역설적인 부분입니다.

그러므로, 저는 독립해서 일하면서 자신을 속박하지 않는 생활을 지향합니다.

감상

동어 반복이 너무 많아서 힘듭니다. 읽으면서도 부끄러웠습니다.