코드트리 청약 통장 챌린지를 시작한 5월 초부터 오늘까지 매일 문제를 풀었다. 알고리즘 공부를 시작했다가 한 주 만에 멈추던 예전의 나를 떠올리면, 두 달이라는 숫자는 단순한 기간이 아니다.
같은 두 달을 코드트리에만 쓴 것도 아니다. SSAFY 16기 코딩테스트에 합격한 뒤 면접까지 마치고 결과를 기다리고 있다. 트레일 2의 시뮬레이션 Ⅰ, Ⅱ에 쌓인 49개의 풀이가 깃허브 레포 CHOOSLA/Algorithm에 그대로 올라가 있다.
5월 10일 첫 갭체크에서 빨강, 노랑이던 네 유형은, 6월 9일 두 번째 갭체크에서 약점 목록을 모두 졸업했다. 두 달 전엔 손도 못 댄 백트래킹 문제가 이번엔 한 번에 통과로 떴다. 매주 한 편씩 6편의 학습 후기를 썼다.
5월 10일의 본인과 6월 23일의 본인은 숫자로도 감각으로도 다른 사람이 되어 있었다. 7주 동안 한 주도 빠짐없이 매일 자리에 앉은 본인에게, 이번 글로 축하를 한 번 보내고 시작한다.
갭체크가 한 달의 학습 좌표를 그려 주었다
5월 10일, 첫 갭체크를 응시했다.
시뮬레이션 Ⅰ과 완전탐색 Ⅱ가 노란불(불안정)로 떴다. 완전탐색 Ⅲ와 백트래킹은 빨간불(부족).
백트래킹은 그래도 많이 풀어봤다고 자신하고 들어갔는데, 진단에서 15분 동안 두 번을 시도하고도 끝내 못 풀었다.
스스로 "구현이 약하다", "DP가 어렵다" 정도로만 막연히 잡고 있던 자기 진단이, 갭체크 결과 앞에서 구체적인 좌표로 다시 그려졌다.
어느 유형에서 시간을 쓰고, 어떤 자리에서 실수가 반복되는지를 한 화면으로 확인했다.
그제야 한 달의 학습 계획이 명확해졌다. 노란불 두 개를 트레일에서 직접 메우는 게 일차 목표였다. 빨간불 두 개는 노란불을 갈고 나면 자연스럽게 함께 풀리는 자리라고 보고, 트레일은 그다음 사이클로 미뤘다.
코드트레일 3단계로 약점을 좁혀나갔다
코드트레일의 3단계 기본 문제 → 연습 문제 → 테스트 문제 는 단순히 풀이의 순서가 아니라, 본인의 사고가 어디서 어긋나는지를 짚어 주는 자가 진단 장치에 가까웠다.
처음 이 구조를 체감한 순간은 시뮬레이션 Ⅰ의 한 테스트 문제였다.
본인 손으로 풀어내고 정답까지 받은 뒤 해설을 확인했더니, 해설은 변환 로직을 별도 함수로 분리해 두고 있었다. 본인 코드는 같은 로직을 main() 안에 그대로 풀어 적은 형태였다.
"맞히긴 했는데, 풀이의 구조가 제대로 된 풀이는 아니었다"는 자각이 거기서 처음 들었다.
기본 문제로 개념을 보고, 연습 문제에서 변형에 적용해 보고, 테스트 문제에서 본인 손으로 풀어낸 코드를 해설과 대조하는 흐름이라, 풀이 자체보다 사고의 결함이 더 분명하게 드러난다. 백준 시절에 익숙했던 "일단 많이 풀어보자"는 접근이 왜 자주 무너졌는지 이 구조 앞에서 보였다.
이 사이클을 시뮬레이션 Ⅰ → 완전탐색 Ⅱ → 시뮬레이션 Ⅱ 순서로 한 달 가까이 돌렸다.
쉬운 사이클은 아니었다. 알림톡으로 매일의 학습을 시스템에 맡기고, 깃허브 자동 연동으로 통과 시점마다 잔디를 채우게 만들지 않았다면 중간에 끊겼을 것이다.
코드트리 알림톡 카톡 화면
한 달 뒤 두 번째 갭체크에서 어떤 결과를 받게 될지는 알 수 없었지만, 매일 풀이는 멈추지 않았다.
1차 갭체크와 2차 갭체크 사이 — 가장 정확한 변화 세 가지
7주에서 가장 분명한 변화는 두 갭체크 결과 사이에 있다.
유형
1차 (5/10)
2차 (6/9)
시뮬레이션 Ⅰ
불안정(노랑)
약점 목록서 빠짐
완전탐색 Ⅱ
불안정(노랑)
약점 목록서 빠짐
완전탐색 Ⅲ
부족(빨강)
2분 45초, 1트 '훌륭'
백트래킹
부족(빨강), 15분 두 시도 실패
한 번에 해결
DP Ⅰ / BFS
—
새 '부족'(빨강)
코드트리 트레일 2 시뮬레이션 Ⅰ, Ⅱ 진행도 — 49문제 풀이 완료
숫자보다 더 인상적이었던 변화는 세 자리에 남아 있었다.
변화 ① — 백트래킹 한 문제
1차 응시 때, 15분을 붙들고 두 번 시도하다 빈칸으로 넘긴 그 문제.
2차에 다시 나왔다.
같은 유형인 걸 알아챈 순간 한 달 전의 막막함부터 떠올랐다.
이번엔 손이 먼저 움직였다. 한 번에 통과가 떴다.
점수판의 색이 빨강에서 빠진 것보다, "한 달 전엔 손도 못 댔는데 지금은 풀고 있다"는 감각이 더 분명한 신호였다.
변화 ② — 깃허브 옛 풀이와 트레일 2 풀이의 차이
깃허브 CHOOSLA/Algorithm/SW Expert Academy/1954/ 폴더 — answer.cpp , main.cpp , input.txt 가 한 폴더에 놓인 화면
SWEA 1954 달팽이 숫자 폴더에는 answer.cpp와 main.cpp가 같이 들어 있다.
한 번 틀린 뒤 정답을 옮겨 적고, 본인 코드로 다시 풀어 둔 자국이다.
옛 main.cpp도 방향 배열을 시계 방향({{0,1}, {1,0}, {0,-1}, {-1,0}}, 우-하-좌-상)으로 잡아 두긴 했다. 그러나 그 위에서 인덱스를 순환시키기 위해 별도의 헬퍼 함수를 정의해 사용했다.
// 옛 SWEA 1954 main.cpp — 시계 90도 회전을 위해 만든 헬퍼
int rotate(int num) {
num = num + 1;
if (num == 4) return 0;
return num;
}
...
direction = rotate(direction);
같은 회전이 코드트리 트레일 2를 풀고 나서는 한 줄로 끝났다. 모듈러 산술을 인덱스 순환에 직접 쓰는 사고, 그리고 문제 요구사항에 맞춰 방향 배열의 순서 자체를 새로 설계하는 사고 두 가지가 더해진 결과였다.
// [되돌아오기 2] — 모듈러로 시계 90도 회전
dir = (dir + 1) % 4;
[작은 구슬의 이동]에서는 방향 배열을 옛 코드와 다른 순서로 새로 잡았다. {하, 우, 좌, 상}. 이 순서에서는 반대 방향이 인덱스의 대칭 짝(0↔3, 1↔2)으로 떨어지기 때문에, 벽에 부딪힐 때의 반사는 3 - dir 한 줄로 끝난다.
// [작은 구슬의 이동] — 방향 배열을 {하, 우, 좌, 상}으로 설계해 반사를 인덱스 대칭으로 표현
int moving[4][2] = {{1,0}, {0,1}, {0,-1}, {-1,0}};
dir = 3 - dir;
[거울에 레이저 쏘기 2]에서는 좌회전이 필요했는데, 단순히 (dir - 1) % 4로 쓰면 C++의 음수 모듈로 때문에 인덱스가 음수로 튄다. (dir + 3) % 4로 적으면 같은 좌회전이 음수 분기 없이 한 줄로 끝난다.
// [거울에 레이저 쏘기 2] — 음수 모듈로 회피한 좌회전
dir = (dir + 3) % 4;
핵심은 두 가지였다. 모듈러 연산을 인덱스 순환에 직접 쓰는 사고, 그리고 문제마다 방향 배열의 순서를 다시 설계해 반사·회전을 인덱스 한 줄에 떨어지게 만드는 사고. 옛 코드에는 두 사고가 모두 없었다.
폴더에 나란히 놓인 두 풀이가 그 변화를 숫자보다 더 분명하게 증명하고 있다.
변화 ③ — 한 유형 전체를 한 줄짜리 골격으로 압축할 수 있게 됐다
마지막 한 달이 끝나갈 무렵, 시뮬레이션 Ⅰ의 [만나는 그 순간] 한 문제에 네 번 연속 Wrong Answer를 받았다.
코드트리 [만나는 그 순간] 채점 화면
한 번에 결과로 점프하려는 옛 손버릇이 두 달째에 들어와서도 같은 자리에서 같은 형태로 어긋났다는 사실이 그 화면에 그대로 떠 있었다.
이걸 한 풀이의 실수가 아니라, 시뮬레이션 유형 전체에 대한 사고 습관의 구멍으로 받아들였다. 그 자리에서 트레일 2의 시뮬레이션 Ⅰ, Ⅱ를 끝까지 풀기로 했고, 49개의 문제를 풀고 나서야 하나의 골격이 손에 잡혔다.
"상태를 정의하고, 시간을 1단위로만 전진시키고, 매 시각의 기록을 한 줄씩 적는다."
골격을 코드로 옮기면, 누적 시간을 가리키는 인덱스 idx를 1부터 증가시키면서 매 1초의 위치를 배열에 그대로 적어 두는 한 줄로 끝난다.
// [만나는 그 순간] — 시간 누적 인덱스 idx에 매 초의 위치를 받아쓰는 한 줄
int idx = 1;
for (int i = 0; i < n; ++i) {
for (int time = 0; time < t[i]; ++time) {
p1[idx] = p1[idx - 1] + (d[i] == 'L' ? -1 : 1);
idx++;
}
}
이 한 줄짜리 패턴이, 시뮬레이션이라는 유형 전체를 풀 수 있는 표준 골격이 됐다.
색이 빠진 자리와, 같은 문제를 한 번에 통과한 감각과, 한 유형을 한 줄로 압축하는 사고. 두 달 간의 학습이 만든 변화는 이 세 자리에 가장 정확하게 남아 있었다.
중간에 그만두고 싶었던 고비 — 매일 풀어도 나아지는지 안 보이던 한 주
7주 동안 가장 큰 고비는 3주차 무렵이었다.
이때는 5월 23일에 SSAFY 16기 코딩테스트를 치른 직후라, 불안함 속에서 결과 발표를 기다리던 시기였다.
코테에서 본인이 어느 자리에서 시간을 썼고 어떤 문제에서 손이 막혔는지를 떠올리면, 지금 트레일에서 풀고 있는 기본, 연습 문제들이 다음 실전 코딩테스트에서도 정말 도움이 될지 확신이 들지 않았다.
매일 잔디는 채우고 있었다. 그러나 모니터 앞에서 손이 멈추는 자리는 여전히 경계값 조건이나 인덱스 1 차이의 실수였다.
"이렇게 매일 조각 문제를 풀고 있는 게 정말 실력으로 쌓이고 있는 건가."
이 회의감이 며칠 이어졌고, 불안 속에서도 일단 잔디를 채우는 하루하루가 2주 가까이 이어졌다.
비결은 두 가지였다.
비결 ① — 시스템이 의지력을 대신했다
알림톡이 매일 저녁 카톡으로 학습 상태를 찔러줬다.
깃허브 잔디는 하루라도 빈칸이 생기면 시각적으로 도드라진다.
그만두려고 마음먹은 날에도, 이 두 신호는 본인의 의지와 무관하게 작동했다.
"오늘만 하나 풀자"가 되는 환경이 의지력의 부재를 메웠다.
비결 ② — 한 달 뒤 2차 갭체크에서 학습 결과가 숫자로 보였다
약점 4개가 한 달 만에 약점 목록에서 모두 빠졌다.
그 결과를 손으로 받고 나서야, "매일 풀고 있는 것이 숫자로 쌓이고 있다"는 사실이 눈에 들어왔다.
그 한 번의 숫자 확인이, 그 이후 3주를 의심 없이 채우는 데 충분한 연료가 됐다.
두 달 동안 만든 다섯 개의 시스템
의지력의 승리가 아니라 시스템의 승리라고 한 줄로 말할 수 있는 이유는 분명하다. 이 두 달 동안 다섯 개의 작은 시스템을 의식적으로 만들어 두었기 때문이다.
매일 자리에 앉히는 알림톡, 그 결과를 시각화하는 깃허브 자동 잔디, 틀린 문제를 다시 끌고 오는 북마크 오답 폴더, 한 유형의 풀이를 한 문장으로 정리한 시간 단위 시뮬 골격, 그리고 한 달 주기로 약점을 다시 진단하는 갭체크 사이클. 이 다섯이다.
#
시스템
작동 방식
1
알림톡
매일 저녁 카톡으로 학습 상태 전달. 의지력을 시스템에 맡김
2
깃허브 자동 연동
통과 시 자동 커밋. 빈 잔디는 시각적으로 도드라짐
3
북마크 오답 폴더 (4주차)
"한번에 못 푼 문제", "해설이 더 나았던 문제" 두 폴더
4
시간 단위 시뮬 골격 (6주차)
"상태 + 시간 1단위 전진 + 매 시각 기록" 한 줄 골격
5
갭체크 주기 점검
한 달마다 약점 진단 → 재교정 루프
북마크 - 해설이 내 풀이보다 나았던 문제북마크 - 한번에 못 푼 문제
이 다섯은 따로 작동한 게 아니라 톱니바퀴처럼 맞물려 돌아갔다. 알림톡과 잔디가 매일을 자동화하고, 북마크가 틀린 문제로 끌고 가고, 골격이 풀이의 사고 비용을 낮추고, 갭체크가 한 달마다 다음 전선을 가리키는 식이다.
1주차에 코드트리를 처음 켰을 때만 해도 머릿속에 없던 구조다.
의지력만으로 코테 공부를 시작하려다 첫 주에 멈춰본 적이 있는 사람, 며칠 풀다 며칠 비우는 패턴을 못 깨본 사람이라면, 이 다섯 중 1번과 2번부터 켜 보길 권한다.
본인의 의지보다 환경이 먼저 움직인다.
코드트리 외 성과 — SSAFY 16기 면접까지 마쳤다
두 달이 코드트리 챌린지에만 쓰인 시간은 아니었다.
5월 23일에 SSAFY 16기 코딩테스트를 응시해 합격했다.
6월 8일에는 면접까지 마쳤다. 지금은 그 결과를 기다리고 있다.
싸피(SSAFY) 코팅테스트 합격
이 두 흐름이 무관하지 않다.
SSAFY 코딩테스트 자체가 시뮬레이션과 완전탐색 비중이 큰 시험이다. 한 달간 트레일 2의 시뮬레이션 Ⅰ, Ⅱ를 갈고 있던 시기와 정확히 겹쳤다.
면접 다음 날인 6월 9일에 2차 갭체크를 다시 응시했다. 1차에서 빨강, 노랑이던 네 유형이 모두 약점 목록에서 빠진 결과가 그날 떴다.
면접의 긴장이 채 가시지 않은 자리에서 받은 객관적인 결과라, 한 달간의 학습이 어디까지 와 있는지가 가장 분명하게 잡힌 시점이었다.
코테 직전 한 달 동안 다듬은 시뮬레이션과 완전탐색의 풀이 흐름이, 시험장에서 시간 압박 속에 풀이 방향을 잡을 때 가장 자주 꺼내 쓴 자리였다.
두 흐름을 병행할 수 있었던 이유는 위의 다섯 시스템 덕분이었다.
알림톡과 잔디가 매일의 학습을 자동화해 두니, 의식적인 시간은 SSAFY 면접 준비에 쓸 수 있었다.
앞으로의 다짐 — 다음 전선은 DP Ⅰ과 BFS다
2차 갭체크에서 새로 빨갛게 켜진 자리가 DP Ⅰ과 BFS다.
이번 두 달 동안 시뮬레이션 Ⅰ, Ⅱ에 적용한 방식을, 같은 두 유형에 그대로 다시 걸어볼 계획이다.
순서는 정해져 있다.
트레일에서 기본 → 연습 → 테스트 3단계를 차례로 밟는다.
한번에 못 풀린 문제는 북마크 폴더에 넣는다.
한 달 뒤에 다시 갭체크를 응시한다.
마지막에 그 유형의 핵심 풀이 접근법을 한 문장으로 정리해 둔다.
여기까지가 한 사이클이다.
BFS라면 "큐와 방문 배열, 그리고 처음 방문한 시각이 최단 거리"라는 한 줄로 잡힐 거라고 보고 있다.
DP Ⅰ은 "상태 정의 + 점화식 + 메모이제이션" 같은 한 줄을 빠르게 잡고 들어가고 싶다.
최종 목표는 두 달 전과 같다.
삼성을 비롯한 대기업의 하반기 코딩테스트를 막힘 없이 통과하는 것.
7주의 챌린지가 끝나도 시스템 다섯 개는 그대로 남는다. 코드트리는 만기 보상으로 8월까지 무료로 이용할 수 있다.
그 두 달을 BFS와 DP에 그대로 쓴다.
코드트리에 바라는 점 — 비교, 대조, 분석을 한 화면으로
7주를 쓰면서 세 가지 기능이 있었으면 좋겠다고 느꼈다.
바람 ① — 갭체크 추이 뷰
1차, 2차 결과를 한 화면에 겹쳐 보여주는 기능이 있었으면 한다.
지금은 두 결과를 각각 캡처해 눈으로 대조해야 한다.
직전 응시 대비 변화가 화살표나 차트로 자동 표시되면, "한 달 동안 내가 어디서 어디까지 올랐는가"라는 질문이 한 번의 클릭으로 답이 나온다.
바람 ② — 오답 다시 풀 때 과거 제출 코드의 분할 뷰
오답으로 분류해 둔 문제를 다시 풀 때, 이전에 작성했던 제출 코드를 문제 화면 옆에 분할 화면이나 슬라이드로 띄워 주는 UX가 있었으면 한다.
지금은 '제출 이력' 탭을 매번 새로 클릭하거나, 깃허브에 남아 있는 과거 버전을 따로 열어 대조해야 한다.
복습의 본질은 과거의 잘못된 사고와 현재의 개선된 사고를 같은 화면에서 마주하는 것이라, 이 단계가 한 번에 보이게 되면 오답노트로서의 가치가 한 단계 올라간다.
바람 ③ — 갭체크 공통 실수 패턴 분석
갭체크가 본인의 풀이를 해석해 주는 것처럼, 학습자들의 공통적인 실수 패턴을 분석해 보여 주는 화면이 있다면, 본인이 어디서 어떻게 어긋나고 있는지를 다른 학습자들과의 대비로 한 번 더 확인할 수 있을 것 같다.
운영진께
매주 글을 쓰게 만든 챌린지 구조 덕분에, 블로그 글로 생각을 정리하게 되었고
본인의 글을 매주 다시 점검하게 만든 학습 도구로서, 이 챌린지의 도움이 컸다. 감사합니다 코드트리!
AI 시대에도 알고리즘을 공부해야 하는 이유 — 결국 워크플로우는 사람이 짠다
이번 챌린지의 마지막 미션 항목 중 하나가 "AI 시대에도 우리가 알고리즘을 공부해야 하는 이유"였다.
답은 두 달의 글 자체에 이미 적혀 있었다.
직관의 함정은 사람과 AI가 공유한다
[만나는 그 순간]에서 본인이 네 번 틀린 그 풀이 도착지 좌표만 계산하고 중간 경로를 잃어버리는 풀이는, 한 번에 결과로 점프하려는 직관의 가장 전형적인 형태다.
이 직관은 사람만 빠지는 함정이 아니다.
AI가 같은 함정에 빠진 코드를 그럴듯하게 완성해 놓으면, 코드 표면만으로 판별하기는 쉽지 않다. 일부 예제에서는 통과하기 때문이다. 그러나 두 객체가 3초나 5초에 스쳐 지나갔는지를 묻는 함정 케이스에서 틀린다.
한 달 동안 트레일 2 시뮬레이션 Ⅰ, Ⅱ를 풀고 시간 단위 시뮬레이션 골격을 손에 갖추고 나서야 짚어낼 수 있는 종류의 결함이다. 이 표준적인 골격이 머릿속에 없으면, 코드의 표면만 보고 통과 여부를 가늠하다 같은 함정에 끌려간다. 골격이 있어야 그 코드가 어디서 무너질지를 짚어내고 교정할 수 있는 토대가 생긴다.
워크플로우의 단계와 검수 지점은 사람이 정의한다
알고리즘 문제를 푼다는 것은 사실 한 가지 동작의 반복이다. 직관으로 한 번에 결과로 점프하지 않고, 문제를 작은 단계로 쪼갠 뒤, 각 단계의 상태를 정확히 정의하고, 그 상태를 한 줄씩 옮겨 적는 사고방식이다. 시뮬레이션이든 BFS든 DP든 본질은 같다.
결국 문제 풀이는 "전체 흐름을 단계로 쪼개고, 각 단계에서 무엇이 결정되는지를 사람이 정의하는 작업" 이다.
AI 시대의 개발자가 하는 일도 같은 모양을 한다. AI는 단계 안의 코드 작성을 도울 수 있다. 그러나 어디서 어디까지가 한 단계인지, 어떤 상태를 추적해야 하는지, 단계 사이의 전이가 어떤 조건에서 일어나는지를 정의하는 것은 사람의 몫이다.
그리고 AI가 만든 출력이 다음 단계로 넘어가도 되는지를 결정하는 검수 지점 워크플로우의 어디에 사람이 끼어들지를 설계하는 것도 사람이 한다.
알고리즘 문제를 풀면서 손에 붙는 사고가 그것이다. 전체 흐름을 단계로 쪼개고, 단계 사이의 검수 지점을 직접 짠다는 사고방식이다.
코드트리 두 달이 본인에게 가르친 것은 시뮬레이션 골격 하나만이 아니었다. 한 문제 앞에서 직관에 기대지 않고 단계를 옮겨 적는 손버릇이었다. 같은 손버릇이 AI 시대에 사람이 짜야 하는 워크플로우의 단계 정의, AI 출력의 검수 지점 배치, 그리고 도메인의 복잡성을 단계로 치환하는 사고에 그대로 옮겨 간다.
알고리즘 공부가 그 토대다.
마치며 — 7주는 의지력의 승리가 아니라 시스템의 승리였다
코드트리 청약 통장 챌린지 마이페이지
7주 동안 가장 자주 확인한 사실은 의지력이 자주 꺾인다는 것이었다. 그 빈자리를 시스템이 바로 잡아주었다.
알림톡이 매일 자리에 앉히고, 잔디가 시각화한다. 북마크가 틀린 문제로 끌고 가고, 골격이 풀이의 사고 비용을 낮춘다. 갭체크가 한 달마다 다음 목표를 가리킨다.
7주의 만기는 끝이 아니다. 갭체크의 새 빨간불인 DP Ⅰ과 BFS가 다음 한 달의 목표로 켜져 있고, 위에서 언급했던 알림톡, 깃허브 자동 잔디, 북마크 오답 폴더, 알고리즘 분석, 갭체크 사이클의 시스템으로 학습한다.
두 달 전에 처음 만든 학습 구조가 두 달 뒤에도 본인을 매일 자리에 앉히고 있다는 사실 자체가, 이번 챌린지가 남긴 가장 값진 성과였다.
챌린지 도중에 한 회차의 글이 그 회차의 최우수 학습 후기로 선정되면서, 박스가 도착하기도 했다.
4회차 최우수 학습 후기 선정 경품 (마우스는 아니다)
그 박스가 책상 위에 자리를 잡은 뒤로는, 다음 회차들의 글을 이어 가는 일이 조금 덜 무겁게 느껴졌다. 도착한 경품의 구성품과 언박싱 기록은 따로 정리해 두었다.