토스 - 유난한 도전

 

책을 사게 된 동기

현시점 한국에서 가장 '프로덕트'를 잘 만드는 팀은 어디가 있을까? 에 가장 먼저 생각난 게 '토스'였다.

가장 프로덕트를 잘 만드는 팀은 프로덕트를 어떻게 만드는지, 어떤 방식으로 일하는지 궁금해졌다. 그래서 이승건 대표의 PO SESSION을 듣기 시작했고, 더 자세한 내용을 알고 싶어서 토스팀에서 발간한 <유난한 도전>을 구입해 보게 됐다.

 

책의 내용은 대단히 토스의 영웅서사를 담은 듯하다. 전쟁에서 승리한 국가가 남긴 역사서 한쪽 같은 느낌이랄까. 

 

토스의 시작과 고난, 극복의 이야기를 통해 내가 지난 몇 년간 일했던 팀에서, 왜 그렇게 어려움들이 있었는지, 왜 그때 그 문제를 해결하지 못했는지를 깨닫게 되었다. 그냥 토스가 알고 싶어서 산 책이, 내 과거에 대한 회고를 하게 해 준 좋은 책이었다.

 

그 이야기를 부분 부분 여러 레슨런으로 나눠서, 내용을 발췌해서 조금씩 적어두려고 한다.


 

"사람들이 오프라인 만남을 앱에 기록하고 싶을 것이라는 첫 번째 가설이 틀렸다는 사실을 인정하지 못했다"

PO로 일하면, 스스로는 계속 확신을 가져야만 한다. 내가 가설을 가지고 타인을 설득하고, 실험하고 깨지고를 반복해야 하기 때문이다. 그렇기에 스스로 갖게 되는 '확신'이 굉장히 위험한 것인데, 이승건대표도 같은 단계를 거친듯하다. 내가 생각하는, 상상하는 세상은 정확하게 내 머릿속에만 있을 가능성이 높다. PO는 내가 생각한 가설을 감히 확신하지 않아야 한다. 그럴 수도 있겠다, 하지만 틀릴가능성이 더 높다.라고 전재해야 위험한 판단을 지양할 수 있다.

 

EO의 클래스 101 대표 인터뷰 영상을 보면, 처음 PMF를 찾은 순간 "드디어 우리가 시장에 왔어"라는 말이 나온다. 팀이 가지고 있었던 여러 가설 중에 한 가지가 실제 마켓에, 고객에게 워킹한 그 순간의 짜릿함 환희를 표현한 것이다. 여기서 '드디어'라는 말을 통해서 우리는 그 어려움을 예상할 수 있다. 

 

나의 생각이 고객에게도 동일하게 있을 가능성은 0에 가깝다. 그렇기에, 항상 의심해야 하고, '무조건'이라는 과한 확신을 지양해야 한다. PMF를 찾는 팀이라면, 우리는 언젠가 '드디어' 그곳에 도착하게 될 것이기 때문이다. 오히려 너무 쉽게 도착하게 되면 옳게 도착한 것이 맞는지 의심해 보는 게 건강할 것 같다.

 


 

책링크는 쿠팡 파트너스 링크입니다. 쿠팡 파트너스 링크를 통해 제품을 구입할 경우, 소정의 수수료를 부여받습니다. 

블로그를 운영하는 원동력으로 사용되며, 쿠팡 파트너스 링크와 글의 내용은 이해관계가 없습니다.

 

나는 원래 목표를 잘 세우는 편이 아니다. 

그 이유는 목표를 세워봐야 잘 이뤄지지도 않고, 목표를 계속 바꾸고 스스로 합리화하는 과정들이 더 피로했기 때문이다.

 

그런데 올 2023. 09. 오랜만에 목표를 세웠다. 내용은 '수익 증대'였다. 

목표를 세우지 않기로 스스로 약속(?) 했던 내가 목표를 세우게 된 이유는 아이러니하게도 목표가 생겨서였다.

조금 더 구체적으로는, 얻고자 하는 바가 생겼고 단기간에 얻을 수 없으니 구체적인 이니셔티브를 세운 것이다. 

 

어쩌면 이제까지 내가 목표를 세우지 않는 것을 고집했던 것은, 취하고 자하는 바가 없었거나, 정신적으로 피로했기 때문 일지 모르겠다. 

 

수익증대 하기 위해서 아래의 이니셔티브들을 나열했다.

 

모든 것은 수익을 증대시키는 하나의 골에 맞춰져 있었고, 장/단기적으로 사이드프로젝트, 새로운 파이프라인 성장, 커리어 성장 이렇게 나눠져 있었다. 

 

