SRL / AX FIELD NOTES TECHNICAL EXPLAINER
PUBLIC SHARE · IDENTIFIERS REDACTED

SNOWFLAKE GRAPH-A × PROJECT CONSOLE

두 그래프,
하나의 정본

구조적 사실과 의미 주장을 분리하고,
증거·시간·검토 계약으로 다시 연결한다.

27 SLIDESEXPLANATION FIRST2026.08
근거 [S-01] 09_ontology_and_tuning_assessment.md §2 · [S-02] 10_pipeline_facts_rawdata.md §4

00 / READING KEY

먼저 맞춰둘 여섯 단어

Assertion · 주장

“누가 무엇을 결정했다”처럼 참·거짓과 근거를 검토할 수 있는 문장.

Entity resolution · 엔티티 해소

여러 이름·계정·ID를 하나의 정본 개체로 연결하는 작업.

Provenance · 출처 계보

파생 데이터가 어느 원문과 변환 실행에서 왔는지 추적하는 정보.

Temporal validity · 시간 유효성

기록한 시각이 아니라, 그 사실이 실제로 유효한 기간.

Projection · 투영

표의 행을 그래프의 점(node)과 선(edge)으로 바꾸는 읽기 모델.

RAG / search · 검색 증강 생성

AI가 답하기 전에 관련 원문을 찾고, 그 근거를 문맥에 넣는 방식.

쉽게 말하면 이름을 하나로 맞추고, 어디서 왔는지 붙이고, 언제까지 맞는지 기록한 뒤, 필요한 근거만 찾아 답하게 만드는 일이다.
근거 [S-01] §2-1 Graph 3축 설계 · [C-03] 내부 모듈 감사: graph_projection.py, kg_orchestrator.py

01 / CENTRAL VERDICT

경쟁안이 아니라 서로 다른 층

GRAPH-A · OBSERVED

구조적 정본

원문 → 정규화 → “누가 썼다 / 어느 채널이다”를 재현 가능하게 연결

강점: identity · lineage · deterministic edges
+evidence
review
time
ASSERTION · PROTOTYPE

검토 가능한 주장

“누가 무엇을 결정했다 / 누구를 대신해 말했다”를 근거와 함께 기록

필요: confidence · validity · supersedes
쉽게 말하면 Graph-A는 택배 송장, Assertion은 상자 안 문서의 결론이다. 송장만으로 결론을 알 수 없고, 결론만으로 원문을 추적할 수도 없다.
근거 [S-01] §2-2 · [S-03] 11_pipeline_explained.md “Graph-A” / “Graph-B”

02 / SNAPSHOT DISCIPLINE

다섯 숫자를 같은 뜻으로 읽지 않는다

79,538

entities

CURRENT 엔티티 점의 수

사람·메시지·파일 등이 섞인 개수. 79,538개의 “업무 개념”을 뜻하지 않음.
190,445

CURRENT relations

CURRENT 관계 선의 수

별도 감사 분모 191,111과 다른 질의·스냅샷. 서로 합치거나 비율 분모로 바꾸지 않음.
19

relation types

구조 관계 유형 수

AUTHORED·IN_CHANNEL 등. DECIDED 같은 의미 술어 수가 아님.
0

assertions

ASSERTION과 EVIDENCE 행

Graph-B 의미 계층은 준비된 스키마만 있고 데이터는 비어 있었음.
38

CORE checks

해당 실행에서 모두 통과

정규화·중복·계보 검증. 의미 주장의 정확도나 일반화를 증명하지 않음.

관측 시점 2026-08-07 · “크다”는 규모, “통과했다”는 지정 검사의 결과일 뿐, 의미 온톨로지 완성을 뜻하지 않는다.

근거 [S-02] §3–§4 · [S-01] §2-2 / 메달리온 보론

03 / WHAT THE NODES ARE

Graph-A의 대부분은 원천 레코드

78,694 / 79,538

Message · File · Thread · Resource · Canvas · Channel 여섯 유형

  • 있다 누가 썼나, 어느 채널인가, 어떤 파일을 공유했나
  • 없다 어떤 결정인가, 누가 책임자인가, 무엇을 번복했나
  • 정확한 해석 “협업 기록의 그래프 복사본” 단계
