GROWTH LOG STORIES

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

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

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

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

대표 이야기 읽기

ALL STORIES

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

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

성장일지

[GL 2기 4회차] 데이터가 지나가는 길목 — 입출력 시스템, 리액트 fetch, tap 연산자 🌱

GROWTH LOG🌱 2026. 8. 9. 03:36

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

키보드에서 CPU까지, 서버에서 화면까지, 그리고 흐름 한가운데를 들여다보는 법. 2기 4회차 세 편입니다.

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

2기 4회차, 2024년 10월 말입니다. 이번 회차에는 데이터가 오가는 통로를 서로 다른 층위에서 다룬 세 편이 모였어요.

 

01

🔌 12, 13강 입출력시스템

김영진 님

김영진 님 원문에 실린 이미지
이런 내용이에요
컴퓨터구조 강의의 입출력 시스템 두 강을 정리한 글입니다. 11,821자예요.
핵심은 속도가 다른 두 세계를 어떻게 잇는가입니다. CPU와 키보드는 속도도, 다루는 데이터 단위도, 오류 발생률도 다릅니다. 그 차이를 메우는 장치들이 차례로 나와요.
데이터 버퍼와 플래그, 직렬·병렬 전송의 선택 기준, 패리티 비트까지 차이마다 대응책이 하나씩 붙어 있습니다.

컴퓨터가 계산만 한다면 입출력은 필요 없습니다. 그런데 결과를 화면에 띄우고 키보드 입력을 받아야 하죠.

문제는 CPU와 주변 장치의 성능 차이가 어마어마하다는 것입니다. 이 글은 그 간극을 메우는 장치들을 순서대로 짚습니다.

조금 더 들어가 보면

🚦 CPU가 직접 하면 왜 안 되나

글이 두 가지 구성을 대비합니다. 먼저 가장 단순한 형태예요.

기본 입출력시스템 — 입출력제어기가 없기 때문에 모든 입출력제어기능은 CPU에 둠
중앙처리장치가 입출력을 수행하기 떄문에 중앙처리장치에서 수행하는 프로그램의 수행이 지연되므로 비효율적인 시스템이다.

CPU가 입출력까지 맡으면 그동안 계산을 못 합니다.

숫자로 보면 차이가 확 와닿습니다. CPU는 1초에 수십억 번 연산하는데, 사람이 키보드를 누르는 건 1초에 몇 번이에요. 그 사이를 CPU가 기다리고 있으면 수억 번의 연산 기회를 버리는 셈입니다.

그래서 별도의 제어기를 둡니다.

CPU가 입출력 제어기능을 수행하지 않고 CPU대신에 별도의 입출력제어기를 두어 입출력을 수행함.
자체의 프로그램 수행능력을 갖고 있으며, 이는 CPU의 개입 없이 입출력이 자율적으로 행해지도록 하기 위함이다.

"자체의 프로그램 수행능력"이 핵심입니다. 단순히 신호를 전달하는 게 아니라, 스스로 판단해서 일을 끝내고 결과만 알려주는 구조예요.

일을 떼어내 다른 데 맡기고 자기는 하던 일을 계속한다 — 비동기 처리의 원형이 여기 있습니다. 이 회차의 두 번째 글에 나오는 async/await도 결국 같은 발상이고요.

⚖️ 세 가지 차이와 세 가지 대응

이 글의 구조가 좋은 건, 차이를 나열하고 각각에 대응책을 붙였다는 점입니다.

주기억장치와 입출력장치는 정보 전달시 동작 속도, 정보의 단위, 동작의 자율성, 오류 발생률의 측면에서 다른 특성을 가진다.
이러한 특성의 차이 때문에 주기억장치와 입출력장치를 직접 연결하여 입출력을 수행할 수는 없다

그리고 하나씩 답이 나옵니다.

속도 차이는 버퍼로 메웁니다. 중간에 임시 저장소를 두고, B(장치 사용 여부)와 D(버퍼 상태) 두 플래그로 서로의 상태를 알립니다. 빠른 쪽이 넣어두고 가면 느린 쪽이 나중에 가져가는 구조예요.

단위 차이는 크기를 맞춰 해결합니다. 주기억장치는 단어(word) 단위로 다루는데 입출력장치는 문자(1바이트) 단위라, 버퍼 크기를 1바이트로 잡습니다.

오류율 차이는 검사 비트로 잡습니다. 패리티 비트를 붙여 전송 중 값이 뒤집혔는지 확인해요.

