GROWTH LOG STORIES

함께 만든 성장을,
기록으로 연결합니다.

AI와 함께 배우고, 직접 만들고, 서로 나눈
그로스로그 멤버들의 생생한 성장 기록을 만나보세요.

성장 기록
5기+이어진 커뮤니티
HEALTHIO
PROJECT

사진 한 장으로 시작하는 건강 루틴, Health IO

대표 이야기 읽기

ALL STORIES

성장의 순간을
한곳에서 만나보세요.

프로젝트의 시작부터 모임에서 나눈 인사이트까지,
그로스로그가 함께 만든 기록을 모았습니다.
개의 성장 기록

성장일지

[GL 5기 2회차 ③] 비슷해 보이는 것을 갈라놓기 — 전산 빈출 개념, Taint와 Toleration, RTSP 스트리밍 서버 🌱

GROWTH LOG🌱 2026. 8. 12. 20:17
GL 5기 성장일지 2회차 큐레이션

안녕하세요! 그로스로그 입니다!😊 🌱

매번 헷갈리는 세 개념, 시험에서 자꾸 틀리는 짝들, 그리고 증상은 하나인데 원인이 셋이던 스트리밍 지연입니다.

5기 2회차 세 번째 묶음입니다. 앞선 여섯 편에 이어 세 편을 더 소개합니다. 이번 세 편은 비슷해 보이는 것을 갈라놓는 일을 다룹니다.

 

01

📚 전산 일반 빈출 내용 정리

문세웅 님

이런 내용이에요
시험 대비로 전산 일반 빈출 개념 열다섯 항목을 한 편에 몰아 정리한 글입니다.
RR과 SR 스케줄링, 자바 상속 시 생성자 호출 순서, GoF 디자인 패턴 세 분류, SQL JOIN, 서브넷 마스크 계산, DB 정규화, GROUP BY 규칙, IterableIterator, 얕은 복사와 깊은 복사, 직접 사상, CA 인증서까지.
항목마다 비슷해서 헷갈리는 짝이 들어 있습니다. GROUP BY vs HAVING, 얕은 복사 vs 깊은 복사처럼요.

정보처리기사나 전산직을 준비하는 분이라면 목차만 봐도 쓸모가 보이는 글입니다.

조금 더 들어가 보면

이 정리의 성격은 "헷갈려서 틀리는 것들의 모음"입니다. 목차를 보면 짝을 이루는 항목이 반복돼요.

· RR (Round Robin) & SR (Shortest Remaining Time) — 둘 다 시간을 기준으로 삼는데 기준이 다릅니다

· GROUP BY 규칙 / HAVING vs WHERE — 조건을 거는 자리가 집계 전이냐 후냐

· 얕은 복사(Shallow Copy) / 깊은 복사(Deep Copy) — 중첩 리스트에서 갈라집니다

· Iterable과 Iterator — 이름이 비슷해서 매번 다시 찾아보게 되는 짝

혼자서는 명확한데 나란히 놓으면 헷갈리는 것들이죠. 시험에서 틀리는 것도 대개 이런 자리입니다.

🏛️ GoF 패턴을 세 갈래로 나눈 것

디자인 패턴 항목이 특히 잘 짜여 있습니다. 스물 몇 개를 나열하는 대신 세 분류로 묶고 대표만 골랐어요.

분류 대표 패턴 무엇을 다루는가
생성 패턴 Singleton, Factory Method 객체를 어떻게 만들 것인가
구조 패턴 Adapter, Decorator 객체를 어떻게 조립할 것인가
행위 패턴 Strategy, Observer 객체들이 어떻게 소통할 것인가

분류가 곧 기억 장치입니다. 패턴 이름을 스물세 개 외우는 것보다 "만들기·조립하기·소통하기" 세 갈래를 잡아두면 새 패턴을 만나도 자리를 찾을 수 있어요.

📝 원문에서는 이렇게 갈라 보입니다

얕은 복사와 깊은 복사를 다룬 대목이 이 글의 방식을 보여줍니다. 설명 대신 같은 원본을 두 방법으로 복사하고 값을 바꿔봅니다.

# 원본 데이터 (중첩 리스트)

# 1. 얕은 복사 (Shallow Copy)
# 2. 깊은 복사 (Deep Copy)