쉽게 말하면 문서 보관함의 위치표는 촘촘하다. 하지만 문서 속 결재 결과를 항목별로 적은 의사결정 대장은 아직 없다.
근거 [S-01] §2-2(1)–(3) · [S-02] §4 엔티티 실측

04 / DENOMINATOR GUARD

감사 분모 191,111은 별도다

ASSERTION_ID0 / 191,111

관계 행이 의미 주장에 연결된 비율

VALID_TO114 / 191,111

관계 종료 시각이 입력된 행 · 0.06%

190,445V_COLLAB_RELATIONSHIP_CURRENT 값
191,111ASSERTION_ID·VALID_TO 충족률 별도 감사 질의 분모

Console 함의 숫자를 하나의 스냅샷처럼 섞으면 없는 주장 연결률이나 잘못된 시간 비율을 만들어낸다. 대시보드·평가 코드에 query_id, observed_at, denominator를 함께 저장해야 한다.

근거 [S-01] §2-2(3)–(4) · [S-02] §8 #5–6 · 상세 보고서 “근거·한계”

05 / TWO KINDS OF TRUTH

구조 관계와 의미 주장은 검증 질문이 다르다

구분정의 / 사실실제 질문필요 증거Console에서의 역할
Structural relation원천 스키마에서 결정론적으로 나온 연결“메시지 M은 채널 C에 있었나?”Slack message ID · channel ID정본 탐색의 뼈대
Semantic assertion원문 의미를 해석해 만든 검토 가능한 주장“담당자가 옵션 B를 결정했나?”원문 구절 · 발화자 · 시각 · 신뢰도답변의 claim 단위
Similarity edge내용 벡터가 가깝다는 탐색 힌트“비슷한 논의를 더 찾을까?”모델·버전·거리검색 후보 확장만
쉽게 말하면 같은 채널에 있었다고 같은 결론을 지지하는 것은 아니다. 문서가 비슷하다고 사실 관계가 생기는 것도 아니다.
근거 [S-01] §2-2(2)–(3) · [C-03] graph_projection.py edge_type_class

06 / END-TO-END EXAMPLE · PSEUDONYMIZED

Slack 한 건이 지식이 되는 과정

#project-alpha · 2026-08-12 10:04 KST“검토 결과 옵션 B로 진행합니다. 담당은 @project-lead입니다.” — @coordinator가 전달
01

Source event

원문·메시지 ID·채널·작성자·수정 시각 보존

02

Canonical entity

@project-lead를 person:P-017로 해소

03

Structural

M-204 AUTHORED_BY P-044
M-204 IN_CHANNEL C-003

04

Assertion

“P-017이 옵션 B 담당”
“옵션 B로 진행 결정”

중요 메시지 작성자 P-044가 결정자라는 뜻은 아니다. 전달자·원 발화자·책임 주체를 분리하려면 원문 문맥과 추가 근거가 필요하다.

근거 [S-01] §2-2(3) 가명화 역할 분리 문제 · [C-01] slack_events.py / slack_message_pipeline.py

07 / ASSERTION CONTRACT

Assertion은 문장 하나가 아니다

필드예시 값왜 필요한가
claim_contentP-017 — OWNS — option:B검토할 주장의 정확한 내용
evidence / sourceslack:M-204 · chars 11–34원문 위치로 되돌아가기
confidence0.82 · model-assisted확정 사실과 추출 후보 구분
identity@project-lead → person:P-017동명이인·별칭 오류 방지
observed_at2026-08-12T10:06+09:00시스템이 관측한 시점
valid_from / valid_to2026-08-12 / open업무상 유효 기간
review_statuspending → approvedAI 추출과 승인된 정본 분리
supersedes / contradictionA-103 supersedes A-087번복과 충돌 이력 보존

Console 함의 knowledge_triples의 SPO 문자열만으로는 승인 상태·근거 구간·유효시간·충돌 이력을 모두 표현하기 어렵다. Assertion을 독립 정본으로 두고 triple은 검색/그래프 투영으로 취급해야 한다.

근거 [S-01] §2-1 스키마 설계 · [C-02] migrations_knowledge_triples.py / triple_extractor_upsert.py

08 / TEMPORAL TRUTH

수정과 번복은 삭제가 아니다

T0 · 10:04

A-087 생성

옵션 B 진행 · pending

observed_at 10:06 · valid_from 10:04
T1 · 11:20