세 가지 다 "차이를 없애는" 게 아니라 "차이를 견디게" 만드는 방식입니다. 키보드를 CPU만큼 빠르게 만들 수는 없으니까요.

🔀 직렬과 병렬, 거리가 기준이다

전송 방식 비교가 특히 실용적입니다.

직렬전송 — 비트별로 한 비트씩 (…) 데이터 전달회선의 수가 한개이면 되기 때문에 입출력장치 인터페이스와 입출력장치의 거리가 비교적 멀어도 회선 비용이 저렴
병렬전송 — 한 바이트를 한꺼번에 전송하므로 최소 8개의 데이터 전달 회선이 필요 (회선의 길이가 길면길수록 느리고 비용증가)

직관적으로는 여덟 개를 한 번에 보내는 병렬이 무조건 빠를 것 같습니다. 그런데 글은 병렬을 "가까운 거리에만" 쓴다고 적었어요.

이유가 있습니다. 여덟 가닥으로 동시에 보내도 도착 시각이 완벽히 같지 않습니다. 선 길이가 미세하게 다르고 신호 간섭도 있어서, 거리가 멀수록 어긋남이 커져요. 그러면 여덟 비트가 다 도착할 때까지 기다려야 하니 오히려 느려집니다.

그래서 선이 하나뿐인 직렬은 거리가 멀어도 이 문제가 없습니다. USB나 SATA처럼 요즘 빠른 규격이 대부분 직렬인 이유예요. 병렬이 이론적으로 유리한 구간은 아주 짧은 거리뿐입니다.

"회선 길이가 길수록 느리다"는 한 줄에 이 사정이 담겨 있습니다.

📝 원문에서는 이렇게 정리합니다

제어기를 두 층으로 나눈 부분이 눈에 띕니다.

입출력장치 제어기 — 입출력에 필요한 입출력장치 고유의 기능만 다루는 제어기 (…) 다른 모든 장치들이 논리회로로 되어있는 것과 달리 아날로그 회로를 포함한다.
입출력제어기 — 입출력장치의 공통적인 기능을 다루는 제어기

고유한 것과 공통된 것을 갈라 층을 나눴습니다.

프린터를 움직이는 모터 제어는 프린터마다 다릅니다. 그런데 "데이터를 받아서 장치로 보낸다"는 공통이에요. 공통 부분을 위로 빼면, 새 장치가 생겨도 아래쪽만 만들면 됩니다.

소프트웨어에서 인터페이스를 두고 구현체를 갈아끼우는 것과 같은 구조입니다. 하드웨어에서 먼저 쓰던 방식이고요.

그리고 "아날로그 회로를 포함한다"는 한 줄도 재밌습니다. 컴퓨터 안은 전부 0과 1인데, 모터를 실제로 돌리려면 아날로그 신호가 필요하거든요. 디지털 세계가 물리 세계와 만나는 지점이 딱 거기입니다.

큐레이터 노트

강의 정리 글인데 구조가 반복돼서 고른 글입니다.

입출력 시스템은 외울 게 많은 단원입니다. 장치 이름도 여러 개고 제어기도 층층이 있어서, 나열식으로 정리하면 항목만 늘어나요.

이 글은 "차이 → 대응"이라는 틀을 잡고 그 안에 항목을 배치했습니다. 속도가 다르니 버퍼, 단위가 다르니 크기 조정, 오류율이 다르니 패리티. 항목이 늘어도 자리가 정해져 있으니 헷갈리지 않습니다.

김영진 님은 2기 내내 컴퓨터구조와 자료구조 강의를 정리해오셨습니다. 회차마다 두 강씩 묶어서요. 교재의 목차를 그대로 따라가되 자기 정리 틀을 얹은 기록입니다.

원문 읽으러 가기  ↗yeongjin.tistory.com/337
 

02

🌐 리액트에서 fetch 사용하기

이주희 님

이주희 님 원문에 실린 이미지
이런 내용이에요
목업 데이터(mock.json)로 만들던 화면을 실제 서버 데이터로 바꾸는 과정입니다.
순서가 실용적이에요. 먼저 콘솔에서 fetch를 쳐 데이터가 오는지 확인하고, 네트워크 탭에서 응답 구조를 보고, api.js로 함수를 분리한 다음, 앱에서 목업을 걷어냅니다.
코드를 바꾸기 전과 후로 나란히 올려서 무엇이 달라졌는지 바로 보입니다.

