TIL

오늘 한 일

Move Zeroes 파이썬 문제풀이

어제 풀었던 Move Zeroes 문제에 파이썬 풀이도 추가했다. 파이썬으로 풀어보면서 리스트가 자바스크립트의 배열과 어떻게 다른지도 알아볼 수 있었다. 그리고 좀 신기했던 게 다른 사람 풀이를 보면서 또 찾아봤는데, 자바스크립트에서 분해대입이 아닌 이상은 변수를 콤마로 구분해 같이 선언하고 할당하는 게 안되는데, 파이썬에서는 가능하다.

1
2
3
const a = 1, b = 2; // 이것은 가능하지만
const a, b = 1, 2; // 이것은 불가능하다.
// SyntaxError: Missing initializer in const declaration

1
2
3
4
5
a = 1, b = 2 
# 이것은 불가능하지만
# SyntaxError: can't assign to literal
a, b = 1, 2
# 이것은 가능하다

좀 헷갈리기는 하는데, 다른 언어를 배우면서 비교해보는 것도 재미있다. 파이썬에서 내 기준 묘한 사용법을 보게되면, ‘어 이거 자바스크립트는 안되지 않나?’하면서 테스트해보고 비교해보니까 같이 공부가 된다.

You don’t know JS: 타입 정리

카일 심슨의 You don’t know JS를 보면서 내용을 정리하고 이전에 배웠던 내용을 정리하고 있다.
책을 읽으면서 정리하려고 했는데 번역이 조금 아쉬웠다. 예를 들면 ‘nullfalsy한 유일한 원시 값이지만, 타입은 object인 특별한 존재다.’라는 문장이 있었다. undefined0도 빈문자열도 다 falsy인 원시값인데 왜 저렇게 썼지 의문이 들어서 github에 올려져 있는 원문을 찾았다.

null is the only primitive value that is “falsy” (aka false-like; see Chapter 4) but that also returns “object” from the typeof check.

라고 되어있는데 이문장을 ‘nullfalsy이면서, typeof 체크에서 object를 반환하는 유일한 원시값이다.’라고 번역했어야 되지 않을까 싶다.(이문장도 매끄러운 번역인지는 잘 모르겠다. 부끄럽게도 영어를 잘 못한다…)
그래서 원문이랑 책을 번갈아 보기로 했다.
자바스크립트에 대한 이해가 없었을 때는 좀 어렵게 느껴진 책이었는데, 지금은 놓치고 있는 자바스크립트의 특성을 하나씩 짚어내면서 더 깊이 다지는 느낌으로 읽을 수 있게 되었다.

Share Comments

TIL

오늘 한 일

이력서 작성

이력서 작성하는 게 공부하는 것보다 제일 어려운 것 같다. 특히 자소서….

Move Zeroes 알고리즘 문제풀이

나는 이 문제에서 splice와 push 메서드를 빼면 원본 배열의 변형을 주면서 어떻게 풀 수 있을까 생각이 잘 안났는데, 내가 loop를 한번만 도는 것에만 집중해서 그런 것 같다. 다른 사람의 풀이를 보니 for문을 두번 사용했지만 메서드 없이 인덱싱만으로 풀어냈다. 그리고 2번째 for문은 0이 들어갈 자리의 개수만큼만 도니까 그리 비효율적이지도 않다.

Share Comments

Moved ZeroS

Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the non-zero elements.

Example:

  • Input: [0,1,0,3,12]
  • Output: [1,3,12,0,0]

Note:
You must do this in-place without making a copy of the array.
Minimize the total number of operations.

나의 풀이

JavaScript

원본 배열에 변형을 주는 splice() 메서드와 push() 메서드를 사용했다. 배열 요소가 0일경우 splice 메서드를 통해 해당 요소는 삭제하고 push 메서드를 통해 0을 배열의 뒤쪽에 추가해줬다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 68ms
var moveZeroes = function(nums) {
let i = 0, l = nums.length;
while(i < l) {
if(nums[i] === 0) {
nums.splice(i, 1);
nums.push(0);
l--;
} else {
i++;
}
}
};