사람 검토

근거 확인 · approved

작성자와 결정자 분리 확인
T2 · 15:40

A-103 번복

옵션 C로 변경

A-087 valid_to 15:40 · supersedes A-087
T3 · 질문

As-of retrieval

“14시 기준?” → B
“현재?” → C

두 답 모두 근거와 시점 표시
쉽게 말하면 최신 메시지만 남기면 “그때 왜 B로 움직였나”를 설명할 수 없다. 이력은 보존하고, 현재 답에서는 유효한 주장만 선택해야 한다.
근거 [S-01] §2-2(4) · [C-02] triple_extractor_upsert.py active/superseded semantics

09 / CONSOLE PIPELINE MAP

Console 파이프라인을 모듈로 펼쳐본다

01

Slack collection

Events API · 30분 reconcile · 6시간 full sync

02

Normalize / index

slack_messages
slack_knowledge_messages

03

Fact / triple extraction

slack_facts
knowledge_triples

04

Graph projection

GraphQueryService
UnifiedProjection

05

AI Chat

legacy service
new orchestrator · KG shadow

SPO triple = Subject–Predicate–Object, 즉 P-017 — OWNS — option:B처럼 주어·술어·목적어로 사실 후보를 표현한 3요소 문장.

핵심 문제는 기능 부재가 아니라, 같은 원천이 서로 다른 테이블·스케줄·플래그를 거치는 동안 정합성 계약이 갈라진다는 점이다.

근거 [C-01] slack_events.py / slack_message_pipeline.py · [C-02] slack_sync_jobs.py / triple_extractor.py · [C-03] graph_projection.py

10 / PATH A · OPERATIONAL

실시간 운영 경로는 slack_facts로 간다

Slack eventslack_messagesSlackMessagePipelineslack_factstask / wiki debounce

정확한 현재 동작

새 메시지를 저장하고, LLM으로 fact를 추출한 뒤, 채널 설정에 따라 태스크 자동 생성과 Wiki 재빌드 판단을 실행한다.

쉬운 상황

“견적 요청드립니다”가 들어오면 몇 분 안에 업무 후보로 잡힐 수 있다. 이 경로는 운영 자동화에 가깝다.

범위·주의

slack_facts는 키워드/trigram 검색 경로에 합쳐지지만, Graph-B 승인 주장 정본과 동일하지 않다.

Console 함의 fact 추출 성공을 “온톨로지 반영 완료”로 표시하면 안 된다. 운영 액션과 지식 승격 상태를 UI에서 분리해야 한다.

근거 [C-01] slack_events.py, slack_message_pipeline.py, slack_fact_extractor.py · [C-04] ai_chat_orchestrator/_retrieve.py

11 / PATH B · KNOWLEDGE

검색 지식 경로는 별도 테이블로 간다

Slack syncslack_knowledge_messagesKnowledgeIndexerRAG / searchknowledge_triples*

정확한 현재 동작

6시간 full sync는 Slack 수집 → Wiki 증분 빌드 → RAG 인덱싱의 3단계로 등록돼 있다.

*중요한 누락

triple_extractor 호출은 이 기본 6시간 파이프라인에 없다. triple 적재는 별도 실행 경로다.

쉬운 상황

검색에는 오늘 메시지가 보이는데 SPO 그래프에는 어제 상태만 남을 수 있다. “검색 최신”과 “그래프 최신”이 갈라진다.

Console 함의 한 run 안에서 index와 assertion/triple의 watermark를 함께 기록하거나, 누락 시 그래프 답변을 자동으로 강등해야 한다.

근거 [C-02] schedulers/slack_sync_jobs.py 3 phases · triple_extractor.py 별도 batch entry

12 / DUPLICATE PATHS

두 쌍의 SSOT 후보가 병존한다

첫 경로둘째 경로갈라질 수 있는 상황필요 계약
메시지slack_messages
운영 pipeline
slack_knowledge_messages
RAG / triple source
한쪽 write 실패, edit/delete 반영 시차canonical source key · tombstone · replay
의미 후보slack_facts
운영/검색 fact
knowledge_triples
SPO / projection
서로 다른 모델·프롬프트·실행 시각assertion ID · extraction run · promotion state
쉽게 말하면 같은 주문을 두 장부에 따로 적으면, 한 장부만 수정됐을 때 어느 쪽이 현재인지 알 수 없다.

