Skip to content

Commit 4e71b81

Browse files
committed
feat: Upgrade sorting
post: add
1 parent 7878f16 commit 4e71b81

7 files changed

Lines changed: 193 additions & 40 deletions

File tree

content/개발 회고/나의 블로그 유목민 역사.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,19 @@ Go 언어를 공부하면서 문득 이런 생각이 들게 되었다.
286286
Go 언어를 배우고 있는지라, 이론을 체화하는데에도 매우 큰 도움이 될 것 같아
287287
블로그 정적 빌더를 만들게 되었다.
288288
디자인은 이미 만들어 놓은 것이 있어 순조롭게 개발되었다.
289-
그리고 로직 부분은 시대가 시대인지라, 생산적인 측면이라고 판단되는 것은
289+
그리고 로직 부분은 시대가 시대인지라, 생산(product)적인 측면이라고 판단되는 것은
290290
LLM을 사용했고, 핵심적인 로직은 내가 직접 구현했다.
291291

292+
> 그러나 이번 프로젝트르 하면서, 내가 모르는 Golang 개념이 너무 많았다.
293+
> 그래서 조금은 LLM을 남용한 측면이 있는 것 같다.
294+
> 그래서, 나는 Golang을 더욱 더 배운 후, 나의 블로그를 코드 리뷰 및 리펙토링 하고자한다.
295+
> 아직은 내가 작성한 코드임에도 불구하고, 이해하지 못하겠다.
296+
> (이해하지 못한 것은 정보가 아니다.
297+
> 왜냐하면 '정'이 없기 때문이다.
298+
> 그러므로 필히 이해해야 한다.)
299+
> Interface 까지는 학습해야 온전히 나의 코드를 이해할 수 있을 듯 하다.
300+
> Golang을 마스터하여, 나의 코드를 이해하는 그 날이 꼭 오기를 기원한다.
301+
292302
내가 구현한 로직은 여러 로직이 있지만,
293303
중요한 것들만 소개해보자면,
294304
PostsData로 데이터 중앙화를 했고
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
date: 2025-08-24
3+
category: [에세이]
4+
published: true
5+
fixed: false
6+
---
7+
8+
우리는 현재 AI 이데올로기 시대를 살고 있다.
9+
AI에 대한 이야기들은 매일 같이 쏟아지고,
10+
AI에 대한 기술도 매일 같이 쏟아진다.
11+
뉴스, 책, 블로그, 인터넷, 면접, 프로그래밍, ...
12+
어떤 분야든지 AI로 점철되어 있다.
13+
사람들은 AI에 대해 말하며, 소비한다.
14+
사람들은 AI가 만든 것을 이용하고, 소비한다.
15+
16+
나는 AI 이데올로기 시대에 한 가지 새로운 관점을 논해보고자 한다.
17+
바로 '완벽주의의 종말'이다.
18+
우리는 항상 완벽주의를 향해 달려왔다.
19+
완벽한 자기소개서, 완벽한 코드, 완벽한 블로그, 완벽한 풀이, ...
20+
그러나, AI가 출현한 이상 완벽한 것은 모두 AI가 작성해준다.
21+
그렇다면, 우리 인간은 도대체 왜 필요한 것인가?
22+
23+
> 이 총장은 “100년 후 인간은 현재 존재하는 인류와 달라져 있을 것”이라며 “인간의 역할과 위상 등을 두고 존재론적 질문에 빠질 수밖에 없다”고 말했다. 현재는 인간의 존재와 역할이 일치하는 시대로 ‘문명의 주인’ 역할을 하지만, 앞으로는 인간이 존재와 사유의 주체이되 역할이 사라질 수 있다고 봤다. 그는 “AI로 인간의 존재와 역할이 부조화가 일어난다”고 말했다.
24+
> 출처: 경향포럼 2025
25+
26+
정말, "인간의 존재와 역할이 부조화"가 실현되고 있는 것이다.
27+
우리는 AI가 생성한 산출물을 현실에 출력하는 존재 밖에 되지 않을 것이다.
28+
그렇다면, 우리는 왜 "AI가 생성한 산출물을 현실에 출력"하고 있는가?
29+
왜냐면, 우리가 완벽주의를 추구하기 때문이다.
30+
완벽한 자기소개서를 원하기 때문에 AI에게 의탁하는 것이고,
31+
완벽한 코드를 원하기 때문에 AI에게 의탁하는 것이다.
32+
33+
AI가 출현한 이상, 완벽한 산출물은 이제 아무 쓸모가 없다.
34+
AI 시대 쓸모 있는 것은, 인간적인 것이다.
35+
조금 문법이 틀린 자기소개서가 완벽한 자기소개서보다 낫고,
36+
조금 느린 코드가 완벽한 코드보다 나으며,
37+
조금 장황한 블로그가 완벽한 블로그보다 낫다.
38+
39+
나는 현재 AI 이데올로기 시대가,
40+
인간이 출현한 이래로 가장 많은 기회가 주어진 시대라고 생각한다.
41+
드디어 '완벽주의'라는 틀에 갇히지 않아도 되기 때문이다.
42+
실수를 용인하는 등의 인간적인 것에,
43+
진정 사람들이 관심을 보여주기 때문이다.
44+
AI 이데올로기는 한 편으로 인간적인 세상의 진정한 시작이라고 볼 수 있다.
45+
'완벽하지 못함'에 두려워하지 말라.
46+
대신, '사회학'적이지 못함에 두려워 하라.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
date: 2025-10-02
3+
category: [에세이]
4+
published: true
5+
fixed: false
6+
---
7+
8+
## 이해하라
9+
생성형 AI를 사용함에 따라 기술 부채가 늘어난다고 한다.
10+
생성형 AI가 나오기 전에도 프로그래머는 일종의 복붙이라는 것을 통해 코딩하곤 했다.
11+
근데 왜 그때는 기술 부채가 지금보다 적었는가?
12+
나는 이 이유를 이해로부터 찾았다.
13+
과거 복붙의 시대에는 복붙할 코드가 결함이 있다는 전제로 활용하였기에
14+
대부분 개발자가 필수적으로 그 코드를 이해하려고 시도했다.
15+
그리고 복붙할 코드는 나의 코드와 호환이 거의 안되기 때문에
16+
필수적으로 이해해서 수정해야 했다.
17+
그러나, LLM의 시대에는 생성된 코드가 나의 코드에 바로 호환이 되기 때문에
18+
개발자들이 굳이 수정하지 않아도 되므로 이해하려는 시도조차 하지 않는 것이 태반이다.
19+
그리고 대부분의 개발자들은 자신들보다 AI가 생성한 코드가 더 낫다고 판단하는 경향이 있기 때문에
20+
생성된 코드가 결함이 있음을 딱히 걱정하지 않는다.
21+
생성된 코드에 버그가 나도 그냥 LLM에게 욕을 하고 다시 생성을 기다리지,
22+
코드를 이해하려고 하지 않는다.
23+
그냥 이해하면 바로 해결될 문제인데, 왜 다시 또 LLM에게 질문하는 것인가?
24+
어찌 보면 AI를 사용함에 따라 버그가 늘어나는 것은 당연한 것이다.
25+
당신이 보는 코드가 무슨 동작을 하는지도 모르는데, 어떻게 오류가 나는지 안나는지 알겠는가?
26+
결론적으로, 예전에는 코드를 이해했지만, 지금은 이해하지 않는다는 것이다.
27+
제발 코드를 이해하라.
28+
29+
## 남용하라
30+
LLM을 사용하면 개발 실력이 낮아질 수 있다는 우려들이 있다.
31+
나도 최근까지는 이렇게 생각했다.
32+
그러나, 큰 오산이었다.
33+
LLM을 사용해서 개발 실력이 낮아지는 것이 아니라,
34+
LLM이 생성한 코드를 이해하지 않아서 개발 실력이 낮아지는 것이다.
35+
LLM의 사용 유무는 당신의 개발 실력에 아무런 상관이 없다.
36+
LLM을 사용해서 개발하는 것은, 나의 실력을 증진시킬 수도, 아닐 수도 있다.
37+
맞는 경우는 LLM이 생성한 코드를 모두 이해했을 때이고,
38+
아닌 경우는 LLM이 생성한 코드를 이해하지 않았을 경우이다.
39+
왜 복붙은 왜 거부감이 들지 않고, 완전한 나의 실력으로서 느껴지는 것인가?
40+
왜 LLM을 써서 코딩하는 것은 아직도 거부감이 들고, 나의 실력으로 생각되지 않는 것인가?
41+
이것 또한 바로 코드의 이해와 연관이 있다.
42+
이해하지 않았으니까 나의 실력으로 생각되지 않는 것이다.
43+
예전에는 이해했으니까 나의 실력으로 판단되었던 것이다.
44+
복붙의 시대일 때도, 이해하지 않은 코드를 사용할 때면 내 실력이 아니라고 생각하곤 했다.
45+
그러나, 지금 LLM의 시대에서는 그런 빈도가 매우 잦아졌다는 것이다.
46+
LLM은 마음껏 써도 된다.
47+
LLM은 남용할 정도로 써라.
48+
그러나, 한 가지 명심해야 할 것은
49+
LLM을 통해 생성된 모든 지식을 이해하라.
50+
이해하기 귀찮은가?
51+
그러면 제발 LLM을 쓰지 말라.
52+
그냥 복붙을 해라.
53+
복붙하는 것이 당신의 역량에도 좋다.
54+
55+
## 기계일 뿐이다
56+
LLM을 쓸 때는 기계라고 생각하고 써라.
57+
생성형 AI를 인격체로 보아야 한다는 말도 있는데,
58+
그것은 LLM의 핵심을 몰라서 하는 말이다.
59+
LLM의 핵심은 트렌스포머 다음 단어, 문장 예측이다.
60+
이것이 무슨 인격체인가?
61+
생성형 AI는 지능은 있으나, 인격은 없다.
62+
한낱 기계일 뿐이다.
63+
그러니 기계처럼 사용하라.
64+
왜 LLM을 사람처럼 대하는 건가?
65+
당신은 망치를 쓸 때 계속해서 '감사합니다'라고 말하면서 자르는가?
66+
당신은 컴퓨터를 쓸 때 계속해서 '정말 고맙습니다'라고 생각하면서 쓰는가?
67+
근데 왜 당신은 LLM한테는 과도한 충성심을 보여주는가?
68+
LLM은 그냥 기계일 뿐이다.
69+
그들에게 있어서 감정적 표현은
70+
쓸데없는 입력값일 뿐이다.
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
date: 2022-06-05
3-
desc:
4-
category: [클린 코드]
3+
category: [에세이]
54
published: true
65
fixed: false
76
---