중첩 리스트를 쓴 게 핵심입니다. 평평한 리스트로는 두 방법의 차이가 안 드러나니까요. 안쪽 리스트가 있어야 "겉만 복사했는가, 속까지 복사했는가"가 갈립니다.

서브넷 마스크와 호스트 개수 계산, 직접 사상(Direct Mapping), CA와 인증서 역할도 같은 방식으로 다룹니다. 개념 설명 + 계산 예시 + 헷갈리는 지점이 한 세트예요.

큐레이터 노트

틀리는 자리를 모아둔 글이라 뽑았습니다.

시험 정리는 보통 교재 순서를 따라갑니다. 이 글은 순서가 다릅니다 — 자꾸 틀리는 것들을 모았어요. 그래서 RR과 SR이 나란히 있고, WHEREHAVING이 나란히 있고, 얕은 복사와 깊은 복사가 나란히 있습니다.

나란히 놓는 것 자체가 학습 방법입니다. 따로 배우면 각각 이해되지만, 시험에서는 둘 중 하나를 고르라고 하니까요. 구분이 필요한 지점을 알아야 구분할 수 있습니다.

분류로 묶은 것도 좋았습니다. GoF 패턴을 생성·구조·행위 셋으로 나누면 개별 패턴을 잊어도 어디쯤에 있던 것인지는 남습니다. 열다섯 항목이라는 분량을 감당할 수 있게 만든 장치이기도 하고요.

정보처리기사를 준비하는 회원이 많은 기수라, 한 편으로 여러 파트를 훑을 수 있는 정리가 특히 값어치 있습니다.

원문 읽으러 가기  ↗velog.io/@moonsyang/GrowthLog-%EC%84%B1%EC%9E%A5%EC%9D%BC%…
 

02

☸️ 쿠버네티스 Taint and Toleration

남혜민 님

이런 내용이에요
쿠버네티스의 Taint와 Toleration을 정리한 글입니다. 그런데 첫 문장이 목적을 분명히 밝혀요.
"들어가기 앞서, 매번 헷갈리는 Node Affinity vs Taint vs Toleration을 정리한다."
세 개념을 한 줄씩 갈라놓고, kubectl taint 명령과 effect의 의미를 코드로 확인합니다.

세 개념을 나란히 놓는 것에서 시작하는 글입니다.

조금 더 들어가 보면

세 정의가 이렇게 정리됩니다.

node affinity : 노드 set을 끌어들이는 파드의 속성
taint : 노드가 파드 셋을 제외시키는 속성
toleration : 파드에 적용되어 노드에 배치될 수 있는 속성

읽고 나면 왜 헷갈렸는지가 보입니다. 셋 다 "어느 노드에 배치할까"를 다루는데 주체와 방향이 다르기 때문이에요.

· Node Affinity파드가 노드를 끌어당깁니다

· Taint노드가 파드를 밀어냅니다

· Toleration파드가 그 밀어냄을 견딥니다

주체가 파드였다가 노드였다가 다시 파드로 바뀝니다. 끌어당김과 밀어냄이라는 반대 방향이 섞여 있고요. 헷갈리는 게 자연스럽습니다.

⚠️ 보장이 아니라는 단서

그리고 중요한 단서를 답니다.

"단, 스케줄은 가능하지만 항상 완전히 보장하진 않는다. 쿠버네티스 스케줄러가 taint나 toleration 뿐만 아니라 다른 파라미터들도 고려하기 때문이다."

Toleration은 "갈 수 있다"이지 "간다"가 아닙니다. 이 구분을 안 해두면 "toleration 붙였는데 왜 거기 안 뜨죠?"에서 막힙니다. 스케줄러는 taint 말고도 리소스 여유, affinity 규칙 같은 걸 같이 보니까요.

📝 원문에서는 이렇게 확인합니다

명령어와 해석을 붙여둔 게 실용적입니다.

kubectl taint nodes node1 key1=value1:NoSchedule

# 삭제 — 끝에 하이픈을 붙인다
kubectl taint nodes node1 key1=value1:NoSchedule-

세 부분으로 나눠 설명합니다 — key(key1), value(value1), effect(NoSchedule).

그리고 이 명령이 무슨 뜻인지를 우리말로 한 번 더 옮깁니다.