하지만 2023.12.31 기준으로, 14개의 이니셔티브 중 Done으로 완료한 것은 단 2개밖에 없다. 

가장 어려운 이직하기와 가장 쉬운 Social Media 만들기 단 두 가지뿐이다.

: 14%의 목표달성율이라고 할 수 있다.

 

그렇다면 나는 왜 14% 밖에 달성하지 못했을까? 원인을 생각해 보자.

 

1. 이직하기 하나의 목표를 달성하는 데에도 벅찼다.

같은 레벨로 14개가 작성되어 있지만 실제적으로 이직완료하기는 다른 것들보다 사이즈가 훨씬 컸고 들어간 공수가 사이즈가 달랐다. 

 

> 다음에는, 이니셔티브를 설정할 때, 그 태스크의 사이즈를 잘 고려해야 할 것 같다. 너무 큰 것은 더 적게 쪼개서 적어야 한다. 

 

2. 사실 이니셔티브들이 무엇이 있었는지도 아예 까먹었다.

연말 분위기가 물씬 나던 어느 날 나는 올해 뭐 했지? 뭔가 적어놨던 것 같은데?를 생각하게 된 그 순간 전까지 나는 이 이니셔티브들을 아예 기억하지 못했다. 

 

> 이니셔티브들을 계속 기억하고 내가 진행할 수 있도록 접근성을 높여야 할 것이다. 노션 홈 또는, 맥북/폰의 위젯으로 이니셔티브들의 진척상황을 노출시켜, 스스로 계속 인지할 수 있도록 한다.

 

3. 이니셔티브에 적어두지 않은 다른 것들을 했다.

이니셔티브에 적어두진 않았지만, 같은 목표를 위해서 했던 프로젝트들이 있다. 크진 않지만 유의미한 파이프라인이 되어주었다. 

이것도 결국 2의 문제에서 파생되었다고 생각한다. 

 

> 이니셔티브의 변동이 있을 때는 미리미리 반영해 두자. 실현/액션 가능성이 높은 이니셔티브를 적자.


오브젝트

 

2023년 하반기는 14% 밖에 안 되는 이니셔티브 달성율을 보였지만, 그것보다 많은 것을 취하고, 도전한 시간이었다.

2024년 한 해도 나에게 기억에 남는 것들이 많은 시간들이 되었으면 한다.

.

파이썬 혼자놀기 패키지 (무료 강의)

3일 차 - 수강 일자 210930

 

from wordcloud import WordCloud

