본문으로 이동
모든 코스
MIT시장과 정책180분4 모듈
참고 자료참고 코드 2024-12-10 · 릴리스 2022

도시 시나리오가 지도와 지표로 움직이는 구조 읽기

URL 선택, WebSocket 메시지, Redux 상태, 지도 렌더링을 따라가며 참여형 도시 시뮬레이션의 구성요소를 배웁니다.

블록 하나를 주거에서 공원으로 바꾸면, 어떤 데이터와 가정이 결과 화면까지 이동할까요?

프로젝트와 최신성

GPL-3.0 CityScopeJS의 핵심 데이터 흐름만 읽습니다. 기존 코드를 배포하는 과제가 아니라 접근성·비용·공정성 지표를 학생이 새로 정의하는 설계 과정입니다.

CityScope 연구 개념은 살아 있지만 이 프런트엔드의 최신 릴리스는 2022년이고 기본 브랜치 마지막 의미 있는 코드는 2024년입니다. 전체 복제 대신 데이터 흐름을 읽고 작은 독립 시뮬레이터를 설계합니다.

먼저 볼 장면

멋진 3D 지도만 복제하고 계산 서버를 놓치기

이 저장소는 통합 프런트엔드입니다. 실시간 CityIO 백엔드와 도시별 데이터·모듈이 없으면 같은 결과가 나오지 않으므로 화면과 계산 책임을 나눠 봅니다.

데이터 흐름

블록 변경 메시지가 지도로 돌아오는 길

1시나리오 URL도시 테이블 선택
2CityIO 연결실시간 메시지 송수신
3Redux 상태현재 도시 데이터 보관
4지도·지표상태를 화면으로 표현
0/4

‘다음 단계’를 눌러 입력이 결과가 되는 길을 따라가세요.

구성요소 대화

지도가 비어 있을 때 구성요소의 대화

‘다음 단계’를 눌러 구성요소의 첫 메시지를 열어 보세요.

코드 워크스루

관심 분야의 문제를 정하고, 코드와 데이터를 읽고, AI 실험을 검증한 뒤 결과를 발표합니다.

40분

주소에서 도시 시나리오 고르기

URL 쿼리를 읽어 CityScope 편집기와 CityIO 목록 화면 중 하나를 고르는 작은 라우터를 봅니다.

먼저 떠올릴 비유

공연 티켓의 회차 번호가 어느 무대 문을 열지 정하는 것과 같습니다.

핵심 판단

주소에 `cityscope` 키가 있으면 그 값을 테이블 이름으로 전달하고, 없으면 일반 CityIO 화면을 엽니다.

직접 해보기

`?cityscope=seoul-school-zone` 같은 주소 세 개와 각 주소가 열 화면을 표로 만듭니다.

남길 증거

URL→도시 테이블→화면 선택 흐름도