3회차 큐레이션에서 이분의 컴포넌트·props 정리를 소개해드렸습니다. 그때는 화면을 조각으로 나누는 이야기였고, 이번엔 그 조각에 넣을 데이터를 밖에서 가져옵니다.

조금 더 들어가 보면

🧪 콘솔에서 먼저 쳐본다

첫 단계가 인상적입니다.

console에 fetch(데이터경로) 입력해서 데이터 잘 불러오는지 확인
Network 탭에서 확인

코드를 쓰기 전에 브라우저 콘솔에서 직접 호출해봅니다.

이게 왜 좋은 순서냐면, 문제가 생겼을 때 어디가 원인인지 갈라주기 때문입니다. 콘솔에서 되는데 앱에서 안 되면 내 코드 문제고, 콘솔에서도 안 되면 주소나 서버 문제예요.

한 번에 다 짜고 나서 "안 되네" 하면 원인 후보가 여럿입니다. 주소가 틀렸는지, 비동기 처리가 잘못됐는지, 상태 갱신이 안 된 건지 하나씩 지워가야 하죠. 먼저 확인하고 시작하면 그 과정이 통째로 사라집니다.

그리고 네트워크 탭에서 응답 구조를 본 것도 같은 맥락입니다. 글에 이렇게 적혀 있어요.

paging 은 데이터 추가 로딩햇을 값을 담고 잇음
reviews 프로퍼티에는 일부 데이터가 잇음 (mock.json 과 구조 비슷)

목업과 실제 응답의 구조를 비교했습니다. 이 확인을 안 하면 나중에 화면이 빈 채로 뜨고, 그때서야 "아 목록이 reviews 안에 있었네"를 알게 됩니다.

⏳ async와 await가 하는 일

api.js로 뺀 함수가 이 글의 핵심입니다.

export async function getReviews() {
  const response = await fetch('경로');
  const body = await response.json();
  return body;
}

네 줄인데 비동기의 핵심이 다 들어 있습니다.

fetch는 즉시 데이터를 주지 않습니다. 요청을 보내고 응답이 올 때까지 기다려야 하는데, 그동안 브라우저가 멈춰 있으면 안 되죠. 버튼도 안 눌리고 화면도 안 움직이면 고장 난 것처럼 보이니까요.

그래서 fetch"나중에 값이 올 것"이라는 약속(Promise)만 먼저 돌려줍니다. await는 그 약속이 지켜질 때까지 이 함수만 잠시 멈춰 세우고, 브라우저의 다른 일은 계속 돌아가게 해요.

앞서 김영진 님 글에서 본 구조와 같습니다. CPU가 입출력을 제어기에 맡기고 자기 일을 계속하는 것과, 브라우저가 네트워크 요청을 걸어두고 화면을 계속 그리는 것이요. 층은 다른데 발상이 같습니다.

await가 두 번 나오는 것도 이유가 있습니다. 첫 번째는 응답 헤더가 도착할 때까지, 두 번째는 본문을 다 받아 JSON으로 바꿀 때까지입니다. 서버가 응답을 시작했다고 데이터가 다 온 건 아니거든요.

📦 왜 api.js로 빼는가

글이 데이터 요청을 별도 파일로 옮긴 것도 짚을 만합니다.

컴포넌트 안에 fetch를 그대로 써도 동작은 합니다. 그런데 파일을 나누면 두 가지가 생겨요.

첫째, 주소가 한 군데 모입니다. 서버 주소가 바뀌거나 개발·운영 환경이 갈릴 때 api.js만 고치면 됩니다. 컴포넌트마다 흩어져 있으면 전부 찾아다녀야 하죠.

둘째, 화면 코드가 데이터 출처를 모르게 됩니다. getReviews()를 부르는 쪽은 그게 서버에서 오는지 목업인지 신경 쓰지 않아요. 그래서 나중에 목업으로 되돌리거나 캐시를 끼워 넣기가 쉽습니다.

실제로 이 글이 한 작업이 정확히 그 교체입니다. mock.jsongetReviews()로 바꿨는데, 화면 컴포넌트는 거의 그대로예요.

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

목업을 걷어내는 과정을 코드 두 벌로 보여줍니다.

// 바꾸기 전
import mockItems from "./mock.json";
const [items, setItems] = useState(mockItems);

// 바꾼 뒤
// import mockItems from "./mock.json";
import { getReviews } from "./api";
const [items, setItems] = useState([]);