권고 지금 당장 테이블을 합치기보다, source event 하나에 canonical ID를 부여하고 두 파생 경로가 그 ID와 동일 run manifest를 공유하게 한다.

근거 [C-01] migrations_knowledge.py / slack_events.py · [C-02] migrations_knowledge_triples.py / triple_extractor.py

13 / TWO GRAPH READERS

그래프 읽기 경로도 둘이다

LEGACY

GraphQueryService

  • 관계형 FK와 일부 Slack 연결
  • 관계 질문의 path / neighbor / explain
  • 프로세스 전역 6시간 캐시
reads
into
UNIFIED · PROTOTYPE

UnifiedProjection

  • FK + wiki + semantic-flow + SPO 병합
  • GraphQueryService 결과를 어댑터로 다시 읽음
  • 동일하게 6시간 TTL

정확성 edge 종류가 한 그래프에 합쳐져 구조·유사도·주장의 증거 강도가 흐려질 수 있다.

운영 두 캐시의 빌드 시점과 source watermark가 다르면 같은 질문에 다른 그래프가 답한다.

권고 edge_class별 질의 정책과 projection run ID를 답변 근거에 포함한다.

근거 [C-03] graph_query.py · graph_projection.py · kg_orchestrator.py

14 / FLAGS × SCHEDULERS

코드가 있어도 운영에서 켜졌다는 뜻은 아니다

PROD MODULESOFF

slack_ai · wiki_graph

배포 설정에서 명시적 승인 대기
AI CHAT ORCHESTRATORDEFAULT OFF

legacy AIChatService가 기본

DB 또는 env flag가 true일 때 새 orchestrator
KG ORCHESTRATORSHADOW

기본 false

true여도 legacy 결과를 제공하고 KG는 비교 로그
SCHEDULER6 h / 30 m

full sync / recent reconcile

스케줄러·pipeline gate·token이 모두 있어야 실행
실제 상황 개발 화면에서 SPO 검색이 잘돼도 prod에서는 모듈이 mount되지 않을 수 있다. 반대로 30분 reconcile로 메시지는 들어와도 triple은 갱신되지 않을 수 있다.

Console 함의 배포 리포트에 “코드 존재” 대신 router mounted · effective flag · last successful run · source/index/triple watermark를 함께 표시한다.

근거 [C-04] modules_config_prod.py · ai_chat_orchestrator/__init__.py · ai_chat_service/__init__.py · schedulers/job_registry.py

15 / RETRIEVAL POLICY

AI Chat은 근거 강도를 구분해야 한다

1

Structured first

정본 ID·멤버십·상태는 구조 조회

answerable fact
2

Approved assertions

유효하고 승인된 주장 + evidence bundle

claim-level citation
3

RAG / search

원문 후보를 찾아 미확정 문맥 보강

quote with caveat
4

Similarity

근접 문서를 탐색 후보로만 확장

never promote alone

권장 답변 형태

현재 승인된 주장 옵션 C로 변경됨 [A-103 · approved · valid 15:40–]

이전 상태 10:04–15:40에는 옵션 B [A-087 · superseded]

검색 보조 관련 논의 3건 [검색 후보 · 사실 승격 전]

근거 [C-03] kg_orchestrator.py retrieval layers · [S-01] §2-2(3) 의미 계층 해석

16 / EVALUATION · LIMITS FIRST

점수보다 측정 조건을 먼저 읽는다

샘플

세 실행 모두 벤더가 이미 본 동일 28문항. 미공개 holdout이 아니다.

반복

7.04는 28×1, 7.38·7.12는 28×3.

채점

7.04는 수동 4축, 7.38·7.12는 동일 LLM judge. 7.04와 나머지는 직접 순위 비교 불가.

조회 경로

7.04는 CORE 직접 SQL, 벤더 에이전트는 semantic view. 동일 조건 재현이 아님.

UNTUNED · 28×17.04/8
V2 · 28×37.38/8
V4 FINAL · 28×37.12/8

허용되는 결론: V2 → V4는 동일 채점·동일 28×3 전체세트에서 하락. 7.04와 7.12는 “같은 성능 구간의 신호”일 뿐 우열 증거가 아니다.