"해석 : key1=value 조건의 파드가 있지 않는 한 해당 노드에 스케줄링 하지 마라."

명령어를 문장으로 바꿔 적어둔 것이 이 글에서 제일 쓸모 있는 대목입니다. NoSchedule이라는 영어 한 단어를 우리말 문장으로 풀어두면 나중에 볼 때 다시 해석할 필요가 없어요.

삭제가 끝에 하이픈을 붙이는 것이라는 것도 실무에서 자주 찾게 되는 정보입니다.

큐레이터 노트

헷갈린다고 먼저 밝히고 시작한 글이라 뽑았습니다.

기술 정리 글은 대개 아는 사람의 목소리로 씁니다. 이 글은 첫 문장이 "매번 헷갈리는"이에요. 그래서 정리의 순서가 달라집니다 — 개념 하나를 깊게 파는 대신 혼동되는 셋을 나란히 놓는 것부터 합니다.

혼동은 대개 개별 개념을 몰라서가 아니라 경계를 몰라서 생깁니다. Taint가 뭔지 각각 읽으면 다 이해되는데, 실제로 클러스터 앞에 앉으면 "이건 affinity로 해야 하나 taint로 해야 하나"에서 막히죠. 그 자리를 정확히 짚은 정리입니다.

보장하지 않는다는 단서를 남긴 것도 좋았습니다. 문서를 옮기기만 하면 빠지기 쉬운 대목인데, 이게 없으면 나중에 원인을 못 찾습니다.

5기 큐레이션에서 쿠버네티스를 다룬 유일한 글이기도 합니다. Cloud·Infra 쪽이 얇은 기수라 더 반가웠습니다.

원문 읽으러 가기  ↗to-be-myself.tistory.com/62
 

03

📹 [C++] RTSP 실시간 웹 스트리밍 서버 구축기

서지영 님

이런 내용이에요
웹 브라우저에서 실시간 CCTV 영상을 보여주기 위해 RTSP 스트림을 WebSocket으로 중계하는 서버를 C++로 직접 구현한 기록입니다.
구조를 설계하고 끝내지 않아요. 문제 셋을 차례로 만나고 각각 원인을 찾아 고칩니다 — 스트리밍 지연, 다중 접속 시 자원 막힘, 세션 충돌.
각 문제마다 원인 → 해결 방법 → 결과가 나란히 적혀 있습니다.

같은 증상처럼 보이는 것에 원인이 셋이었다는 기록입니다.

조금 더 들어가 보면

먼저 왜 중계 서버가 필요한지부터 짚습니다.

"웹 브라우저는 RTSP 프로토콜을 직접 지원하지 않기 때문에, 중간에서 스트림을 변환하고 전달하는 서버 계층이 필요합니다."

그래서 파이프라인이 이렇게 됩니다.

RTSP Input (CCTV)  →  FFmpeg (디코딩·변환)  →  WebSocket Server (C++)  →  브라우저

여기서 초기 판단 하나가 기록돼 있습니다. Base64 인코딩을 고려했다가 버린 것이요. "실시간 스트리밍 특성상 인코딩/디코딩 오버헤드가 부담이 되어 최종적으로는 바이너리(ArrayBuffer) 기반 전송 방식을 선택했습니다." 검토했다가 안 고른 선택지를 남긴 것이라 뒤에 오는 사람이 같은 고민을 반복하지 않습니다.

구조는 둘로 나눴습니다.

· StreamWorker — FFmpeg 프로세스를 실행하고, 별도 스레드에서 출력을 계속 읽어 내부 버퍼로 전달

· StreamListener — 그 데이터를 받아 웹소켓으로 클라이언트에 전송

그리고 이 문장이 이어집니다.

"이 구조는 역할 분리가 명확해 구현은 수월했지만, 실제 운영 환경에서는 예상하지 못한 문제가 발생했습니다."

🐢 문제 1 — 지연의 원인은 내 코드가 아니었다

첫 문제가 비정상적인 지연이었습니다. 서버는 데이터를 정상 수신하는데 브라우저에서는 몇 초씩 밀린 영상이 나왔어요.

원인이 의외의 자리에 있었습니다.

"popen으로 실행한 FFmpeg 프로세스의 출력이 C 런타임의 Full Buffering 정책에 의해 지연되고 있었습니다. 즉, 데이터가 일정 크기 이상 쌓일 때까지 외부로 전달되지 않는 구조였습니다."