초기값이 mockItems에서 빈 배열 []로 바뀐 게 중요합니다.

목업을 쓸 때는 화면이 뜨는 순간 데이터가 이미 있습니다. 서버에서 가져오면 처음 몇 백 밀리초 동안은 아무것도 없어요. 그 사이에 화면이 그려지니, 빈 배열이 없으면 "없는 값을 읽으려 한다"는 오류가 납니다.

목업에서 실제 데이터로 옮길 때 반드시 만나는 지점입니다. "데이터가 아직 없는 순간"이 새로 생기거든요. 로딩 표시나 빈 화면 처리가 필요해지는 것도 이때부터고요.

그리고 주석 처리로 남겨둔 // import mockItems도 눈에 띕니다. 지우지 않고 남긴 건 되돌릴 수 있게 해둔 것이죠. 학습 중에는 이렇게 두는 편이 낫습니다.

큐레이터 노트

순서가 좋아서 고른 글입니다.

콘솔에서 확인 → 응답 구조 파악 → 함수 분리 → 화면 교체. 이 네 단계가 그대로 적혀 있습니다. 강의를 들으며 정리한 노트인데, 강의가 알려준 순서를 그냥 옮긴 게 아니라 왜 그 순서인지가 보이게 적었어요.

그리고 바꾸기 전후 코드를 둘 다 올린 것. 결과 코드만 있으면 "이렇게 하면 된다"로 끝나는데, 전후가 있으면 무엇이 달라졌는지가 보입니다. 나중에 자기가 다시 볼 때도 그 차이가 기억을 되살려주고요.

원문 읽으러 가기  ↗velog.io/@veryverysohappy/%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%9…
 

03

🔬 8장. 유틸리티 연산자 요약

남기준 님

남기준 님 원문에 실린 이미지
이런 내용이에요
RxJS의 tap 연산자를 다룹니다. 값을 바꾸지 않고 지나가는 걸 들여다보기만 하는 연산자예요.
세 가지 콜백(next·error·complete)을 각각 코드와 실행 결과로 보여줍니다.
특히 첫 예제가 좋습니다. 연산자 사이사이에 tap을 끼워 넣어 값이 각 단계를 어떻게 통과하는지 출력으로 찍어냅니다.

앞의 두 글이 데이터를 가져오는 이야기라면, 이건 데이터가 지나가는 중간을 보는 이야기입니다.

조금 더 들어가 보면

👀 바꾸지 않고 보기만 한다

tap의 정의가 간결합니다.

tap 연산자는 소스 옵저버블에서 발행하는 값을 전달 받은 후 인자로 사용하는 함수를 호출하고 소스 옵저버블에서 발행한 값을 그대로 발행한다.

받아서 뭔가 하고, 원래 값을 그대로 흘려보냅니다.

3회차에서 다룬 map이나 filter와 다른 점이 여기입니다. map은 값을 바꾸고 filter는 값을 걸러내는데, tap은 흐름에 아무 영향을 주지 않아요. 파이프 중간에 창문을 하나 낸 것에 가깝습니다.

그럼 왜 쓸까요. 디버깅 때문입니다.

여러 연산자를 이어 붙인 파이프에서 결과가 이상할 때, 어느 단계에서 틀어졌는지 알기 어렵습니다. 중간값이 안 보이니까요. console.log를 넣고 싶어도 파이프 안에는 넣을 자리가 없습니다.

tap이 그 자리를 만들어줍니다.

🪜 단계마다 창문을 내기

첫 예제가 이 쓰임을 정확히 보여줍니다.

range(1, 10).pipe(
  tap(x => console.log(`stream 1 (range 1, 10) ${x}`)),
  filter(x => x % 2 === 0),
  tap(x => console.log(`  stream 2 (filter x % 2 === 0) ${x}`)),
  map(x => x + 1),
  tap(x => console.log(`    stream 3 (map x + 1) ${x}`))
).subscribe(x => console.log(`      result ${x}`));

연산자 사이마다 tap을 끼웠습니다. 그리고 출력 앞의 공백을 단계마다 늘려서, 로그만 봐도 어느 깊이인지 보이게 했어요.

실행 결과를 보면 흐름이 그대로 드러납니다.

stream 1 (range 1, 10) 1
stream 1 (range 1, 10) 2
  stream 2 (filter x % 2 === 0) 2
    stream 3 (map x + 1) 3
      result 3