근거 [S-04] 07_cli_untuned_baseline_result.md §1–§2 · [S-02] §6 평가 이력

17 / IMPLEMENTATION ≠ GENERALIZATION

튜닝 구현과 일반화 증명은 별개다

검증된 구현

실제 기능은 있다

  • 파일 공유 위치를 모호성 상태와 함께 찾는 도구
  • 기간형 Slack·Gmail 근거를 모으는 도구
  • 출처 의무·고유명사 환각 억제·시간 완결성 규칙
아직 없는 증명

새 문제에도 좋아지는가

  • 실패 문항을 본 뒤 규칙과 전용 도구 추가
  • 부분집합 재측정과 전체세트 결과가 혼재
  • 동일 28×3에서 V2 7.38 → V4 7.12
쉽게 말하면 답안지를 베낀 코드는 아니다. 다만 연습문제를 보고 만든 풀이법이 새 시험에도 통하는지는 아직 안 쟀다.

Console 함의 튜닝을 출시하려면 unseen holdout, 반복 실행, 동일 채점기, claim·identity·temporal 지표를 별도로 통과해야 한다.

근거 [S-01] §1-1–§1-5 · [S-04] §2 한계

18 / TARGET ARCHITECTURE

목표는 source에서 retrieval까지 한 계약

L0

Source event

payload · hash · edit/delete · ingest run

L1

Canonical entity

identity · alias · source key · provenance

L2

Structural relation

deterministic edge · typed source record

L3

Assertion

claim · evidence · confidence · validity

L4

Review / promotion

pending · approved · rejected · superseded

L5

Retrieval

as-of · permission · claim citation · fallback

원문은 immutable · 엔티티는 canonical · 구조 edge는 deterministic · 주장은 reviewable · 검색은 permission-aware

근거 [S-01] §2-1 · 상세 보고서 “목표 구조” · [C-03] current permission gates

19 / MODULE CHANGE SET

모듈마다 하나의 계약을 고친다

01

Slack collection

canonical source event ID · edit/delete tombstone · idempotent replay

02

Indexer

source/index/triple watermark · run manifest · drift alert

03

triple_extractor

제약 술어 · typed validation · entity resolution · model/prompt version

04

upsert / assertion

evidence span · cardinality · valid time · review · supersedes

05

projection

structural / assertion / similarity 분리 · projection run ID

06

AI Chat / eval

structured-first · claim citation · unseen holdout · split metrics

원칙 모델 교체보다 먼저 경계·식별자·시간·승격 상태를 고정한다. 기존 fail-secure 권한 게이트는 유지한다.

근거 [C-01–C-04] 내부 모듈 감사 · 상세 보고서 “MODULE-BY-MODULE CHANGE SET”

20 / ROADMAP · P0

먼저 관측 가능한 기준선을 만든다

P0

BASELINE / INSTRUMENT

기능 추가 전에 두 경로의 실제 상태를 같은 시각표로 본다.

현재 이슈

메시지·fact·triple·projection의 최신 시각이 분리돼 있다.

변경 모듈

scheduler · indexer · extractor · AI Chat logging

Migration / backfill

기존 행은 변경하지 않고 run manifest와 watermark inventory 생성.

Validation

동일 source event가 두 메시지 테이블과 두 의미 테이블에서 추적되는지 50개 표본 확인.

Promotion gate

재현 가능한 baseline + source coverage + stale-path report.

Rollback

관측 코드가 지연/오류를 만들면 write hook 중단, read-only audit로 복귀.

근거 [C-01–C-04] 현재 경로 감사 · 상세 보고서 P0 권고

21 / ROADMAP · P1

원천과 신원을 정본화한다

P1

CANONICALIZE / REPLAY

두 Slack 테이블을 지우지 않고 동일 source event 계약 아래 묶는다.

현재 이슈

dual-write, edit/delete 시차, 별칭·핸들 누락 가능성.

변경 모듈

Slack collector · normalizer · identity resolver · indexer

Migration / backfill

canonical_event_id, source hash, tombstone, timezone 정규화. 과거 메시지 replay 가능하게 backfill.

Validation

중복·누락·edit/delete 재생, identity collision, as-of 시나리오.

Promotion gate

lineage 100%와 합의한 identity 정확도 목표를 독립 표본에서 통과.

Rollback