lib/is_korean.go

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/sort.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package lib
2+
3+
import "unicode"
4+
5+
const (
6+
typeNumber = iota
7+
typeKorean
8+
typeEnglish
9+
typeOther
10+
)
11+
12+
func getCharType(r rune) int {
13+
if unicode.IsDigit(r) {
14+
return typeNumber
15+
}
16+
if r >= '가' && r <= '힣' {
17+
return typeKorean
18+
}
19+
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') {
20+
return typeEnglish
21+
}
22+
return typeOther
23+
}
24+
25+
// CompareStrings는 두 문자열을 '숫자 -> 한글 -> 영어' 순서 규칙에 따라 비교합니다.
26+
// a가 b보다 앞에 와야 하면 true를 반환합니다.
27+
func CompareStrings(a, b string) bool {
28+
runesA := []rune(a)
29+
runesB := []rune(b)
30+
31+
lenA := len(runesA)
32+
lenB := len(runesB)
33+
34+
minLen := lenA
35+
if lenB < minLen {
36+
minLen = lenB
37+
}
38+
39+
for i := 0; i < minLen; i++ {
40+
runeA, runeB := runesA[i], runesB[i]
41+
typeA := getCharType(runeA)
42+
typeB := getCharType(runeB)
43+
44+
if typeA != typeB {
45+
return typeA < typeB
46+
}
47+
if runeA != runeB {
48+
return runeA < runeB
49+
}
50+
}
51+
52+
return lenA < lenB
53+
}