1은 stream 1에서 멈췄고, 2는 끝까지 갔습니다. 홀수가 필터에서 걸러진다는 게 눈으로 보이죠.

글이 정리한 한 줄이 정확합니다.

단계별로 filter 연산자의 조건을 만족하지 못하면 해당 부분만 출력되고, 조건을 만족하면 다음 스트립을 출력한다.

여기서 하나 더 보이는 게 있습니다. 1이 다 처리되고 나서 2가 시작됩니다. 열 개를 한꺼번에 필터에 넣고 그 결과를 map에 넣는 게 아니에요. 값 하나가 파이프 끝까지 갔다 오고 나서 다음 값이 출발합니다.

배열 메서드를 체이닝할 때와 다른 점입니다. 배열은 filter가 전부 끝나야 map이 시작하는데, 스트림은 값 단위로 흐릅니다. 로그 순서가 그 차이를 보여줍니다.

🚨 에러도 흘러간다

두 번째 예제는 에러 상황입니다.

range(1, 8).pipe(
  map(x => x === 8 ? x.test() : x + 1),   // 8에서 일부러 에러
  tap(
    x => console.log(`tap next: ${x}`),
    err => console.error(`tap ERROR: ${err}`)
  )
).subscribe(...)

결과가 이렇습니다.

tap next: 7
result: 7
tap next: 8
result: 8
tap ERROR: TypeError: x.test is not a function
subscribe ERROR: TypeError: x.test is not a function

글의 설명이 정확합니다.

8에 해당 값은 에러 때문에 map 연산자로 값을 변환하지 못하므로 출력 결과가 없고 tap 연산자의 두번째 인자인 error 콜백 함수를 호출한 후 그 다음 subscribe 에 있는 옵저버의 error 콜백 함수를 호출한다.

에러가 값처럼 파이프를 따라 흘러갑니다. tap의 error 콜백이 먼저 받고, 그다음 subscribe의 error 콜백이 받아요.

이게 스트림 방식의 특징입니다. 보통의 코드에서는 에러가 나면 try/catch로 그 자리에서 잡는데, 스트림에서는 에러도 하나의 신호로 아래로 전달됩니다. 그래서 파이프 중간에서 로그를 남기고 끝에서 처리하는 식으로 역할을 나눌 수 있어요.

그리고 에러가 나면 스트림이 거기서 끝납니다. 위 결과에 8 다음이 없는 게 그 때문입니다. 남은 값이 있어도 더 흐르지 않아요.

📝 원문에서는 이렇게 적습니다

연산자 원형에 붙은 설명이 꼼꼼합니다.

- nextOrObserver? — 함수일 때 소스 옵저버블에서 발행하는 다음 값을 전달받는 next 콜백 함수로 동작한다. 객체이면 옵저버 객체로 다룬다.
- error, complete — 에러가 발생하거나 소스 옵저버블 구독을 완료했을 때 발생하는 콜백이다.

같은 자리에 함수를 넣을 수도 있고 객체를 넣을 수도 있다는 것. 인자 하나가 두 가지 방식을 받는 구조인데, 원형을 안 보면 모르고 지나칩니다.

세 번째 예제에서 concat으로 두 스트림을 이어 붙여 complete가 언제 불리는지 확인한 것도 꼼꼼합니다. 완료 시점은 눈에 안 보이니 직접 찍어봐야 알 수 있거든요.

큐레이터 노트

디버깅 도구를 다룬 글이라 골랐습니다.

RxJS 연산자 정리를 여러 회차에 걸쳐 이어오고 계신데, 그중 tap은 성격이 다릅니다. 결과를 만드는 연산자가 아니라 과정을 보는 연산자니까요.

3회차 큐레이션에서 이분 글의 특징으로 "누적 과정을 숫자로 대입해 적는 것"을 짚었습니다. tap은 그걸 코드로 하는 방법입니다. 머리로 따라가는 대신 로그로 찍어서 보는 것이요.

값이 흐르는 걸 눈으로 볼 수 있게 되면, 그때부터 스트림이 추상적인 개념에서 관찰 가능한 것으로 바뀝니다. 이 글이 그 전환을 다룹니다.

원문 읽으러 가기  ↗paekma09.tistory.com/12

💡 세 편을 겹쳐 읽으며

세 글이 서 있는 층이 완전히 다릅니다. 하나는 하드웨어, 하나는 브라우저와 서버 사이, 하나는 코드 안의 데이터 흐름이에요.