source count·hash 불일치 또는 identity merge 오염 시 새 canonical read 비활성, 구 경로 유지.

근거 [S-01] §2-1 / §2-2(4) · [C-01] dual write · [S-04] §4 alias / CURRENT view 발견

22 / ROADMAP · P2

주장을 추출하고 검토한다

P2

ASSERTIONS / REVIEW

SPO 후보를 바로 사실로 쓰지 않고 검토 가능한 Assertion으로 승격한다.

현재 이슈

Snowflake Assertion 0건, Console triple에는 승인·근거 구간·충돌 계약이 부족.

변경 모듈

triple_extractor · upsert · assertion store · reviewer UI

Migration / backfill

고위험 술어부터 historical extraction. 모든 후보는 pending, 원문 span 필수.

Validation

claim precision · evidence accuracy · identity accuracy · temporal consistency 분리 측정.

Promotion gate

근거 연결 100% + 승인된 고위험 술어 precision 목표 통과.

Rollback

근거 없는 claim 또는 private-source leakage 1건이면 자동 승격 중단, 검색 후보로만 강등.

근거 [S-01] §2-2(3) · [C-02] triple schema/upsert · 상세 보고서 P2 권고

23 / ROADMAP · P3

shadow에서 단계적으로 승격한다

P3

ROUTE / PROMOTE

새 KG 경로가 legacy를 조용히 대체하지 않게 질문군별로 승격한다.

현재 이슈

prod 모듈 OFF, 새 orchestrator 기본 OFF, KG는 shadow 비교 단계.

변경 모듈

AI Chat router · orchestrator · projection · feature flags · eval

Migration / backfill

approved assertion projection 생성, 캐시 warm-up, 기존 검색 결과와 dual-run.

Validation

unseen holdout × 반복 × 동일 채점. 권한·as-of·번복·지연 시나리오 포함.

Promotion gate

질문군별 품질·latency·permission gate 통과 후 5% → 25% → 100%.

Rollback

회귀·stale watermark·권한 오류가 임계치를 넘으면 즉시 legacy serve, shadow 유지.

근거 [C-03] true shadow contract · [C-04] effective flags · [S-04] 평가 한계

24 / DECISION REQUEST

오늘 결정할 것은 세 가지

  1. 01

    계층 분리

    structural relation · assertion · similarity를 서로 다른 증거 강도로 운영한다.

  2. 02

    단일 원천 계약

    두 Slack 저장 경로와 두 의미 경로를 canonical_event_id와 run manifest로 묶는다.

  3. 03

    증거 기반 승격

    P0→P3 gate와 rollback을 승인하고, 미공개 holdout 전에는 일반화를 주장하지 않는다.

STRUCTURE IS THE SPINE.
ASSERTIONS ARE REVIEWABLE CLAIMS.

근거 [S-01–S-04] 내부 평가 문서 · [C-01–C-04] 내부 모듈 감사

25 / TRACEABILITY

근거와 남은 한계

S-01

09_ontology_and_tuning_assessment.md

Graph-A/Assertion 실측 해석, 시간 필드, 튜닝 판정.

S-02

10_pipeline_facts_rawdata.md

79,538 · 190,445 · 19종 · 38 checks · 평가 이력의 사실 대장.

S-03

11_pipeline_explained.md

RAW→CORE→Graph-A→Agent→Graph-B의 비전공자 설명.

S-04

07_cli_untuned_baseline_result.md

7.04/8, 28×1, 수동 채점과 비교 한계.

C-01 / C-02

Console ingestion / extraction audit

Slack dual-write, fact/triple, 6시간 sync의 실제 호출 경로.

C-03 / C-04

Console graph / runtime audit

두 projection, shadow mode, prod module·orchestrator·scheduler gates.

이 덱이 증명하지 않는 것

  • Snowflake와 Console의 전체 운영 성능·비용 우열
  • 191,111 감사 분모와 190,445 CURRENT 관계가 동일 스냅샷이라는 주장
  • 7.04와 7.12의 직접적인 우열
  • 아직 실행하지 않은 target gate의 달성 여부

KEYBOARD / TOUCH

발표 제어

← / →
이전 / 다음
PgUp / PgDn
이전 / 다음
Space
다음
Home / End
처음 / 끝
O
오버뷰
F
전체 화면
P
인쇄
? / H
도움말
Swipe
모바일 이동