코드 용어
저장소의 실제 코드이 파일에서 확인
src/App.js1cb2e63
    const keys = Object.keys(parsed);

    if (keys.includes("cityscope")) {
      selectView("cityscopejs", parsed.cityscope);
    } else {
      setViewSelectorState("cityio");
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
코드가 하는 일
  1. 1

    해석한 URL에서 모든 키 이름을 꺼냅니다.

  2. 2

    `cityscope` 키가 있으면 그 값으로 편집기 화면을 선택합니다.

  3. 3

    없으면 CityIO 목록 화면을 기본으로 선택합니다.

새 상황에 적용하기

주소에 `?cityscope=gangnam`이 있지만 목록 화면만 열립니다.

가장 먼저 볼 곳은 어디인가요?

45분

실시간 도시 데이터 구독하기

WebSocket 연결이 열리면 테이블 이름을 담은 `LISTEN` 메시지를 보내는 흐름을 읽습니다.

먼저 떠올릴 비유

라디오 주파수를 맞춘 뒤 원하는 채널을 계속 듣는 것과 같습니다.

핵심 판단

연결은 공유되고 끊기면 재연결을 시도합니다. 열린 뒤에만 테이블 구독 메시지를 보내야 합니다.

직접 해보기

연결 전·열림·메시지 수신·재연결 네 상태에서 사용자에게 보여 줄 문구를 씁니다.

남길 증거

연결 상태별 오류·복구 카드

코드 용어
저장소의 실제 코드이 파일에서 확인
src/Components/CityIO/index.js1cb2e63
  const { sendJsonMessage, lastJsonMessage, readyState } = useWebSocket(
    cityIOSettings.cityIO.websocketURL,
    {
      share: true,
      shouldReconnect: () => true,
    },
  )

  // When the WS connection state (readyState) changes to OPEN,
코드가 하는 일
  1. 1

    훅은 메시지 보내기, 마지막 메시지, 연결 상태를 돌려줍니다.

  2. 2

    서버 주소는 공통 설정에서 읽습니다.

  3. 3

    연결을 구성요소끼리 공유하고 끊기면 다시 연결하도록 설정합니다.

새 상황에 적용하기

브라우저가 오프라인이 됐다가 돌아왔지만 지도가 이전 값에 멈췄습니다.

어떤 흐름을 점검해야 하나요?

45분

한 도시 상태를 여러 화면이 함께 쓰기

Redux slice가 도시 데이터, 로딩 완료 여부, 테이블 이름을 갱신하는 작은 책임을 봅니다.

먼저 떠올릴 비유

공연장 중앙 전광판 하나를 지도·메뉴·차트가 함께 읽는 것과 같습니다.

핵심 판단

세 reducer는 각자 하나의 상태 필드만 바꿉니다. 메시지는 도착했는데 화면이 안 바뀌면 dispatch와 이 저장소 사이를 추적합니다.

직접 해보기

`TABLE_SNAPSHOT`을 받았을 때 바뀌어야 할 세 상태와 이를 읽는 화면을 연결합니다.

남길 증거

메시지→Redux 상태→화면 의존성 지도

코드 용어
저장소의 실제 코드이 파일에서 확인
src/redux/reducers/cityIOdataSlice.js1cb2e63
  reducers: {
    updateCityIOdata: (state, action) => {
      state.cityIOdata = action.payload;
    },
    toggleCityIOisDone: (state, action) => {
      state.cityIOisDone = action.payload;
    },
    updateCityIOtableName: (state, action) => {
      state.cityIOtableName = action.payload;
    },
  },
코드가 하는 일
  1. 1

    `updateCityIOdata`는 메시지의 도시 내용을 저장합니다.

  2. 2

    완료 토글은 화면을 그릴 준비가 됐는지 저장합니다.

  3. 3

    세 번째 규칙은 현재 연결할 도시 테이블 이름을 보관합니다.

새 상황에 적용하기

WebSocket 로그에는 새 데이터가 보이지만 차트가 바뀌지 않습니다.

가장 먼저 추적할 것은 무엇인가요?

50분

화면과 계산의 경계를 보고 작게 다시 설계하기

데이터 준비 여부에 따라 CityIO 연결, 지도, 메뉴, 차트를 조건부로 여는 화면 구조를 읽습니다.

먼저 떠올릴 비유

무대 뒤 세트가 준비되기 전에 커튼을 열지 않는 공연 운영과 같습니다.

핵심 판단

프런트엔드는 테이블이 있으면 데이터를 구독하고, 완료 플래그가 참일 때만 시각 요소를 엽니다. 도시 지표 계산 자체는 다른 서비스와 모듈에 있습니다.

직접 해보기

원본 전체 대신 학교 주변 보행 접근성 한 지표만 계산하는 입력·규칙·출력 프로토타입을 정합니다.

남길 증거

단일 도시 질문용 독립 시뮬레이터 명세

코드 용어
저장소의 실제 코드이 파일에서 확인
src/views/CityScopeJS/index.js1cb2e63
      {/* if we got a cityIO table name, start cityIO module */}
      {tableName && <CityIO tableName={tableName} />}
      {/* if cityIO module is done loading, start the CSjs app */}
      {cityIOisDone && (
        <>
          <div  style={{ height: '100vh', width: '100vw', position: 'relative', overflow: 'hidden' }}>
            <DeckGLMap />
          </div>
          <MenuContainer />
          <VisContainer />
코드가 하는 일
  1. 1

    테이블 이름이 있을 때만 CityIO 연결 구성요소를 시작합니다.

  2. 2

    데이터 로딩 완료 플래그가 참일 때만 앱 시각 요소를 엽니다.

  3. 3

    지도, 메뉴, 지표 차트가 서로 다른 구성요소로 나뉩니다.

새 상황에 적용하기

지도 UI는 복제했지만 어떤 시나리오를 선택해도 지표가 없습니다.

가장 가능성 높은 빠진 부분은 무엇인가요?

이번 코스의 결과물

한 도시 문제의 단순화된 시나리오 흐름도와 프로토타입 명세

제출 전 확인

  • 이 프런트엔드가 참고형 레거시임을 표시했다.
  • URL·연결·상태·화면 흐름을 구분했다.
  • 백엔드와 계산 모듈을 원본 프런트엔드의 기능으로 오해하지 않았다.
  • 새 프로토타입은 도시 문제 하나와 지표 하나로 제한했다.

7분 세미나 질문

도시 시뮬레이터의 숫자가 정책 참여를 돕는 순간과 오히려 선택을 숨기는 순간은 언제인가요?

다음 코스

AI 기업의 ‘책임 있다’는 말을 증거로 바꾸기

과정 보기