C 런타임의 기본 버퍼링 정책이 범인이었습니다. 코드는 맞게 짰는데 런타임이 데이터를 모아두고 있었던 거죠. 실시간 스트리밍에서는 그 "모아두기"가 곧 지연입니다.

해결은 셋입니다.

· setvbuf버퍼링 제거(Unbuffered 모드)

· _read 기반으로 즉시 데이터 읽기

· 세션 종료 시 pclose명시적 자원 해제

결과가 좋습니다. "스트리밍 지연이 눈에 띄게 감소하였고, 장기 실행 시 발생하던 좀비 프로세스 문제도 해결되었습니다." 한 가지를 고치니 다른 문제도 같이 풀린 것이죠.

📝 원문에서는 이렇게 구조를 바꿉니다

두 번째 문제는 규모에서 왔습니다. 초기 구조가 이랬어요.

"클라이언트 1명당 FFmpeg 프로세스 1개 생성"

한 명일 때는 아무 문제가 없었습니다. 그런데 "여러 사용자가 동시에 접속하거나 브라우저 탭을 여러 개 열 경우 CPU 사용량과 네트워크 트래픽이 급격히 증가"했고, 일정 수준을 넘으면 서버 전체가 불안정해졌습니다.

탭을 여러 개 여는 것만으로도 프로세스가 늘어난다는 게 이 구조의 함정입니다. 사용자 수가 아니라 연결 수에 비례하니까요.

그래서 1:N 브로드캐스팅으로 바꿉니다. FFmpeg 하나가 만든 스트림을 여러 클라이언트가 나눠 받는 구조요.

세 번째 문제는 그 변경이 만든 새 문제였습니다 — 세션 충돌 및 화면 혼합. 스트림을 공유하니 세션이 섞인 것이죠. 이건 세션 격리(Session Isolation)로 해결합니다.

문제 → 해결 → 그 해결이 만든 새 문제 → 다시 해결. 실제 개발이 진행되는 모양 그대로입니다.

큐레이터 노트

해결이 만든 새 문제까지 적은 글이라 뽑았습니다.

구축기는 보통 완성된 구조를 보여줍니다. 이 글은 초기 구조를 먼저 보여주고 그게 왜 안 됐는지를 셋으로 나눠 적어요. 그리고 두 번째 해결(1:N 브로드캐스팅)이 세 번째 문제(세션 충돌)를 만들었다는 것까지 남깁니다. 구조 변경에 값이 붙는다는 걸 그대로 보여주는 기록입니다.

원인이 자기 코드 바깥에 있었던 것도 값어치 있는 대목입니다. 지연의 범인이 C 런타임의 버퍼링 정책이었다는 것 — 로직을 아무리 들여다봐도 안 나오는 자리예요. "서버는 정상적으로 데이터를 수신하고 있었지만"이라는 관찰이 그 단서였습니다. 받고 있는데 늦는다면 받는 코드가 아니라 그 아래를 봐야 한다는 것이죠.

5기에서 C++로 서버를 구현한 유일한 기록이고, RTSP·WebSocket 중계는 검색해도 자료가 많지 않은 영역입니다. 자료가 드문 영역이라는 것 자체가 기여입니다.

원문 읽으러 가기  ↗www.createdoodle.dev/post/20

💡 세 편을 겹쳐 읽으며

시험 정리, 쿠버네티스 개념, C++ 서버 구축기입니다. 층이 다 다른데 세 편이 같은 작업을 하고 있습니다.

비슷해 보이는 것을 갈라놓기

남혜민 님 글이 이걸 제목처럼 내겁니다. "매번 헷갈리는 Node Affinity vs Taint vs Toleration을 정리한다." 셋 다 배치를 다루는데 주체와 방향이 달라서 헷갈렸던 거였죠.

문세웅 님 정리도 같은 성격입니다. RR과 SR, WHEREHAVING, 얕은 복사와 깊은 복사 — 혼자 보면 알겠는데 나란히 놓으면 헷갈리는 짝들이 모여 있습니다.

서지영 님 글은 그 반대 방향입니다. 증상은 하나("영상이 늦게 나온다")인데 원인이 셋이었어요. 버퍼링 정책, 프로세스 수, 세션 공유. 증상이 같다고 원인이 같은 게 아니라는 걸 세 번에 걸쳐 보여줍니다.