main.go

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import (
2323

2424
// TODO: post에 Thumnail 추가 -> header hero 처럼
2525

26+
// FIX: fixed된 게시물 이름순으로 하기. -> Q: 힙하게 힙하게 가 똑같으면 어떻게 비교를 수행하는가?
27+
// FIX: fixed, category 이름 순에 숫자->한글->영어 순으로 하기
28+
2629
func main() {
2730
// Get env
2831
var appEnv string = os.Getenv("APP_ENV")
@@ -402,17 +405,10 @@ func main() {
402405
for category := range postsDataByCategory {
403406
categories = append(categories, category)
404407
}
405-
sort.Slice(categories, func(i, j int) bool {
406-
keyI := categories[i]
407-
keyJ := categories[j]
408-
isKoreanI := lib.IsKorean(keyI)
409-
isKoreanJ := lib.IsKorean(keyJ)
410-
411-
if isKoreanI != isKoreanJ {
412-
return isKoreanI
413-
}
414408

415-
return keyI < keyJ
409+
// 목록 Sort
410+
sort.Slice(categories, func(i, j int) bool {
411+
return lib.CompareStrings(categories[i], categories[j])
416412
})
417413

418414
for _, category := range categories {
@@ -429,7 +425,7 @@ func main() {
429425
postList = append(postList, fmt.Sprintf("<h2 class=\"category-group-title\"><a href=\"%s\">[%s]</a></h2>", categoryLink, category))
430426
postList = append(postList, "<ul class=\"category-group-list\">")
431427

432-
// 정렬: fixed, date
428+
// fixed 정렬
433429
sort.Slice(posts, func(i, j int) bool {
434430
postI := posts[i]
435431
postJ := posts[j]
@@ -444,15 +440,7 @@ func main() {
444440
if fixedI {
445441
titleI, _ := postI["title"].(string)
446442
titleJ, _ := postJ["title"].(string)
447-
448-
isKoreanI := lib.IsKorean(titleI)
449-
isKoreanJ := lib.IsKorean(titleJ)
450-
451-
if isKoreanI != isKoreanJ {
452-
return isKoreanI
453-
}
454-
455-
return titleI < titleJ
443+
return lib.CompareStrings(titleI, titleJ)
456444
}
457445

458446
dateI, _ := postI["date"].(string)
@@ -570,6 +558,7 @@ func main() {
570558
return
571559
}
572560

561+
// 정렬
573562
for category, posts := range postsDataByCategory {
574563
sort.Slice(posts, func(i, j int) bool {
575564
postI := posts[i]
@@ -579,16 +568,13 @@ func main() {
579568
if fixedI != fixedJ {
580569
return fixedI
581570
}
571+
582572
if fixedI {
583573
titleI, _ := postI["title"].(string)
584574
titleJ, _ := postJ["title"].(string)
585-
isKoreanI := lib.IsKorean(titleI)
586-
isKoreanJ := lib.IsKorean(titleJ)
587-
if isKoreanI != isKoreanJ {
588-
return isKoreanI
589-
}
590-
return titleI < titleJ
575+
return lib.CompareStrings(titleI, titleJ)
591576
}
577+
592578
dateI, _ := postI["date"].(string)
593579
dateJ, _ := postJ["date"].(string)
594580
return dateI > dateJ

0 commit comments

Comments
 (0)