Python

자바스크립트에서 푼 풀이방법으로 list의 메서드를 이용해 풀었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
l = len(nums)
for i in range(l):
if nums[i] == 0:
nums.remove(0)
nums.append(0)
l -= 1
else:
i += 1

count() 메서드를 통해 0인 요소의 개수를 세어 그만큼 for문을 돌리는 방법을 사용했다.

1
2
3
4
5
6
7
8
9
10
class Solution:
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
l = nums.count(0)
for i in range(l):
nums.remove(0)
nums.append(0)

다른 사람 풀이

JavaScript

0이 아닌 요소만 다시 배열에 순서대로 담아주고, index부터 총 길이까지 0을 추가해줬다.

1
2
3
4
5
6
7
8
9
10
11
12
13
var moveZeroes = function(nums) {
var index = 0
for (var i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[index] = nums[i];
index++;
}
}

for (var i = index; i < nums.length; i++) {
nums[i] = 0;
}
};

Python

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def moveZeroes(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
idx = 0
for i in range(len(nums)):
if nums[i] != 0:
nums[idx], nums[i] = nums[i], nums[idx]
idx += 1

자바스크립트에서는 객체와 변수의 분해대입이 아니라면 변수를 ,(콤마)로 구분해 값을 한번에 할당할 수가 없는데, 파이썬에서는 가능하다.

1
2
3
4
5
6
7
8
9
10
const a, b = 1, 2; // 이것은 문법적으로 허용되지 않고
// Uncaught SyntaxError: Missing initializer in const declaration

const a = b = 1; // 이것은 b가 전역 변수가 되기 때문에 좋은 방법이 아니다.

// 대신 다음과 같은 객체와 배열의 분해대입은 가능하다.
const [a, b] = [1, 2]

const obj = {a: 1, b: 2}
const {a, b} = obj

파이썬에서는 다음과 같은 방법으로 변수를 만들 수 있다.

1
2
3
4
5
a, b = 1, 2
a, b = (1, 2)
(a, b) = 1, 2
[a, b] = [1, 2]
a = b = 'python'

Share Comments

TIL

오늘 한 일

House Robber 알고리즘 문제풀이

프로그래머스의 땅따먹기 문제의 악몽이… 생각보다 어려워서 조금 시간이 걸렸다. 처음에는 막연히 filter랑 reduce 같은 걸 써야하나?라고 생각했는데 그보다는 더 복잡했다. 단순히 하나를 건너뛰는게 아니라 [2, 1, 1, 2]같이 0번째와 3번째가 아니라 0번째와 4번째의 조합이 가장 큰 수인 경우도 있어서 어떤 규칙을 찾아야했다.
leetcode에서 Dynamic Programming으로 분류되어 있길래 관련해서도 정리해봤다. 정리하면서 내가 쓴 방법이 메모이제이션임을 알게되었고 피보나치 수열을 예로 설명을 정리해보니 메모이제이션에 대해 이해가 되었다.

블로그 수정

  • 헤더, follow 버튼, 링크 컬러 수정
  • 하단 탑 버튼 디자인 수정

블록체인 이해하기

블록체인을 기반으로 하겠다는 기술도 기업도 많다. 내가 블록체인에 대해 알고 있는 것은 조작이 어려워 안전하고 익명이지만 추적가능하고 거래 투명성을 보장한다는 것 정도이다. 블록체인의 기술 구현보다 이 기술의 실효성에 대해 이해가 잘 안되어서 오늘은 관련 글을 이것저것 찾아서 읽어봤다.

읽으면서도 계속 의문점이 들었던 거는 블록체인의 본질이라고 할 수 있는 탈중앙화의 의미 때문이었는데, 어떤 곳에서 플랫폼을 제공하고 그 플랫폼에서 이루어지는 거래의 수수료를 떼는 구조라면 또다른 중앙화랑 뭐가 다른가 싶어서였다. 그런데 이 부분은 나는 경제와 권력의 관점에서 진정한 탈중앙화의 의미에 너무 치중해서 생각하고 있어서 그런 것 같다. 데이터의 분산과 그에 따라 더 보안을 보장할 수 있는 것, 그리고 기여자들에게도 그 대가가 돌아가는 구조라는 점에서 효용성을 봐야할 것 같다. 그리고 또 하나는 속도인데… 이거는 EOS에 대해서도 좀 더 찾아봐야겠다.


drafts에 글 배포 잊지말자;;

Share Comments

House Robber

leetcode 문제링크

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

  • Input: [1,2,3,1]
  • Output: 4
  • Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
    Total amount you can rob = 1 + 3 = 4.

Example 2:

  • Input: [2,7,9,3,1]
  • Output: 12
  • Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
    Total amount you can rob = 2 + 9 + 1 = 12.

나의 풀이

문제에 주어진 배열이 [1, 2, 3]이라고 했을 때 1 + 32를 비교하게 되고, [1, 2, 3, 4]일 경우는 1 + 32 + 4를 비교하게 되는데 그러면 홀수번과 다음 수를 비교할 때는even = Math.max(1 + 3, 2)이 되고, 짝수번의 요소와 다음 수를 비교하면odd = Math.max(4, 2 + 4)가 된다. 이런 규칙을 이용해서 푸는데, 만약 빈배열이거나 요소가 1개일 경우를 위해evenodd`는 0을 기본값으로 할당해줬다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// 60ms
var rob = function(nums) {
let even = 0;
let odd = 0;
for (let i = 0; i < nums.length; i++) {
if (i % 2 === 0) {
even = Math.max(even + nums[i], odd);
} else {
odd = Math.max(even, odd + nums[i]);
}
}
return Math.max(even, odd)
}

예전에 푼 프로그래머스 땅따먹기 문제랑 비슷한 것 같다. 이것도 너무 오래 걸렸다. 이런 유형의 알고리즘을 Dynamic Programming(DP)이라고 하는 것 같다.

다른 사람 풀이

빈배열, 배열 요소가 하나일 때, 2개 일때는 따로 값을 반환하고, 3개 이상일 경우부터 n: Max(n+s(n-2), s(n-1))같은 규칙을 따른다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var rob = function(nums) {
// 1: 1
// 1,2: Max(1, 2)
// 1,2,3: Max(3+s([1]), s([1,2]))
// 1,2,3,4: Max(4+s([1,2]), s([1,2,3]))
// n: Max(n+s(n-2), s(n-1))
if(!nums.length) {
return 0;
}

if(nums.length === 1) {
return nums[0];
}

if(nums.length === 2) {
return Math.max(nums[0], nums[1]);
}

const dp = [];

dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
// dp[2] = Math.max(nums[2] + dp[0], dp[1]);

for(let i = 2; i < nums.length; i++) {
dp[i] = Math.max(nums[i]+dp[i-2], dp[i-1]);
}

return dp[dp.length - 1];
};

Dynamic Programming(DP)

동적 프로그래밍

문제를 여러 개의 하위 문제로 나누어 푼 다음, 그것을 결합하여 최종적인 목적에 도달하는 방법으로 하위 문제의 값을 저장해두어(memozation) 그 하위 문제를 반복해서 풀어야 하는 경우 다시 계산하지 않고 재사용하는 식으로 계산 횟수를 줄일 수 있다.

모든 방법을 일일이 검토해 그 중 최적의 풀이법을 찾아내야 하기 때문에 최적의 방법(혹은 최단 경로)를 찾아내기 위한 시간이 걸리지만 그 결과는 가장 최적의 방법(최단 경로)라고 장담할 수 있다.

이를 이용한 알고리즘으로 최장 공통 부분 수열, 벨만-포드 알고리즘, 배낭문제 등이 있다.

피보나치 수열 문제의 경우 재귀적으로 다음과 같이 풀 수 있다.

1
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233...

1
2
3
4
const fibo = (n) => {
if (n <= 1) return n;
return fibo(n - 1) + fibo(n - 2);
}

이 경우 fibo(5)를 구할 경우 다음과 같이 계산되는데, fibo(n)이 중복되어 계산되는 부분이 있어서, 전체적인 계산 속도를 떨어뜨린다.(이 알고리즘의 시간 복잡도는 지수함수가 된다.)

  • fibo(5)
  • fibo(4) + fibo(3)
  • (fibo(3) + fibo(2)) + (fibo(2) + fibo(1))
  • ((fibo(2) + fibo(1)) + (fibo(1) + fibo(0))) + ((fibo(1) + fibo(0)) + fibo(1))
  • (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

이를 계산했던 값을 저장하는 메모이제이션을 이용해 동적 프로그래밍 방법으로 풀어본다면 다음과 같이 풀 수 있다. 이렇게 하면 중복되는 계산이 줄어든다.(시간 복잡도는 O(n)이 된다.)

1
2
3
4
5
6
7
8
9
10
11
12
const fibonacci = (n) => {
const memo = {0: 0, 1: 1};
const fibo = (n) => {
if (n <= 1 || memo[n]) {
return memo[n]
} else {
memo[n] = fibo(n - 1) + fibo(n - 2);
return memo[n];
}
};
return fibo(n);
}


참고

Share Comments

TIL

오늘 한 일

Jest 공부하기

자료구조를 만들어보면 테스트를 어떻게 할 지 고민을 했다. 처음에는 HTML 파일을 만들어서 script로 넣어서 콘솔에 넣을까 생각했다. ES6를 사용하니까 babel과 parcel 문서를 보고 환경을 만들다가 javascript-algorithm 처럼 테스트 환경을 만들어 보는 게 나을 것 같아서 Jest로 테스트 환경을 만들기로 했다.

Jest 문서의 Getting Started를 참고해서 sum 함수를 테스트 해보려다가 다음과 같은 에러가 발생했다.

SecurityError: localStorage is not available for opaque origins

Jest 깃헙의 이슈를 참고해서 package.json에 다음과 같이 testURL값을 http://localhost/ 로 해서 jest 설정 부분을 추가했다. 해당 옵션은 ‘jsdom’환경의 URL을 설정한다고 한다.

1
2
3
4
5
6
{
"jest": {
"verbose": true,
"testURL": "http://localhost/"
},
}

이 부분은 jest.config.js파일을 만들어서 다음과 같이 추가해도 된다.

1
2
3
4
module.exports = {
verbose: true,
testURL: "http://localhost/"
};

verbose는 테스트 결과를 자세히 보고할 지 여부인데 기본값이 false라서 같이 추가해줬다.

영어학원 등록

나는 외국을 안 나갈거니까 영어 따위는 필요없다고 호기롭게 말했던 학생때의 나를 때려주고 싶다. 사실 개발을 하게 될 줄도 몰랐지만… 영어와 뗄래야 뗄 수 없는 관계가 될 줄도 몰랐다.
개발 공부하면서 영어 공부의 필요성을 무지막지하게 느끼고 있다. 아직까지는 수능영어 공부할 때와 공무원 영어 공부하면서 얻은 독해 실력과 구글 번역기로 연명하고 있는데, 좀 더 빨리 읽고 싶고, 의미를 더 잘 이해하고 싶고 무엇보다 자막없는 컨퍼런스 영상을 이해하고 싶다. 그리고 커밋 메시지 비문없이 영어로 적고 싶다!

Share Comments

TIL

오늘 한 일

자료구조 연결리스트 풀이

연결리스트 설명부분만 먼저 보고, leetcode에 관련 문제가 있어서 먼저 구현해봤다. 연결리스트 설명이 블록체인에 대해 유튜브에서 간단히 설명했을때의 구조와 비슷한 것 같아서 흥미로웠다.
처음에 설명만 읽어서는 배열 안에 넣어야하나라고 생각했다. 그런데 배열 자체가 이미 push, pop을 할 수 있고, 인덱스로 해당 값을 구할 수 있다. 그래서 ZeroCho님의 블로그에서의 설명을 더 참고했다. 자바스크립트는 이미 배열로 연결 리스트가 구현되어 있어서, 객체로 만들어본다고 했다. 거기서 아이디어를 얻어서 leetcode 문제를 바탕으로 풀어봤다. 풀이는 github TIL 레포지토리에 올렸는데 좀 더 정리되면 블로그에 올려야겠다.

Share Comments

keyboardRow

leetcode 문제링크

Given a List of words, return the words that can be typed using letters of alphabet on only one row’s of American keyboard like the image below.

Example 1:

  • Input: [“Hello”, “Alaska”, “Dad”, “Peace”]
  • Output: [“Alaska”, “Dad”]

Note:

  • You may use one character in the keyboard more than once.
  • You may assume the input string will only contain letters of alphabet.

나의 풀이

every메소드를 써서 키보드 배열 중 모든 문자열이 속하는 배열이 있는 지 확인하는 부분에서 반복문을 쓸까 하다가 키보드 배열의 값은 변경될 일이 없을 것 같고 반복문 쓰면서 every의 반환값을 어딘가에 저장해두는 것이 더 좋은 방법 같지는 않아서 다음과 같이 풀었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 48ms
const keyboard = [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['Z', 'X', 'C', 'V', 'B', 'N', 'M'],
];

var findWords = function(words) {
return words.filter(item => {
const itemArr = item.toUpperCase().split('');
return itemArr.every(item => keyboard[0].includes(item)) ||
itemArr.every(item => keyboard[1].includes(item)) ||
itemArr.every(item => keyboard[2].includes(item));
})
};

정규식이랑 match() 메소드, some()메소드를 이용해 다른 방법으로 풀어보았다. result에 한번 match의 반환값을 저장할 필요가 있었는데, join()으로 다시 문자열 결합할 때, match의 반환값이 배열이 아니라 null일때도 있기 때문이다.

1
2
3
4
5
6
7
8
9
10
// 52ms
var findWords = function(words) {
const keyboards = [/[QWERTYUIOP]/ig, /[ASDFGHJKL]/ig, /[ZXCVBNM]/ig];
return words.filter(item => {
return keyboards.some(row => {
const result = item.match(row);
return result && result.join('') === item
});
})
};

다른 사람 풀이

정규식을 굉장히 잘 사용한 풀이인 것 같다. ^$을 이용해서 문자셋으로만 구성된 단어인지 여부를 RegExp test() 메소드를 통해서 bool값으로 반환하도록 했다.

1
2
3
4
5
6
7
8
9
10
11
12
var findWords = function(words) {
return words.filter((w) => {
// remove word from array if it fails matching all three rows
if (
!/^[qwertyuiop]*$/i.test(w) &&
!/^[asdfghjkl]*$/i.test(w) &&
!/^[zxcvbnm]*$/i.test(w)
) return false;

return true;
});
};

Share Comments

2018 장고걸스 서울 워크샵 후기

기다리던 장고걸스 서울 워크샵 소식이 올라왔을 때 기쁘면서도 걱정이 되었다. 나는 파이썬과 장고는 생소하지만, 프로그래밍을 전혀 모르는 사람은 아니며 퍼블리셔로는 3년을 일했는데 개발 입문자를 위한 이 워크샵에 당첨될 수 있을까? 그래서 참가 신청 때 개발 경험이 있는지 등을 묻는 질문지를 보면서 이거 살짝 뻥을 쳐야하는 건가 생각했다. 차마 그럴 수 없어서 매우 솔직하게 썼는데 ‘장고걸스에서의 경험을 나누고 싶고 깃헙을 관리하고 있고 개발 블로그도 운영하고 있습니다’라는 나의 어필이 통한 것일까 당첨이 되었다. (야호!)
그리고 스쿨 동기들에게도 슬랙으로 워크샵 소식을 공유했더니 몇분이 신청해서 같이 참여하게 되었다.

장고걸스 행사장 앞에 있는 배너

장고걸스는 개발 입문자가 가장 편안한 마음으로 참여할 수 있는 개발 행사이다.

2018년의 나의 다짐은 ‘마크업만이 아니라 스크립트도 잘 다루고 최신 프론트엔드 트렌드도 따라갈 수 있는 개발자가 되자’였다. 그래서 3년을 다녔던 웹 에이전시를 나오기로 했고, 눈여겨보고 있던 패스트캠퍼스의 프론트엔드 스쿨 과정을 등록했다. 마침 시기도 적절한 게 퇴사일과 학원 개강일 사이에 2주 정도의 텀이 있었다. 학원에서는 각종 개발 커뮤니티와 밋업, 컨퍼런스에 참여하기를 권장했고 실제로 그렇게 열심히 살아야만 이 시대의 개발자(적어도 내가 이상으로 삼았던 개발자)로 살아갈 수 있는 것 같았다. 일단 페이스북 그룹이나 슬랙에 가입했다. 커뮤니티가 다양한 만큼 종종 다양한 행사 소식도 올라왔다. 간단히 맥주를 마시면서 개발에 관한 얘기를 나눠보자는 모임부터 해마다 정기적으로 열리는 것 같은 컨퍼런스 소식까지 다양했다. 그런데 그 많은 행사 중에 어느 것 하나 선뜻 참여할 용기가 나지 않았던 이유는 내가 꿔다놓은 보릿자루같이 굴 것 같아서였다.

‘아는 사람 하나 없이 뻘쭘하게 있을 것 같아.’
‘대화하는데 내가 너무 몰라서 못 알아들으면 어떡하지?’
‘내가 너무 바보 같은 질문을 하면 어쩌지?’
‘입문자를 위한 모임은 없나?’

이런 나의 걱정을 해소해주고 편안한 마음으로 참여할 수 있는 개발 행사가 장고걸스 워크샵이었다.

장고걸스 워크샵에서 가장 좋았던 점은 워크샵 기간 동안 지켜줘야 할 점에 대해 알려주는데, 그중 참석자는 어떠한 질문이라도 (너무 기초적이라 바보같이 느껴질 것 같은 질문이라도) 할 수 있다는 것이다. 요즘은 개발 커뮤니티에서도 어느 정도 자정하는 분위기인데, 가끔 너무 기초적인 것을 물어보는 사람에게 그 정도도 검색해서 찾아보지 않으냐며 날카롭게 구는 사람들이 몇몇 있다. 모르는 사람의 가장 큰 어려움은 이 모르는 걸 어떤 방법을 써야 해결할 수 있는지조차 모른다는 것이다. 아는 사람들이야 ‘“구글”에 “영어”로 이런 “키워드”로 검색하면 다 나와’, ‘“stack overflow”에 가면 다 있어’라고 말하지만, 그것조차 모를 수도 있는 법이다. 실제로 나는 웹 쪽으로 전향하기 전, 우체국에서 일할 당시만 해도 크롬은 안 썼다. 검색은 모두 네이버를 통해 이뤄졌고 어릴 때는 익스플로러가 업데이트되어서 UI가 조금이라도 바뀌면 화를 냈었다. 내가 그 사람 옆에서 성장 과정을 계속 지켜보지 않은 이상은 상대가 어느 정도 알 것이라는 판단을 섣부르게 해서는 안 된다.

아무튼, 이런 나의 여과 없이 나오는 질문에도 친절히 알려주신 이재열 코치님께 감사드린다.

장고걸스에는 훌륭하고 친절한 코치님이 많이 계신다. 모른다고 걱정하지 말자

행사장에 딱 들어섰을 때 느낀 것은 ‘많다! 사람이 많다!!’였다. 파란 옷을 입은 워크샵 신청자도 많은데 흰옷을 입고 있는 코치님이나 검은 옷을 입고 있는 관계자분도 많았다. 조를 꾸려서 한 조에 신청자 3명 정도에 코치님이 1명 이상이 붙어서 진행하는데, 그렇게 구성된 조가 20팀 이상이었던 것 같다.
워크샵 첫날(7/20)은 7시에 시작되어 2시간 정도 파이썬을 설치하거나 에디터를 설치하는 것 같은 기본적인 개발환경을 세팅했다. 두 번째 날(7/21)에 본격적으로 장고걸스 튜토리얼을 따라 하면서 장고로 블로그를 만들었다. 우리 조는 나를 포함해 개발을 배워보셨거나 배우고 있는 분들이어서 어쩌다 보니 굉장히 빠르게 진행되어 심화 튜토리얼까지 진행해버렸지만, 중간중간 막히는 부분도 있었다. 나의 경우는 내가 찾을 수 없는 오류가 발생하는 경우거나 git에서 실수해버린 경우였는데 코치님이 팀 테이블 주위를 열심히 뛰어다니면서 문제가 발생할 때마다 같이 봐주시고 해결해주셨다. 그리고 블로그를 만들면서 개인적으로 파이썬 문법과 장고에 대해 어느 부분까지가 장고의 기능이고, 파이썬의 문법인지 궁금한 점을 여쭤봤는데 매우 친절하고 쉽게 알려주셨다.
특히 첫날에 MVC에 대해 설명해주셨는데, 사실 이전에는 MVC, MVVM 등의 아키텍처 패턴에 대한 이해가 많이 부족했다. 리액트는 뷰만 담당하는 라이브러리이고 앵귤러는 프레임워크다라는 설명을 들었을 때도 앵귤러에 대한 경험과 이해가 없다 보니 어떤 점이 다른 것인지 이해하기는 힘들었다. 관련해서 글을 찾아봐도 이해를 잘 못 했는데, 이재열 코치님의 설명을 듣고 장고걸스 튜토리얼을 따라 해 보면서 MVC 패턴이나 프레임워크란 것이 어떤 것인지 이해하게 되었다.

나의 첫 파이썬/장고 프로젝트

장고걸스 워크샵의 좋은 점은 내가 혼자서 한다면 몇 날 며칠이 걸릴지도 모르는 문제를 코치의 도움을 받아 빠르게 해결할 수 있다는 것이다. 혼자 공부하는 것에도 장점은 있다. 해결 방법을 찾는 과정 또한 공부일 것이고, 문제 해결 능력을 키울 수 있다. 해결했다는 성취감 역시 얻을 수 있다. 단점은 매우 많은 삽질을 해야 하고 엄청나게 시간을 낭비할지 모른다는 것이다. 이전에 장고걸스 튜토리얼을 따라 해보려다 포기한 이유는 튜토리얼 자체가 ‘이 정도는 아시죠?’ 같은 느낌이 없지 않아 있는 데다가 그 이 정도를 맞추기 위해 어디부터 공부해야 할 지 감이 안 잡히고, 오류 상황이 발생했을 때 그걸 풀 능력이 내게 부족해서 gulp와 Sass를 처음 익힐 때처럼 매우 고통의 시간이 될 것 같은 예감이 들어서였다. 그래서 스쿨과정이 끝날 때쯤에는 어느 정도 스크립트에 익숙해져 있을 테니 그때 다시 도전하자는 마음으로 일단 접어두었었다.
단순히 따라하는 것뿐이더라도 개발의 한 사이클을 경험해보고 결과물을 만들게 되면 앞으로의 공부에 많은 도움이 된다. 그런 점에서 장고걸스는 개발 입문자에게 (혹은 나처럼 파이썬/장고 입문자에게) 굉장히 좋은 기회인 것 같다.

마치며

오늘도 작문 실력을 늘려야겠다는 깊은 반성을 하며…
장고걸스 워크샵을 신청한 계기는 ‘잘 만들어진 튜토리얼을 제공한다해도 누구의 도움도 없이 생소한 언어와 생소한 기술을 사용해 보는 것은 굉장히 오랜 시간이 걸리니까 워크샵을 통해 코치님들의 도움을 받아 한 사이클을 빠르게 경험해보자’였다. 실제로 코치님의 도움으로 튜토리얼을 따라하는데 큰 어려움은 없었다. 장고의 일부를 경험한 것이지만 웹 프레임워크라는 것이 어떤 것인지 경험해 볼 수 있어서 그것만으로도 굉장히 유익했다.
그런데 그런 목표 성취 이상의 경험이었다. 세마나 형식의 컨퍼런스 외에 이런 소통을 통한 커뮤니티 행사에 처음 참여해 본 것이었고 나 스스로 이전과 다르게 외향적으로도 적극적인 사람이 되었구나를 느꼈다. 그리고 앞으로 개발 커뮤니티의 행사에 참여할 용기를 얻었다. 다음에는 장고걸스에 코치로 참여하는 것을 목표로 해야겠다.

장고걸스 굿즈가 탐이 난다면 다음 워크샵 신청...


Share Comments

TIL

오늘 한 일

엔트리

감기와 올해 4학년이 된 사촌동생이 함께 찾아왔다.(신난다) 자는 동안은 감기로 죽어있고, 깨어있는 동안은 열정적인 여동생과 놀아줘야했다. 다음주 내내 휴가를 낸 언니는 그것만 바라보며 약간 득도한 모양이다. ‘치킨차차’라고 기억력 향상에 매우 유익한 보드게임이 있는데, 아무도 나와 놀아주지 않아서 구석에서 썩고 있던 것을 사촌동생이 잘도 찾아내서 끝나지 않을 것만같은 꼬리잡기 릴레이를 했다.

동생의 흥미를 다른 곳으로 돌리기 위해 게임 만드는 거 좋아하냐는 질문으로 약을 팔면서 컴퓨터 앞에 앉혔다. 다행히 게임 만드는 게 재미있을 것 같다며 흥미로워 했다. 엔트리는 네이버에서 홍보할 당시에 소프트웨어적 사고력을 키워준대서 해봤었는데, 오랜만에 들어오니 많이 체계적으로 바껴있고 작품 공유하기에는 어린애들이 만든게 맞나 싶을 정도로 꽤 잘 만든 것도 있었다. 학습하기를 따라하도록 하고서 지켜봤는데, 학습용이라는 목적에 맞게 단계적으로 진행하도록 설명 팁이 계속 제공되었다.
학습하기 외에 작품만들기를 이용하면, 학습하기에서 학습했던 것을 토대로 자신만의 창의적인 작품을 만들어 볼 수 있는데, 이걸 봤다가 갑자기 모르는 UI가 급 보여지니까 어렵게 느껴졌는지 사촌동생의 흥미 역시 급 하락해버렸다…

액괴 영상에 밀려서 더이상 진행하지는 못했지만, 학습하기에서 반복문 안에 로직을 넣는 것이 나왔었는데, 이런 사고력을 어릴때부터 키운다면 나중에 다른 언어를 공부한다해도 크게 어려움이 없겠구나 생각되었다. 요즘 초등학생들은 이런 엔트리나 스크래치를 이용해서 코딩교육을 한다고 들었는데, 나중에라도 동생이 이쪽으로 흥미가 생기거나 필요하게 되면 나한테 도움을 구해줬으면 좋겠다. 그리고 꼭 개발자가 되고싶지 않더라도 경험이란 것은 앞으로의 선택에 중요한 밑거름이 되니까 도움이 되었으면 좋겠다.

갑자기 고등학생때 RPG 쯔꾸루로 게임을 만들어본다고 알지도 못하는 스크립트를 Ctrl + C / V 하면서 혼자 삽질했던 기억이…

Share Comments