한쪽은 개념을 갈라놓고 한쪽은 원인을 갈라놓지만, 하는 일은 같습니다.

문장으로 옮겨 적어두기

두 번째 공통점은 기록의 형태입니다.

남혜민 님은 kubectl taint nodes node1 key1=value1:NoSchedule을 우리말 한 문장으로 옮겨 적었습니다 — "key1=value 조건의 파드가 있지 않는 한 해당 노드에 스케줄링 하지 마라." 명령어를 다시 해석할 필요가 없어집니다.

문세웅 님은 얕은 복사와 깊은 복사를 설명 대신 중첩 리스트에 두 방법을 적용한 코드로 남겼습니다.

서지영 님은 문제마다 원인 · 해결 방법 · 결과를 같은 형식으로 적었습니다. 세 번 반복되니 읽는 사람이 형식을 익히고, 나중에 자기 문제도 그 틀로 정리할 수 있게 되죠.

안 고른 것과 안 되는 것을 같이 적었다

세 번째는 경계를 남긴 것입니다.

남혜민 님은 "스케줄은 가능하지만 항상 완전히 보장하진 않는다"고 단서를 달았습니다. 서지영 님은 Base64를 검토했다가 버린 이유를 적었고요. 문세웅 님의 HAVING vs WHERE도 결국 "어느 자리에 쓰면 안 되는가"의 문제입니다.

되는 것만 적으면 나중에 왜 안 되는지 모릅니다.

이번 회차에서 가져갈 것

1. 헷갈리는 개념은 나란히 놓고 주체와 방향부터 확인하기.

Affinity는 파드가 끌어당기고, Taint는 노드가 밀어내고, Toleration은 파드가 견딥니다. 주체가 바뀌는 지점이 헷갈림의 원인입니다.

2. Toleration은 "갈 수 있다"이지 "간다"가 아니다.

스케줄러는 리소스 여유와 affinity도 같이 봅니다. 붙였는데 안 뜬다면 다른 조건을 확인하세요.

3. 명령어를 우리말 문장으로 옮겨 적어두기.

NoSchedule 같은 옵션은 나중에 또 해석하게 됩니다. 한 번 풀어 써두면 다시 안 찾습니다.

4. 실시간 처리에서 지연이 나면 내 코드 아래를 보기.

popen의 Full Buffering처럼 런타임 기본값이 데이터를 모아두고 있을 수 있습니다. "받고는 있는데 늦는다"면 특히요.

5. 연결 1개당 프로세스 1개 구조는 탭 하나에도 늘어난다.

사용자 수가 아니라 연결 수에 비례합니다. 공유할 수 있는 자원은 1:N으로 묶고, 대신 세션 격리를 같이 설계하세요.

6. 구조를 바꾸면 새 문제가 따라온다.

1:N으로 묶으니 세션이 섞였습니다. 개선의 대가를 미리 예상해두면 다음 문제를 버그가 아니라 예정된 작업으로 다룰 수 있습니다.

7. 패턴은 개별 이름보다 분류로 기억하기.

생성·구조·행위 세 갈래를 잡아두면 새 패턴을 만나도 자리를 찾습니다.


성장일지는 멤버들이 2주에 한 번씩 자신의 성장을 기록하는 활동이에요. 지난 기수의 성장일지를 다시 읽으면서, 그때 소개해드리지 못한 글을 하나씩 꺼내고 있습니다.

좋은 글 남겨주신 문세웅 님, 남혜민 님, 서지영 님께 감사드립니다! 😊

다음 큐레이션으로 다시 찾아오겠습니다! 🌱

- 에디터 · 성장일지 큐레이터 -


※ 본 큐레이션은 각 저자가 공개한 글을 소개하는 것이며, 모든 원문의 저작권은 저자에게 있습니다. 저자 본인의 요청이 있을 경우 즉시 수정 또는 삭제합니다.

WRITE YOUR GROWTH

오늘의 배움을
내일의 성장으로.

기록은 나를 돌아보게 하고, 공유는 우리를 연결합니다.
당신의 다음 성장 이야기도 그로스로그에서 시작해보세요.

커뮤니티 둘러보기