그런데 셋 다 데이터가 A에서 B로 갈 때 생기는 문제를 다룹니다.

김영진 님의 글에서는 속도와 단위와 오류율이 달라서 직접 연결할 수 없었습니다. 이주희 님의 글에서는 데이터가 도착하기까지 시간이 걸려서 그동안 화면이 비어 있었고요. 남기준 님의 글에서는 여러 단계를 거치는 동안 중간값이 보이지 않는 게 문제였습니다.

기다림을 다루는 같은 방법

특히 앞의 두 편이 똑같은 해법에 도달합니다.

CPU는 입출력을 기다리지 않습니다. 제어기에 맡기고 자기 일을 계속하다가, 끝나면 알림을 받아요. 브라우저도 fetch 응답을 기다리지 않습니다. 요청을 걸어두고 화면을 계속 그리다가, 데이터가 오면 그때 갱신합니다.

둘 다 "맡기고 계속한다"입니다. 하드웨어 설계에서 먼저 자리 잡은 방식이 언어 문법으로 올라온 셈이에요. asyncawait라는 단어만 새롭지, 발상은 오래된 것입니다.

그래서 하나를 알면 다른 하나가 쉬워집니다. 컴퓨터구조 시간에 배운 것이 자바스크립트를 이해하는 데 쓰이는 자리가 여기고요.

중간을 보이게 만들기

남기준 님의 tap은 조금 다른 이야기를 합니다. 잘 흘러가는 것을 눈에 보이게 만드는 일이요.

세 편에 공통으로 나오는 게 있습니다. 직접 확인하는 절차예요. 이주희 님은 코드를 쓰기 전에 콘솔에서 fetch를 쳐봤고, 남기준 님은 단계마다 로그를 찍었습니다. 김영진 님의 글에도 상태를 알리는 B·D 플래그가 나오고요.

데이터가 지나가는 길은 대개 안 보입니다. 잘 되면 결과만 보이고, 안 되면 아무것도 안 보이죠. 그래서 중간을 보는 장치를 따로 만들어야 합니다.

이번 회차에서 가져갈 것

1. 코드를 쓰기 전에 콘솔에서 먼저 쳐보기.

이주희 님이 fetch를 콘솔에서 확인하고 시작한 순서입니다. 콘솔에서 되는데 앱에서 안 되면 내 코드 문제, 콘솔에서도 안 되면 주소나 서버 문제. 원인 후보를 절반으로 줄이고 시작하는 방법입니다.

2. 목업을 걷어낼 때 "데이터 없는 순간"을 처리하기.

초기값을 빈 배열로 두는 이유입니다. 목업은 화면이 뜨는 순간 이미 있지만, 서버 데이터는 몇 백 밀리초 뒤에 옵니다. 그 사이에도 화면은 그려집니다.

3. 파이프 중간에 창문 내기.

연산자를 여러 개 이어 붙였는데 결과가 이상하면, 단계 사이에 tap을 끼워 값을 찍어보세요. 어느 단계에서 틀어졌는지가 로그 한 번에 드러납니다.

4. 차이를 없애려 하지 말고 견디게 만들기.

키보드를 CPU만큼 빠르게 만들 수는 없습니다. 대신 버퍼를 두고 플래그로 상태를 알리죠. 속도나 형식이 다른 두 시스템을 붙일 때 쓰는 기본 패턴입니다.

5. 데이터 요청은 한 파일로 모으기.

서버 주소가 한 군데 있으면 환경이 바뀔 때 거기만 고치면 됩니다. 그리고 화면 코드가 데이터 출처를 모르게 되니, 나중에 캐시를 끼우거나 목업으로 되돌리기도 쉬워집니다.


2기 4회차는 2024년 10월 말이었습니다. 학기 중간고사 대체과제가 몰리던 시기라 다들 바빴을 텐데, 세 분 다 진도를 이어갔어요.

컴퓨터구조 강의와 리액트 강의와 RxJS 교재가 각자 다른 데서 굴러가고 있었는데, 나란히 놓고 보니 같은 문제를 다루고 있었습니다. 2주에 한 번 같은 자리에 글이 모이니까 보이는 우연입니다.

좋은 글 남겨주신 김영진 님, 이주희 님, 남기준 님께 감사드립니다. 그리고 2기를 함께 채워주신 모든 멤버분들께도요! 😊

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

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


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

WRITE YOUR GROWTH

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

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

커뮤니티 둘러보기