text = ''
with open("kakaotalk.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    for line in lines:
        text += line

wc = WordCloud(font_path='/System/Library/Fonts/AppleSDGothicNeo.ttc', background_color="white", width=600, height=400)
wc.generate(text)
wc.to_file("result.png")

 

코드 설명

from wordcloud import WordCloud

워드클라우드 라이브러리를 사용한다.

 

text = ''
with open("kakaotalk.txt", "r", encoding="utf-8") as f:

    lines = f.readlines()
    for line in lines:
    text += line

text를 공란으로 만들어주고, kakaotalk.txt라는 파일을 오픈한다. (txt파일이라면 어떤 파일도 무방하다. 카카오톡 톡 내보내기를 통해 사용하는 것을 강의에서 권하고 있으나, 그럴 경우 csv파일로 export되어 적용이 안된다.)

kakaotalk.txt파일의 모든 줄들을 읽어서 한줄한줄을 text에 채워준다.

 

wc = WordCloud(font_path='/System/Library/Fonts/AppleSDGothicNeo.ttc', background_color="white", width=600, height=400)
wc.generate(text)
wc.to_file("result.png")

text에 워드클라우드 함수를 적용한다.

폰트를 설정하고, 백그라운드 컬러와 가로 세로 크기를 결정한다.

저장할 파일 명을 결정한다. result.png

 

🔥 이때 폰트 경로 설정이 중요하다.

아래의 코드를 통해 폰트들의 링크를 가져올 수 있다. 왜인지 모르게 ttf type의 폰트는 적용이 안돼서, ttc파일을 적용시켰다.

 

폰트 경로 가져오기

import matplotlib.font_manager as fm

for font in fm.fontManager.ttflist:
    if 'Gothic' in font.name:
        print(font.name, font.fname)

폰트 경로 출력 결과

Apple SD Gothic Neo /System/Library/Fonts/AppleSDGothicNeo.ttc
Hiragino Maru Gothic Pro /System/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc
Noto Sans Gothic /System/Library/Fonts/Supplemental/NotoSansGothic-Regular.ttf
AppleGothic /System/Library/Fonts/Supplemental/AppleGothic.ttf

위의 링크에서 /로 시작하는 폰트 링크를 복사해 위의 내용을 font_path에 넣으면 된다.

 

if, 혹시 폰트 경로만 출력하고싶다면 아래의 코드를 입력하면 된다.

import matplotlib.font_manager as fm

for font in fm.fontManager.ttflist:
    if 'Gothic' in font.name:
        print(font.fname)

 

출력 결과

.

결과를 보면 무의미한 내용이 엄청 많이 들어있다. ㅋㅋㅋ, hk 이런내용들이다.

여기서 무의미한 데이터들을 필터링해주는 데이터클리닝 과정을 진행한다.

 

데이터 클리닝

text = ''
with open("kakaotalk.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    for line in lines[5:]: 
        if '] [' in line: 
        text += line.split('] ')[2].replace('ㅋ','').replace('ㅜ','').replace('이모티콘\n','').replace('삭제된 메시지입니다','')

for line in lines[5:]:

5번째 줄부터 출력 (초반에 불필요한 메시지들 제외)

 

if '] [' in line:

사람들이 말한 경우만 포함하기 = 시스템 명령어 제거하기

파일 구조에 시스템 명령어들은 ] [를 포함하고 있지 않고, 사람이 말한 경우 "[말한사람이름] [시간] 말한 내용 "이렇게 돼서 위의 트릭으로 사람이 말한 경우만 포함 할 수 있다.

 

line.split('] ')[2]

파일 구조가 "ex. [정훈hk] [오후 5:10] 왜 우울한지 고르시오"이런식으로 생겨서 '] '를 기준으로 짜르면 text부분이 2순서에 위치함. 일종의 트릭

 

.replace('ㅋ','').replace('ㅜ','').replace('이모티콘\n','').replace('삭제된 메시지입니','')

위와 같은 이유와 목적으로 여러가지 무의미한 내용들을 삭제한다.

 

 

다시 워드클라우드

이렇게 클리닝된 내용을 기반으로 워드클라우드를 다시 해보자

from wordcloud import WordCloud

text = ''
with open("kakaotalk.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    for line in lines[5:]:
        if '] [' in line:
        text += line.split('] ')[2].replace('ㅋ','').replace('ㅜ','').replace('이모티콘\n','').replace('삭제된 메시지입니다','').replace('저두','').replace('저도','').replace('근데','').replace('나','').replace('아','')

wc = WordCloud(font_path='/System/Library/Fonts/AppleSDGothicNeo.ttc', background_color="white", width=600, height=400)
wc.generate(text)
wc.to_file("result4.png")

 

출력 결과

.

전보다는 훨씬 유의미한 내용들만 남은것을 볼 수 있다.

 

원하는 모양으로 워드클라우드

원하는 형태의 이미지를 import 해서 워드클라우드를 만들자

from wordcloud import WordCloud
from PIL import Image
import numpy as np

text = ''
with open("kakaotalk.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
    for line in lines[5:]:
        if '] [' in line:
        text += line.split('] ')[2].replace('ㅋ','').replace('ㅜ','').replace('이모티콘\n','').replace('삭제된 메시지입니','').replace('저두','').replace('저도','').replace('근데','').replace('나','').replace('아','')

mask = np.array(Image.open('cloud.png'))
wc = WordCloud(font_path='/System/Library/Fonts/AppleSDGothicNeo.ttc', background_color="white", mask=mask)
wc.generate(text)
wc.to_file("result_masked.png")

 

적용시킨 이미지 (cloud.png)

.

 

출력 결과

.

wordcloud 함수는 이미지상의 '검은색영역'에 워드클라우드를 만드는 것을 볼 수 있다.

 

다른 이미지

다른 이미지 출처 

 

위처럼 형태가 다른 이미지를 넣어서 적용할 경우

.

역시 검정 영역에 채워지는 결과를 볼 수 있다.

검정과 흰색의 대비가 애매한 이미지를 사용하면 위의 사각형과 동일한 결과를 낸다.

 

.


 

강의 회고록으로 이어집니다. 👇

(회고록 링크 추가예정)


스파르타 코딩클럽 5만 원 할인 쿠폰 링크 💵

아래 링크를 통해 가입하시면, 즉시 5만원 할인 쿠폰이 발급됩니다!

 

스파르타코딩클럽

왕초보 8주 완성! 웹/앱/게임 빠르게 배우고 내것을 만드세요!

spartacodingclub.kr

 

+ Recent posts