Ver3.5 ๐ CSV ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ๋ณํํ๋ ์์ ์ ๋ณต ์์ค์ฝ๋ ๊ฐ์ด๋

๐ CSV ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ๋ณํํ๋ ์์ ์ ๋ณต ์์ค์ฝ๋ ๊ฐ์ด๋
Python ยท JavaScript ยท Java ยท Go ยท PHP ๋ค๊ตญ์ด ์ค์ ์์ + ์ฃ์ง์ผ์ด์ค ์๋ฒฝ ๋์ ๐ก
๐ค 01. CSV์ JSON, ์๋ค ๋๋์ฒด ๋ญ์ผ?
๊ฐ๋ฐํ๋ค ๋ณด๋ฉด ๋ฐ์ดํฐ ํ์ ๋๋ฌธ์ ๋จธ๋ฆฌ ์ธ๋งค๋ ์๊ฐ์ด ๊ผญ ํ ๋ฒ์ฉ ์จ๋ค.
"์์
์์ ๋ฝ์ CSV ํ์ผ์ธ๋ฐ, API๋ JSON๋ง ๋ฐ๋๋ค๊ณ ?!" ๐ซ
์ด๋ฐ ์ํฉ, ํ ๋ฒ์ฏค ๊ฒช์ด๋ดค์ง? ์ค๋์ ์ด ๋ ์น๊ตฌ๋ฅผ ์์ ํ ์ ๋ณตํด๋ณด์.
CSV(Comma-Separated Values)๋ ๋ง ๊ทธ๋๋ก ์ผํ๋ก ๊ฐ์ ๊ตฌ๋ถํ๋ ํ
์คํธ ํ์ผ์ด์ผ.
์์
์์ "๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ์ ์ฅ โ CSV" ํ๋ฉด ๋ฐ๋ก ๋์ค๋ ๊ทธ ํ์ผ.
๋ฐ์ดํฐ๋ฒ ์ด์ค ๋คํ, ํต๊ณ ๋ฐ์ดํฐ, ํ์ ๋ชฉ๋ก ๊ฐ์ ํ ํํ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ์ ํต์ ์ผ๋ก ๋ง์ด ์จ์์ด.
JSON(JavaScript Object Notation)์ 2000๋
๋ ์ด๋ฐ ๋๊ธ๋ผ์ค ํฌ๋กํฌ๋๊ฐ ์ ๋ฆฝํ ๋ฐ์ดํฐ ๊ตํ ํฌ๋งท์ด์ผ.
์ด๋ฆ์ JavaScript๊ฐ ๋ค์ด๊ฐ์ง๋ง ์ฌ์ค์ ์ธ์ด ๋
๋ฆฝ์ ์ธ ๋ฒ์ฉ ํฌ๋งท์ผ๋ก ์๋ฆฌ์ก์๊ณ ,
ํ์ฌ REST API, NoSQL DB, ์ค์ ํ์ผ ๋ฑ ๊ฑฐ์ ๋ชจ๋ ๊ณณ์์ ์ฐ์ด๋ ์ฌ์ค์์ ํ์ค์ด์ผ. ๐
โ ํ์ผ ํฌ๊ธฐ ์์
โ ์์ ์ง์ ์ด๊ธฐ ๊ฐ๋ฅ
โ ์ฌ๋์ด ์ฝ๊ธฐ ์ฌ์
โ ๊ณ์ธต ๊ตฌ์กฐ ํํ ๋ถ๊ฐ
โ ๋ฐ์ดํฐ ํ์ ๊ตฌ๋ถ ์์
โ ํ์ค ์คํ์ด ๋์จํจ
โ ๊ณ์ธต ๊ตฌ์กฐ ํํ ๊ฐ๋ฅ
โ ๋ฐ์ดํฐ ํ์ ๋ช ํ
โ API ํ์ค ํฌ๋งท
โ ํ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ๋ถ
โ CSV๋ณด๋ค ํ์ผ ํฌ๊ธฐ ํผ
โ ์์ ์ง์ ์ด๊ธฐ ๋ถํธ
๐ข 02. ๋ณํ์ด ์ ํ์ํ์ง โ ์ค๋ฌด ์๋๋ฆฌ์ค ์ด์ ๋ฆฌ
"๊ทธ๋ฅ ์ฒ์๋ถํฐ JSON์ผ๋ก ์ฐ๋ฉด ๋์ง ์๋?" ๋ผ๊ณ ์๊ฐํ ์ ์๋๋ฐ,
ํ์ค์ ๊ทธ๋ ๊ฒ ํธ๋ฝํธ๋ฝํ์ง ์์. ๐
์ค๋ฌด์์ CSV โ JSON ๋ณํ์ด ํ์ํ ์ํฉ์ ๋ณด์.
์ค๋๋ ERP, ํ๊ณ ์์คํ ๋ค์ ๋๋ถ๋ถ CSV๋ก ๋ฐ์ดํฐ๋ฅผ ๋ด๋ณด๋ด. ๊ทผ๋ฐ ์๋ก ๋ง๋๋ API ์๋ฒ๋ JSON๋ง ๋ฐ๋ ์ํฉ. ์ด ๊ฐญ์ ๋ฉ์์ผ ํด.
๋ฐ์ดํฐ ํ์์ ์์ ๋ก ์ ๋ฆฌํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฐํ API์ ๋ฃ์ด์ผ ํ ๋. ๊ธฐํ์๊ฐ CSV๋ก ์ฃผ๋ฉด ๊ฐ๋ฐ์๊ฐ JSON์ผ๋ก ๋ณํํด์ DB์ ๋ฃ๋ ํ๋ฆ์ด ํํด.
์๋น์ค ์ด์ ์ ๊ธฐ์กด DB ๋ฐ์ดํฐ๋ฅผ CSV๋ก ๋คํ โ ์ ์์คํ API์ JSON์ผ๋ก ์ ๋ก๋ํ๋ ํจํด์ด ๋งค์ฐ ์ผ๋ฐ์ ์ด์ผ.
๊ณต๊ณต๋ฐ์ดํฐํฌํธ, ํต๊ณ์ฒญ ๋ฑ์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ ๋๋ถ๋ถ CSV์ผ. ์ด๊ฑธ ์น ์ฑ์์ ์ฐ๋ ค๋ฉด JSON์ผ๋ก ๋ณํ์ด ํ์ํด.
์ฌ๋ฅ๋ท์ฒ๋ผ ๋ค์ํ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ํ๋ซํผ์์๋ ํ์ ๋ฐ์ดํฐ, ๊ฑฐ๋ ๋ด์ญ ๋ฑ์ CSV๋ก ๋ฐ์์ JSON API๋ก ์ฒ๋ฆฌํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์.
๐ฌ 03. CSV ๊ตฌ์กฐ ์์ ํด๋ถ โ ์๊ณ ๋ณํํ์
๋ณํ ์ฝ๋๋ฅผ ์ง๊ธฐ ์ ์ CSV๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง ์ ๋๋ก ์์์ผ ํด.
"๊ทธ๋ฅ ์ผํ๋ก ๊ตฌ๋ถํ๋ ๊ฑฐ ์๋?" ๋ผ๊ณ ์๊ฐํ๋ฉด ๋์ค์ ์ฃ์ง์ผ์ด์ค์์ ํฐ์ง๋ค. ๐ฃ
๐ ๊ธฐ๋ณธ ๊ตฌ์กฐ
<span class="tx-comment"># ๊ธฐ๋ณธ CSV ๊ตฌ์กฐ</span>
<span class="tx-string">name,age,city,score</span>
<span class="tx-string">Alice,30,Seoul,95.5</span>
<span class="tx-string">Bob,25,Busan,88.0</span>
<span class="tx-string">Carol,28,Incheon,92.3</span>
์ฒซ ๋ฒ์งธ ์ค์ด ํค๋(Header)์ผ โ ๊ฐ ์ปฌ๋ผ์ ์ด๋ฆ์ ์ ์ํด.
๋ ๋ฒ์งธ ์ค๋ถํฐ๊ฐ ๋ฐ์ดํฐ ํ(Row)์ด๊ณ , ๊ฐ ๊ฐ์ ์ผํ๋ก ๊ตฌ๋ถ๋ผ.
โ ๏ธ ์์์ผ ํ CSV์ ํจ์ ๋ค
"Seoul, Gangnam",30,Aliceโ ๊ฐ์ ์ผํ๊ฐ ํฌํจ๋๋ฉด ํฐ๋ฐ์ดํ๋ก ๊ฐ์ธ์ผ ํด. ์ด๊ฑธ ์ฒ๋ฆฌ ๋ชปํ๋ฉด ํ์ฑ์ด ๊นจ์ ธ.
"์ฒซ ๋ฒ์งธ ์ค๋ ๋ฒ์งธ ์ค",30,Aliceโ ๋ฉํฐ๋ผ์ธ ๊ฐ๋ ํฐ๋ฐ์ดํ๋ก ๊ฐ์ธ. ์ด๊ฑธ ๋ชจ๋ฅด๋ฉด ํ ํ์ฑ์ด ์์ ํ ๋ง๊ฐ์ ธ.
"๊ทธ๋ ""์๋
""์ด๋ผ๊ณ ๋งํ๋ค",30โ ๊ฐ ์์ ํฐ๋ฐ์ดํ๊ฐ ์์ผ๋ฉด ๋ ๋ฒ ์จ์ ์ด์ค์ผ์ดํํด.
"" = "
ํนํ ์๋์ฐ ์์ ์์ ์ ์ฅํ CSV๋ EUC-KR(CP949)์ธ ๊ฒฝ์ฐ๊ฐ ๋ง์์ ์ด ๋ ์ธ์ฝ๋ฉ ์ง์ ํ์!
\ufeff)๊ฐ ๋ถ์ด.์ด๊ฑธ ์ฒ๋ฆฌ ์ ํ๋ฉด ์ฒซ ๋ฒ์งธ ์ปฌ๋ผ ์ด๋ฆ์ด ์ด์ํ๊ฒ ํ์ฑ๋ผ.
๐๏ธ 04. JSON ๊ตฌ์กฐ ์์ ํด๋ถ โ ๋ชฉ์ ์ง๋ฅผ ์์์ผ ๊ธธ์ด ๋ณด์ธ๋ค
CSV๋ฅผ JSON์ผ๋ก ๋ณํํ ๋ "์ด๋ค ๋ชจ์์ JSON์ผ๋ก ๋ง๋ค ๊ฒ์ธ๊ฐ"๋ฅผ ๋จผ์ ๊ฒฐ์ ํด์ผ ํด.
์ฃผ๋ก ์ฐ์ด๋ ํจํด์ด ๋ช ๊ฐ์ง ์๊ฑฐ๋ .
๐ ํจํด 1: ๋ฐฐ์ด of ๊ฐ์ฒด (๊ฐ์ฅ ์ผ๋ฐ์ )
<span class="tx-comment">// ๊ฐ ํ์ด ํ๋์ ๊ฐ์ฒด๊ฐ ๋๋ ํจํด</span>
<span class="tx-keyword">[</span>
<span class="tx-keyword">{</span> <span class="tx-string">"name"</span>: <span class="tx-string">"Alice"</span>, <span class="tx-string">"age"</span>: <span class="tx-num">30</span>, <span class="tx-string">"city"</span>: <span class="tx-string">"Seoul"</span> <span class="tx-keyword">}</span>,
<span class="tx-keyword">{</span> <span class="tx-string">"name"</span>: <span class="tx-string">"Bob"</span>, <span class="tx-string">"age"</span>: <span class="tx-num">25</span>, <span class="tx-string">"city"</span>: <span class="tx-string">"Busan"</span> <span class="tx-keyword">}</span>,
<span class="tx-keyword">{</span> <span class="tx-string">"name"</span>: <span class="tx-string">"Carol"</span>, <span class="tx-string">"age"</span>: <span class="tx-num">28</span>, <span class="tx-string">"city"</span>: <span class="tx-string">"Incheon"</span> <span class="tx-keyword">}</span>
<span class="tx-keyword">]</span>
๊ฐ์ฅ ํํ๊ณ ์ง๊ด์ ์ธ ํจํด. API ์๋ต, DB ์ฝ์ ๋ฑ ๋๋ถ๋ถ์ ์ฉ๋์ ์ ํฉํด.
๐ ํจํด 2: ๋ํผ ๊ฐ์ฒด ํฌํจ
<span class="tx-comment">// ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๋ด๋ ํจํด</span>
<span class="tx-keyword">{</span>
<span class="tx-string">"total"</span>: <span class="tx-num">3</span>,
<span class="tx-string">"data"</span>: <span class="tx-keyword">[</span>
<span class="tx-keyword">{</span> <span class="tx-string">"name"</span>: <span class="tx-string">"Alice"</span>, <span class="tx-string">"age"</span>: <span class="tx-num">30</span> <span class="tx-keyword">}</span>,
<span class="tx-keyword">{</span> <span class="tx-string">"name"</span>: <span class="tx-string">"Bob"</span>, <span class="tx-string">"age"</span>: <span class="tx-num">25</span> <span class="tx-keyword">}</span>
<span class="tx-keyword">]</span>
<span class="tx-keyword">}</span>
๐ ํจํด 3: ํค-๊ฐ ๋งต (ํน์ ์ปฌ๋ผ์ ํค๋ก)
<span class="tx-comment">// name์ ํค๋ก ์ฌ์ฉํ๋ ํจํด</span>
<span class="tx-keyword">{</span>
<span class="tx-string">"Alice"</span>: <span class="tx-keyword">{</span> <span class="tx-string">"age"</span>: <span class="tx-num">30</span>, <span class="tx-string">"city"</span>: <span class="tx-string">"Seoul"</span> <span class="tx-keyword">}</span>,
<span class="tx-string">"Bob"</span>: <span class="tx-keyword">{</span> <span class="tx-string">"age"</span>: <span class="tx-num">25</span>, <span class="tx-string">"city"</span>: <span class="tx-string">"Busan"</span> <span class="tx-keyword">}</span>
<span class="tx-keyword">}</span>
ํน์ ํค๋ก ๋น ๋ฅด๊ฒ ์กฐํํด์ผ ํ ๋ ์ ์ฉํด. ๋จ, ํค๊ฐ ์ ๋ํฌํด์ผ ํด.
number๋ก, ๋ถ๋ฆฌ์ธ์ boolean์ผ๋ก ํ์
๋ณํ์ ํด์ค์ผ ์ ๋๋ก ๋ JSON์ด ๋ผ. ์ด ์ฒ๋ฆฌ๋ฅผ ์ ํ๋ฉด "age": "30"์ฒ๋ผ ์ซ์๊ฐ ๋ฌธ์์ด๋ก ๋ค์ด๊ฐ๋ฒ๋ ค.
๐ 05. Python์ผ๋ก CSV โ JSON ๋ณํ (๊ธฐ์ด ~ ๊ณ ๊ธ)
Python์ CSV ๋ณํ์ ์์ด์ ์ง์ง ์ต๊ฐ์ด์ผ. ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ง์ผ๋ก๋ ์ถฉ๋ถํ๊ณ ,
pandas๊น์ง ์ฐ๋ฉด ๋ชป ํ๋ ๊ฒ ์์ด. ๋จ๊ณ๋ณ๋ก ์ดํด๋ณด์!
๐ฐ ๋ฐฉ๋ฒ 1: ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ง ์ฌ์ฉ (csv + json)
<span class="tx-keyword">import</span> csv
<span class="tx-keyword">import</span> json
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_basic</span>(csv_file_path, json_file_path, encoding=<span class="tx-string">'utf-8'</span>):
<span class="tx-string">"""
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ CSV โ JSON ๋ณํ ํจ์
์ฒซ ๋ฒ์งธ ํ์ ํค๋๋ก ์ฌ์ฉํ์ฌ ๋ฐฐ์ด of ๊ฐ์ฒด ํํ๋ก ๋ณํ
"""</span>
result = []
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_file_path, <span class="tx-string">'r'</span>, encoding=encoding, newline=<span class="tx-string">''</span>) <span class="tx-keyword">as</span> csv_file:
<span class="tx-comment"># DictReader: ์ฒซ ํ์ ํค๋๋ก ์๋ ์ธ์</span>
reader = csv.DictReader(csv_file)
<span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader:
<span class="tx-comment"># OrderedDict โ ์ผ๋ฐ dict๋ก ๋ณํ</span>
result.append(<span class="tx-func">dict</span>(row))
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(json_file_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> json_file:
json.<span class="tx-func">dump</span>(result, json_file, ensure_ascii=<span class="tx-keyword">False</span>, indent=<span class="tx-num">2</span>)
<span class="tx-func">print</span>(<span class="tx-string">f"โ
๋ณํ ์๋ฃ: {len(result)}๊ฐ ํ ์ฒ๋ฆฌ๋จ"</span>)
<span class="tx-keyword">return</span> result
<span class="tx-comment"># ์ฌ์ฉ ์์</span>
data = <span class="tx-func">csv_to_json_basic</span>(<span class="tx-string">'input.csv'</span>, <span class="tx-string">'output.json'</span>)
ensure_ascii=False๋ฅผ ๊ผญ ๋ฃ์ด์ค! ์ด๊ฒ ์์ผ๋ฉด ํ๊ธ์ด \uD55C\uAE00 ๊ฐ์ ์ ๋์ฝ๋ ์ด์ค์ผ์ดํ๋ก ์ ์ฅ๋ผ์ ์ฝ๊ธฐ ํ๋ค์ด์ ธ.
๐ฅ ๋ฐฉ๋ฒ 2: ํ์ ์๋ ๋ณํ ํฌํจ (์ค๋ฌด ์ถ์ฒ)
<span class="tx-keyword">import</span> csv
<span class="tx-keyword">import</span> json
<span class="tx-keyword">def</span> <span class="tx-func">auto_convert_type</span>(value):
<span class="tx-string">"""๋ฌธ์์ด ๊ฐ์ ์ ์ ํ ํ์
์ผ๋ก ์๋ ๋ณํ"""</span>
<span class="tx-keyword">if</span> value == <span class="tx-string">''</span> <span class="tx-keyword">or</span> value <span class="tx-keyword">is</span> <span class="tx-keyword">None</span>:
<span class="tx-keyword">return</span> <span class="tx-keyword">None</span>
<span class="tx-comment"># ๋ถ๋ฆฌ์ธ ์ฒดํฌ</span>
<span class="tx-keyword">if</span> value.lower() <span class="tx-keyword">in</span> (<span class="tx-string">'true'</span>, <span class="tx-string">'yes'</span>, <span class="tx-string">'1'</span>):
<span class="tx-keyword">return</span> <span class="tx-keyword">True</span>
<span class="tx-keyword">if</span> value.lower() <span class="tx-keyword">in</span> (<span class="tx-string">'false'</span>, <span class="tx-string">'no'</span>, <span class="tx-string">'0'</span>):
<span class="tx-keyword">return</span> <span class="tx-keyword">False</span>
<span class="tx-comment"># ์ ์ ์ฒดํฌ</span>
<span class="tx-keyword">try</span>:
int_val = <span class="tx-func">int</span>(value)
<span class="tx-keyword">return</span> int_val
<span class="tx-keyword">except</span> ValueError:
<span class="tx-keyword">pass</span>
<span class="tx-comment"># ์ค์ ์ฒดํฌ</span>
<span class="tx-keyword">try</span>:
float_val = <span class="tx-func">float</span>(value)
<span class="tx-keyword">return</span> float_val
<span class="tx-keyword">except</span> ValueError:
<span class="tx-keyword">pass</span>
<span class="tx-comment"># ๊ทธ ์ธ๋ ๋ฌธ์์ด ๊ทธ๋๋ก</span>
<span class="tx-keyword">return</span> value
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_typed</span>(csv_path, json_path, encoding=<span class="tx-string">'utf-8'</span>):
<span class="tx-string">"""ํ์
์๋ ๋ณํ์ด ํฌํจ๋ CSV โ JSON ๋ณํ"""</span>
result = []
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_path, <span class="tx-string">'r'</span>, encoding=encoding, newline=<span class="tx-string">''</span>) <span class="tx-keyword">as</span> f:
reader = csv.DictReader(f)
<span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader:
typed_row = {
key: <span class="tx-func">auto_convert_type</span>(value)
<span class="tx-keyword">for</span> key, value <span class="tx-keyword">in</span> row.items()
}
result.append(typed_row)
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(json_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> f:
json.<span class="tx-func">dump</span>(result, f, ensure_ascii=<span class="tx-keyword">False</span>, indent=<span class="tx-num">2</span>)
<span class="tx-keyword">return</span> result
๐ ๋ฐฉ๋ฒ 3: BOM ์ฒ๋ฆฌ + ๋ค์ํ ์ธ์ฝ๋ฉ ์๋ ๊ฐ์ง
<span class="tx-keyword">import</span> csv
<span class="tx-keyword">import</span> json
<span class="tx-keyword">import</span> chardet <span class="tx-comment"># pip install chardet</span>
<span class="tx-keyword">def</span> <span class="tx-func">detect_encoding</span>(file_path):
<span class="tx-string">"""ํ์ผ ์ธ์ฝ๋ฉ ์๋ ๊ฐ์ง"""</span>
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(file_path, <span class="tx-string">'rb'</span>) <span class="tx-keyword">as</span> f:
raw = f.<span class="tx-func">read</span>(<span class="tx-num">10000</span>) <span class="tx-comment"># ์ฒ์ 10KB๋ง ์ฝ์ด์ ๊ฐ์ง</span>
result = chardet.<span class="tx-func">detect</span>(raw)
<span class="tx-keyword">return</span> result[<span class="tx-string">'encoding'</span>]
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_smart</span>(csv_path, json_path=<span class="tx-keyword">None</span>,
delimiter=<span class="tx-string">','</span>, encoding=<span class="tx-keyword">None</span>):
<span class="tx-string">"""
์ค๋งํธ CSV โ JSON ๋ณํ
- ์ธ์ฝ๋ฉ ์๋ ๊ฐ์ง
- BOM ์ฒ๋ฆฌ
- ์ปค์คํ
๊ตฌ๋ถ์ ์ง์
- json_path๊ฐ None์ด๋ฉด ๊ฒฐ๊ณผ๋ง ๋ฐํ
"""</span>
<span class="tx-keyword">if</span> encoding <span class="tx-keyword">is</span> <span class="tx-keyword">None</span>:
encoding = <span class="tx-func">detect_encoding</span>(csv_path)
<span class="tx-func">print</span>(<span class="tx-string">f"๐ ๊ฐ์ง๋ ์ธ์ฝ๋ฉ: {encoding}"</span>)
<span class="tx-comment"># utf-8-sig๋ BOM์ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ค</span>
<span class="tx-keyword">if</span> encoding <span class="tx-keyword">and</span> encoding.lower() == <span class="tx-string">'utf-8'</span>:
encoding = <span class="tx-string">'utf-8-sig'</span>
result = []
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_path, <span class="tx-string">'r'</span>, encoding=encoding, newline=<span class="tx-string">''</span>) <span class="tx-keyword">as</span> f:
reader = csv.DictReader(f, delimiter=delimiter)
<span class="tx-comment"># ํค๋ ๊ณต๋ฐฑ ์ ๊ฑฐ</span>
reader.fieldnames = [
field.<span class="tx-func">strip</span>() <span class="tx-keyword">for</span> field <span class="tx-keyword">in</span> reader.fieldnames
]
<span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader:
cleaned = {
k.<span class="tx-func">strip</span>(): v.<span class="tx-func">strip</span>() <span class="tx-keyword">if</span> v <span class="tx-keyword">else</span> <span class="tx-keyword">None</span>
<span class="tx-keyword">for</span> k, v <span class="tx-keyword">in</span> row.items()
<span class="tx-keyword">if</span> k <span class="tx-keyword">is</span> <span class="tx-keyword">not</span> <span class="tx-keyword">None</span>
}
result.append(cleaned)
<span class="tx-keyword">if</span> json_path:
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(json_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> f:
json.<span class="tx-func">dump</span>(result, f, ensure_ascii=<span class="tx-keyword">False</span>, indent=<span class="tx-num">2</span>)
<span class="tx-keyword">return</span> result
โก ๋ฐฉ๋ฒ 4: pandas ํ์ฉ (๋ฐ์ดํฐ ๋ถ์ ํ๊ฒฝ)
<span class="tx-keyword">import</span> pandas <span class="tx-keyword">as</span> pd
<span class="tx-keyword">import</span> json
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_pandas</span>(csv_path, json_path=<span class="tx-keyword">None</span>, orient=<span class="tx-string">'records'</span>):
<span class="tx-string">"""
pandas๋ฅผ ์ด์ฉํ CSV โ JSON ๋ณํ
orient ์ต์
:
'records' : [{col1:val, col2:val}, ...] โ ๊ฐ์ฅ ์ผ๋ฐ์
'index' : {idx: {col1:val, ...}, ...}
'columns' : {col1: {idx:val, ...}, ...}
'values' : [[val1, val2, ...], ...]
'split' : {columns:[...], index:[...], data:[[...]]}
"""</span>
<span class="tx-comment"># ์ธ์ฝ๋ฉ ์๋ ์ฒ๋ฆฌ (utf-8-sig๋ก BOM ์ฒ๋ฆฌ)</span>
<span class="tx-keyword">try</span>:
df = pd.<span class="tx-func">read_csv</span>(csv_path, encoding=<span class="tx-string">'utf-8-sig'</span>)
<span class="tx-keyword">except</span> UnicodeDecodeError:
df = pd.<span class="tx-func">read_csv</span>(csv_path, encoding=<span class="tx-string">'cp949'</span>)
<span class="tx-comment"># NaN์ None์ผ๋ก ๋ณํ (JSON null๋ก ์ง๋ ฌํ๋จ)</span>
df = df.<span class="tx-func">where</span>(pd.<span class="tx-func">notnull</span>(df), <span class="tx-keyword">None</span>)
<span class="tx-comment"># ์ปฌ๋ผ๋ช
๊ณต๋ฐฑ ์ ๊ฑฐ</span>
df.columns = df.columns.<span class="tx-func">str.strip</span>()
json_str = df.<span class="tx-func">to_json</span>(orient=orient, force_ascii=<span class="tx-keyword">False</span>, indent=<span class="tx-num">2</span>)
<span class="tx-keyword">if</span> json_path:
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(json_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> f:
f.<span class="tx-func">write</span>(json_str)
<span class="tx-keyword">return</span> json.<span class="tx-func">loads</span>(json_str)
<span class="tx-comment"># ์ฌ์ฉ ์์</span>
data = <span class="tx-func">csv_to_json_pandas</span>(<span class="tx-string">'users.csv'</span>, <span class="tx-string">'users.json'</span>)
<span class="tx-func">print</span>(<span class="tx-string">f"์ด {len(data)}๊ฐ ๋ ์ฝ๋ ๋ณํ ์๋ฃ ๐"</span>)
๐ฏ ๋ฐฉ๋ฒ 5: ์ปค๋งจ๋๋ผ์ธ ์๋ผ์ด๋ (๋น ๋ฅธ ๋ณํ)
<span class="tx-comment"># ํฐ๋ฏธ๋์์ ๋ฐ๋ก ์คํ ๊ฐ๋ฅํ ์๋ผ์ด๋</span>
python3 -c <span class="tx-string">"
import csv, json, sys
with open(sys.argv[1], 'r', encoding='utf-8-sig') as f:
print(json.dumps(list(csv.DictReader(f)), ensure_ascii=False, indent=2))
"</span> input.csv > output.json
๐จ 06. JavaScript / Node.js๋ก ๋ณํํ๊ธฐ
ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ผ๋ฉด JavaScript๋ก ์ฒ๋ฆฌํ๊ณ ์ถ์ ๊ฑฐ์ผ.
๋ธ๋ผ์ฐ์ ์์ ์ง์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ๊ณผ Node.js ์๋ฒ์ฌ์ด๋ ๋ฐฉ๋ฒ ๋ ๋ค ์์๋ณด์!
๐ ๋ฐฉ๋ฒ 1: ๋ธ๋ผ์ฐ์ ์์ ์ง์ ์ฒ๋ฆฌ (์์ JS)
<span class="tx-comment">/**
* ๋ธ๋ผ์ฐ์ ์์ CSV ๋ฌธ์์ด์ JSON์ผ๋ก ๋ณํ
* ํ์ผ ์
๋ก๋ ํ FileReader๋ก ์ฝ์ ํ
์คํธ๋ฅผ ๋๊ฒจ์ฃผ๋ฉด ๋จ
*/</span>
<span class="tx-keyword">function</span> <span class="tx-func">csvToJson</span>(csvText, delimiter = <span class="tx-string">','</span>) {
<span class="tx-keyword">const</span> lines = csvText
.<span class="tx-func">trim</span>()
.<span class="tx-func">split</span>(<span class="tx-string">'\n'</span>)
.<span class="tx-func">map</span>(line => line.<span class="tx-func">replace</span>(<span class="tx-string">/\r$/</span>, <span class="tx-string">''</span>)); <span class="tx-comment">// CRLF ์ฒ๋ฆฌ</span>
<span class="tx-keyword">if</span> (lines.length === <span class="tx-num">0</span>) <span class="tx-keyword">return</span> [];
<span class="tx-comment">// ํค๋ ํ์ฑ</span>
<span class="tx-keyword">const</span> headers = <span class="tx-func">parseCSVLine</span>(lines[<span class="tx-num">0</span>], delimiter);
<span class="tx-comment">// ๋ฐ์ดํฐ ํ ํ์ฑ</span>
<span class="tx-keyword">return</span> lines
.<span class="tx-func">slice</span>(<span class="tx-num">1</span>)
.<span class="tx-func">filter</span>(line => line.<span class="tx-func">trim</span>() !== <span class="tx-string">''</span>) <span class="tx-comment">// ๋น ํ ์ ๊ฑฐ</span>
.<span class="tx-func">map</span>(line => {
<span class="tx-keyword">const</span> values = <span class="tx-func">parseCSVLine</span>(line, delimiter);
<span class="tx-keyword">return</span> headers.<span class="tx-func">reduce</span>((obj, header, index) => {
obj[header.<span class="tx-func">trim</span>()] = <span class="tx-func">autoType</span>(values[index] ?? <span class="tx-string">''</span>);
<span class="tx-keyword">return</span> obj;
}, {});
});
}
<span class="tx-comment">/**
* CSV ํ ์ค์ ํ์ฑ (๋ฐ์ดํ ์ฒ๋ฆฌ ํฌํจ)
*/</span>
<span class="tx-keyword">function</span> <span class="tx-func">parseCSVLine</span>(line, delimiter = <span class="tx-string">','</span>) {
<span class="tx-keyword">const</span> result = [];
<span class="tx-keyword">let</span> current = <span class="tx-string">''</span>;
<span class="tx-keyword">let</span> inQuotes = <span class="tx-keyword">false</span>;
<span class="tx-keyword">for</span> (<span class="tx-keyword">let</span> i = <span class="tx-num">0</span>; i < line.length; i++) {
<span class="tx-keyword">const</span> char = line[i];
<span class="tx-keyword">const</span> nextChar = line[i + <span class="tx-num">1</span>];
<span class="tx-keyword">if</span> (char === <span class="tx-string">'"'</span>) {
<span class="tx-keyword">if</span> (inQuotes && nextChar === <span class="tx-string">'"'</span>) {
<span class="tx-comment">// ์ด์ค์ผ์ดํ๋ ๋ฐ์ดํ ("")</span>
current += <span class="tx-string">'"'</span>;
i++;
} <span class="tx-keyword">else</span> {
inQuotes = !inQuotes;
}
} <span class="tx-keyword">else if</span> (char === delimiter && !inQuotes) {
result.<span class="tx-func">push</span>(current);
current = <span class="tx-string">''</span>;
} <span class="tx-keyword">else</span> {
current += char;
}
}
result.<span class="tx-func">push</span>(current);
<span class="tx-keyword">return</span> result;
}
<span class="tx-comment">/**
* ๋ฌธ์์ด ๊ฐ์ ์ ์ ํ ํ์
์ผ๋ก ๋ณํ
*/</span>
<span class="tx-keyword">function</span> <span class="tx-func">autoType</span>(value) {
<span class="tx-keyword">if</span> (value === <span class="tx-string">''</span>) <span class="tx-keyword">return</span> <span class="tx-keyword">null</span>;
<span class="tx-keyword">if</span> (value.toLowerCase() === <span class="tx-string">'true'</span>) <span class="tx-keyword">return</span> <span class="tx-keyword">true</span>;
<span class="tx-keyword">if</span> (value.toLowerCase() === <span class="tx-string">'false'</span>) <span class="tx-keyword">return</span> <span class="tx-keyword">false</span>;
<span class="tx-keyword">if</span> (!<span class="tx-func">isNaN</span>(value) && value !== <span class="tx-string">''</span>) <span class="tx-keyword">return</span> <span class="tx-func">Number</span>(value);
<span class="tx-keyword">return</span> value;
}
๐ ํ์ผ ์ ๋ก๋ ์ฐ๋ ์์
<span class="tx-comment">// HTML: <input type="file" id="csvFile" accept=".csv"></span>
document.<span class="tx-func">getElementById</span>(<span class="tx-string">'csvFile'</span>)
.<span class="tx-func">addEventListener</span>(<span class="tx-string">'change'</span>, <span class="tx-keyword">function</span>(event) {
<span class="tx-keyword">const</span> file = event.target.files[<span class="tx-num">0</span>];
<span class="tx-keyword">if</span> (!file) <span class="tx-keyword">return</span>;
<span class="tx-keyword">const</span> reader = <span class="tx-keyword">new</span> <span class="tx-func">FileReader</span>();
reader.onload = <span class="tx-keyword">function</span>(e) {
<span class="tx-keyword">const</span> csvText = e.target.result;
<span class="tx-keyword">const</span> jsonData = <span class="tx-func">csvToJson</span>(csvText);
console.<span class="tx-func">log</span>(<span class="tx-string">'๋ณํ ๊ฒฐ๊ณผ:'</span>, jsonData);
console.<span class="tx-func">log</span>(<span class="tx-string">'JSON ๋ฌธ์์ด:'</span>, JSON.<span class="tx-func">stringify</span>(jsonData, <span class="tx-keyword">null</span>, <span class="tx-num">2</span>));
<span class="tx-comment">// ๋ค์ด๋ก๋ ๊ธฐ๋ฅ</span>
<span class="tx-keyword">const</span> blob = <span class="tx-keyword">new</span> <span class="tx-func">Blob</span>(
[JSON.<span class="tx-func">stringify</span>(jsonData, <span class="tx-keyword">null</span>, <span class="tx-num">2</span>)],
{ type: <span class="tx-string">'application/json'</span> }
);
<span class="tx-keyword">const</span> url = URL.<span class="tx-func">createObjectURL</span>(blob);
<span class="tx-keyword">const</span> a = document.<span class="tx-func">createElement</span>(<span class="tx-string">'a'</span>);
a.href = url;
a.download = <span class="tx-string">'output.json'</span>;
a.<span class="tx-func">click</span>();
};
reader.<span class="tx-func">readAsText</span>(file, <span class="tx-string">'UTF-8'</span>);
});
๐ข Node.js ์๋ฒ์ฌ์ด๋ ๋ณํ
<span class="tx-comment">// npm install csv-parse โ ๊ฒ์ฆ๋ CSV ํ์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ</span>
<span class="tx-keyword">const</span> { parse } = <span class="tx-func">require</span>(<span class="tx-string">'csv-parse/sync'</span>);
<span class="tx-keyword">const</span> fs = <span class="tx-func">require</span>(<span class="tx-string">'fs'</span>);
<span class="tx-keyword">const</span> path = <span class="tx-func">require</span>(<span class="tx-string">'path'</span>);
<span class="tx-keyword">function</span> <span class="tx-func">csvToJsonFile</span>(inputPath, outputPath) {
<span class="tx-comment">// BOM ์ ๊ฑฐ ํ ์ฝ๊ธฐ</span>
<span class="tx-keyword">let</span> content = fs.<span class="tx-func">readFileSync</span>(inputPath, <span class="tx-string">'utf-8'</span>);
<span class="tx-keyword">if</span> (content.<span class="tx-func">charCodeAt</span>(<span class="tx-num">0</span>) === <span class="tx-num">0xFEFF</span>) {
content = content.<span class="tx-func">slice</span>(<span class="tx-num">1</span>); <span class="tx-comment">// BOM ์ ๊ฑฐ</span>
}
<span class="tx-keyword">const</span> records = <span class="tx-func">parse</span>(content, {
columns: <span class="tx-keyword">true</span>, <span class="tx-comment">// ์ฒซ ํ์ ํค๋๋ก</span>
skip_empty_lines: <span class="tx-keyword">true</span>, <span class="tx-comment">// ๋น ์ค ์คํต</span>
trim: <span class="tx-keyword">true</span>, <span class="tx-comment">// ์๋ค ๊ณต๋ฐฑ ์ ๊ฑฐ</span>
cast: <span class="tx-keyword">true</span>, <span class="tx-comment">// ํ์
์๋ ๋ณํ</span>
cast_date: <span class="tx-keyword">false</span> <span class="tx-comment">// ๋ ์ง ์๋ ๋ณํ์ ๋ (์๋์น ์์ ๋ณํ ๋ฐฉ์ง)</span>
});
<span class="tx-keyword">const</span> jsonStr = JSON.<span class="tx-func">stringify</span>(records, <span class="tx-keyword">null</span>, <span class="tx-num">2</span>);
<span class="tx-keyword">if</span> (outputPath) {
fs.<span class="tx-func">writeFileSync</span>(outputPath, jsonStr, <span class="tx-string">'utf-8'</span>);
console.<span class="tx-func">log</span>(<span class="tx-string">`โ
${records.length}๊ฐ ๋ ์ฝ๋ โ ${outputPath}`</span>);
}
<span class="tx-keyword">return</span> records;
}
<span class="tx-comment">// ์คํ</span>
<span class="tx-keyword">const</span> data = <span class="tx-func">csvToJsonFile</span>(<span class="tx-string">'./data/input.csv'</span>, <span class="tx-string">'./data/output.json'</span>);
csv-parse๊ฐ ๊ฐ์ฅ ๊ฒ์ฆ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. RFC 4180 ์๋ฒฝ ์ค์, ์คํธ๋ฆฌ๋ฐ ์ง์, ํ์
์บ์คํ
๋ฑ ํ์ํ ๊ธฐ๋ฅ์ด ๋ค ์์ด.
โ 07. Java๋ก ๋ณํํ๊ธฐ (Jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
Java ํ๊ฒฝ์์๋ Jackson๊ณผ OpenCSV ์กฐํฉ์ด ๊ฐ์ฅ ๊ฐ๋ ฅํด.
Spring Boot ํ๋ก์ ํธ๋ผ๋ฉด Jackson์ ์ด๋ฏธ ๋ค์ด๊ฐ ์์ ๊ฑฐ์ผ!
๐ฆ ์์กด์ฑ ์ถ๊ฐ (Maven)
<span class="tx-comment"><!-- pom.xml --></span>
<span class="tx-keyword"><dependency></span>
<span class="tx-string"><groupId></span>com.opencsv<span class="tx-string"></groupId></span>
<span class="tx-string"><artifactId></span>opencsv<span class="tx-string"></artifactId></span>
<span class="tx-string"><version></span>5.7.1<span class="tx-string"></version></span>
<span class="tx-keyword"></dependency></span>
<span class="tx-keyword"><dependency></span>
<span class="tx-string"><groupId></span>com.fasterxml.jackson.core<span class="tx-string"></groupId></span>
<span class="tx-string"><artifactId></span>jackson-databind<span class="tx-string"></artifactId></span>
<span class="tx-string"><version></span>2.15.2<span class="tx-string"></version></span>
<span class="tx-keyword"></dependency></span>
โ ๋ณํ ์ฝ๋
<span class="tx-keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;
<span class="tx-keyword">import</span> com.opencsv.CSVReader;
<span class="tx-keyword">import</span> com.opencsv.exceptions.CsvException;
<span class="tx-keyword">import</span> java.io.*;
<span class="tx-keyword">import</span> java.nio.charset.StandardCharsets;
<span class="tx-keyword">import</span> java.util.*;
<span class="tx-keyword">public class</span> <span class="tx-func">CsvToJsonConverter</span> {
<span class="tx-keyword">private final</span> ObjectMapper objectMapper = <span class="tx-keyword">new</span> <span class="tx-func">ObjectMapper</span>();
<span class="tx-comment">/**
* CSV ํ์ผ์ JSON ๋ฌธ์์ด๋ก ๋ณํ
* @param csvFilePath CSV ํ์ผ ๊ฒฝ๋ก
* @return JSON ๋ฌธ์์ด
*/</span>
<span class="tx-keyword">public</span> String <span class="tx-func">convertToJson</span>(String csvFilePath)
<span class="tx-keyword">throws</span> IOException, CsvException {
List<Map<String, String>> result = <span class="tx-keyword">new</span> ArrayList<>();
<span class="tx-keyword">try</span> (
InputStreamReader isr = <span class="tx-keyword">new</span> <span class="tx-func">InputStreamReader</span>(
<span class="tx-keyword">new</span> <span class="tx-func">FileInputStream</span>(csvFilePath),
StandardCharsets.UTF_8
);
CSVReader reader = <span class="tx-keyword">new</span> <span class="tx-func">CSVReader</span>(isr)
) {
<span class="tx-comment">// ํค๋ ์ฝ๊ธฐ</span>
String[] headers = reader.<span class="tx-func">readNext</span>();
<span class="tx-keyword">if</span> (headers == <span class="tx-keyword">null</span>) <span class="tx-keyword">return</span> <span class="tx-string">"[]"</span>;
<span class="tx-comment">// BOM ์ ๊ฑฐ</span>
<span class="tx-keyword">if</span> (headers[<span class="tx-num">0</span>].<span class="tx-func">startsWith</span>(<span class="tx-string">"\uFEFF"</span>)) {
headers[<span class="tx-num">0</span>] = headers[<span class="tx-num">0</span>].<span class="tx-func">substring</span>(<span class="tx-num">1</span>);
}
<span class="tx-comment">// ํค๋ ๊ณต๋ฐฑ ์ ๊ฑฐ</span>
<span class="tx-keyword">for</span> (<span class="tx-keyword">int</span> i = <span class="tx-num">0</span>; i < headers.length; i++) {
headers[i] = headers[i].<span class="tx-func">trim</span>();
}
<span class="tx-comment">// ๋ฐ์ดํฐ ํ ์ฒ๋ฆฌ</span>
String[] row;
<span class="tx-keyword">while</span> ((row = reader.<span class="tx-func">readNext</span>()) != <span class="tx-keyword">null</span>) {
Map<String, String> rowMap = <span class="tx-keyword">new</span> LinkedHashMap<>();
<span class="tx-keyword">for</span> (<span class="tx-keyword">int</span> i = <span class="tx-num">0</span>; i < headers.length; i++) {
String value = (i < row.length) ? row[i].<span class="tx-func">trim</span>() : <span class="tx-string">""</span>;
rowMap.<span class="tx-func">put</span>(headers[i], value.isEmpty() ? <span class="tx-keyword">null</span> : value);
}
result.<span class="tx-func">add</span>(rowMap);
}
}
<span class="tx-keyword">return</span> objectMapper
.<span class="tx-func">writerWithDefaultPrettyPrinter</span>()
.<span class="tx-func">writeValueAsString</span>(result);
}
<span class="tx-comment">// ํ์ผ๋ก ์ ์ฅํ๋ ๋ฒ์ </span>
<span class="tx-keyword">public void</span> <span class="tx-func">convertToJsonFile</span>(String csvPath, String jsonPath)
<span class="tx-keyword">throws</span> IOException, CsvException {
String json = <span class="tx-func">convertToJson</span>(csvPath);
<span class="tx-keyword">try</span> (FileWriter fw = <span class="tx-keyword">new</span> <span class="tx-func">FileWriter</span>(jsonPath, StandardCharsets.UTF_8)) {
fw.<span class="tx-func">write</span>(json);
}
System.out.<span class="tx-func">println</span>(<span class="tx-string">"โ
๋ณํ ์๋ฃ: "</span> + jsonPath);
}
<span class="tx-keyword">public static void</span> <span class="tx-func">main</span>(String[] args) <span class="tx-keyword">throws</span> Exception {
CsvToJsonConverter converter = <span class="tx-keyword">new</span> <span class="tx-func">CsvToJsonConverter</span>();
converter.<span class="tx-func">convertToJsonFile</span>(<span class="tx-string">"input.csv"</span>, <span class="tx-string">"output.json"</span>);
}
}
LinkedHashMap์ ์ฐ๋ฉด CSV ์ปฌ๋ผ ์์๊ฐ JSON์์๋ ์ ์ง๋ผ. ์ผ๋ฐ HashMap์ ์์๊ฐ ๋ณด์ฅ ์ ๋๋๊น ์ฃผ์!
๐น 08. Go ์ธ์ด๋ก ๋ณํํ๊ธฐ
Go๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๋ง ์ ๋์ด ์์ด์ ์ธ๋ถ ํจํค์ง ์์ด๋ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ด.
์ฑ๋ฅ๋ ์ต๊ณ ์์ค์ด๋ผ ๋์ฉ๋ ์ฒ๋ฆฌ์๋ ๊ฐํด! ๐ช
<span class="tx-keyword">package</span> main
<span class="tx-keyword">import</span> (
<span class="tx-string">"encoding/csv"</span>
<span class="tx-string">"encoding/json"</span>
<span class="tx-string">"fmt"</span>
<span class="tx-string">"os"</span>
<span class="tx-string">"strings"</span>
<span class="tx-string">"strconv"</span>
)
<span class="tx-comment">// autoConvert: ๋ฌธ์์ด์ ์ ์ ํ ํ์
์ผ๋ก ๋ณํ</span>
<span class="tx-keyword">func</span> <span class="tx-func">autoConvert</span>(s string) <span class="tx-keyword">interface</span>{} {
s = strings.<span class="tx-func">TrimSpace</span>(s)
<span class="tx-keyword">if</span> s == <span class="tx-string">""</span> {
<span class="tx-keyword">return</span> <span class="tx-keyword">nil</span>
}
<span class="tx-comment">// ๋ถ๋ฆฌ์ธ ์ฒดํฌ</span>
lower := strings.<span class="tx-func">ToLower</span>(s)
<span class="tx-keyword">if</span> lower == <span class="tx-string">"true"</span> || lower == <span class="tx-string">"yes"</span> {
<span class="tx-keyword">return</span> <span class="tx-keyword">true</span>
}
<span class="tx-keyword">if</span> lower == <span class="tx-string">"false"</span> || lower == <span class="tx-string">"no"</span> {
<span class="tx-keyword">return</span> <span class="tx-keyword">false</span>
}
<span class="tx-comment">// ์ ์ ์ฒดํฌ</span>
<span class="tx-keyword">if</span> i, err := strconv.<span class="tx-func">ParseInt</span>(s, <span class="tx-num">10</span>, <span class="tx-num">64</span>); err == <span class="tx-keyword">nil</span> {
<span class="tx-keyword">return</span> i
}
<span class="tx-comment">// ์ค์ ์ฒดํฌ</span>
<span class="tx-keyword">if</span> f, err := strconv.<span class="tx-func">ParseFloat</span>(s, <span class="tx-num">64</span>); err == <span class="tx-keyword">nil</span> {
<span class="tx-keyword">return</span> f
}
<span class="tx-keyword">return</span> s
}
<span class="tx-comment">// CsvToJson: CSV ํ์ผ์ JSON์ผ๋ก ๋ณํ</span>
<span class="tx-keyword">func</span> <span class="tx-func">CsvToJson</span>(csvPath, jsonPath string) error {
<span class="tx-comment">// CSV ํ์ผ ์ด๊ธฐ</span>
csvFile, err := os.<span class="tx-func">Open</span>(csvPath)
<span class="tx-keyword">if</span> err != <span class="tx-keyword">nil</span> {
<span class="tx-keyword">return</span> fmt.<span class="tx-func">Errorf</span>(<span class="tx-string">"CSV ํ์ผ ์ด๊ธฐ ์คํจ: %w"</span>, err)
}
<span class="tx-keyword">defer</span> csvFile.<span class="tx-func">Close</span>()
reader := csv.<span class="tx-func">NewReader</span>(csvFile)
reader.TrimLeadingSpace = <span class="tx-keyword">true</span>
<span class="tx-comment">// ํค๋ ์ฝ๊ธฐ</span>
headers, err := reader.<span class="tx-func">Read</span>()
<span class="tx-keyword">if</span> err != <span class="tx-keyword">nil</span> {
<span class="tx-keyword">return</span> fmt.<span class="tx-func">Errorf</span>(<span class="tx-string">"ํค๋ ์ฝ๊ธฐ ์คํจ: %w"</span>, err)
}
<span class="tx-comment">// BOM ์ ๊ฑฐ</span>
<span class="tx-keyword">if</span> len(headers) > <span class="tx-num">0</span> {
headers[<span class="tx-num">0</span>] = strings.<span class="tx-func">TrimPrefix</span>(headers[<span class="tx-num">0</span>], <span class="tx-string">"\uFEFF"</span>)
}
<span class="tx-keyword">var</span> result []map[string]<span class="tx-keyword">interface</span>{}
<span class="tx-comment">// ๋ฐ์ดํฐ ํ ์ฒ๋ฆฌ</span>
<span class="tx-keyword">for</span> {
row, err := reader.<span class="tx-func">Read</span>()
<span class="tx-keyword">if</span> err != <span class="tx-keyword">nil</span> {
<span class="tx-keyword">break</span> <span class="tx-comment">// EOF ๋๋ ์๋ฌ</span>
}
rowMap := make(map[string]<span class="tx-keyword">interface</span>{})
<span class="tx-keyword">for</span> i, header := <span class="tx-keyword">range</span> headers {
<span class="tx-keyword">if</span> i < len(row) {
rowMap[strings.<span class="tx-func">TrimSpace</span>(header)] = <span class="tx-func">autoConvert</span>(row[i])
} <span class="tx-keyword">else</span> {
rowMap[strings.<span class="tx-func">TrimSpace</span>(header)] = <span class="tx-keyword">nil</span>
}
}
result = <span class="tx-func">append</span>(result, rowMap)
}
<span class="tx-comment">// JSON ํ์ผ ์ ์ฅ</span>
jsonFile, err := os.<span class="tx-func">Create</span>(jsonPath)
<span class="tx-keyword">if</span> err != <span class="tx-keyword">nil</span> {
<span class="tx-keyword">return</span> fmt.<span class="tx-func">Errorf</span>(<span class="tx-string">"JSON ํ์ผ ์์ฑ ์คํจ: %w"</span>, err)
}
<span class="tx-keyword">defer</span> jsonFile.<span class="tx-func">Close</span>()
encoder := json.<span class="tx-func">NewEncoder</span>(jsonFile)
encoder.<span class="tx-func">SetIndent</span>(<span class="tx-string">""</span>, <span class="tx-string">" "</span>)
encoder.<span class="tx-func">SetEscapeHTML</span>(<span class="tx-keyword">false</span>) <span class="tx-comment">// ํ๊ธ ์ด์ค์ผ์ดํ ๋ฐฉ์ง</span>
<span class="tx-keyword">if</span> err := encoder.<span class="tx-func">Encode</span>(result); err != <span class="tx-keyword">nil</span> {
<span class="tx-keyword">return</span> fmt.<span class="tx-func">Errorf</span>(<span class="tx-string">"JSON ์ธ์ฝ๋ฉ ์คํจ: %w"</span>, err)
}
fmt.<span class="tx-func">Printf</span>(<span class="tx-string">"โ
๋ณํ ์๋ฃ: %d๊ฐ ๋ ์ฝ๋\n"</span>, len(result))
<span class="tx-keyword">return</span> <span class="tx-keyword">nil</span>
}
<span class="tx-keyword">func</span> <span class="tx-func">main</span>() {
<span class="tx-keyword">if</span> err := <span class="tx-func">CsvToJson</span>(<span class="tx-string">"input.csv"</span>, <span class="tx-string">"output.json"</span>); err != <span class="tx-keyword">nil</span> {
fmt.<span class="tx-func">Fprintf</span>(os.Stderr, <span class="tx-string">"์๋ฌ: %v\n"</span>, err)
os.<span class="tx-func">Exit</span>(<span class="tx-num">1</span>)
}
}
encoder.SetEscapeHTML(false)๋ฅผ ๊ผญ ๋ฃ์ด์ค! ์ด๊ฒ ์์ผ๋ฉด <, >, & ๊ฐ์ ๋ฌธ์๊ฐ ์ ๋์ฝ๋ ์ด์ค์ผ์ดํ๋ก ๋ณํ๋ผ. ํ๊ธ๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด์ค์ผ์ดํ๋ ์ ์์ด.
๐ 09. PHP๋ก ๋ณํํ๊ธฐ
PHP๋ ์น ์๋ฒ ์ฌ์ด๋์์ CSV ์
๋ก๋ ์ฒ๋ฆฌํ ๋ ๋ง์ด ์ฐ์ฌ.
๋ด์ฅ ํจ์๋ง์ผ๋ก๋ ์ถฉ๋ถํ ์ฒ๋ฆฌํ ์ ์์ด!
<span class="tx-keyword"><?php</span>
<span class="tx-comment">/**
* CSV ํ์ผ์ JSON์ผ๋ก ๋ณํํ๋ ํจ์
*
* @param string $csvPath CSV ํ์ผ ๊ฒฝ๋ก
* @param string|null $jsonPath ์ ์ฅํ JSON ํ์ผ ๊ฒฝ๋ก (null์ด๋ฉด ๋ฐํ๋ง)
* @param string $encoding ํ์ผ ์ธ์ฝ๋ฉ (๊ธฐ๋ณธ: UTF-8)
* @param string $delimiter ๊ตฌ๋ถ์ (๊ธฐ๋ณธ: ์ผํ)
* @return array ๋ณํ๋ ๋ฐ์ดํฐ ๋ฐฐ์ด
*/</span>
<span class="tx-keyword">function</span> <span class="tx-func">csvToJson</span>(
string $csvPath,
?string $jsonPath = <span class="tx-keyword">null</span>,
string $encoding = <span class="tx-string">'UTF-8'</span>,
string $delimiter = <span class="tx-string">','</span>
): array {
<span class="tx-keyword">if</span> (!<span class="tx-func">file_exists</span>($csvPath)) {
<span class="tx-keyword">throw new</span> <span class="tx-func">RuntimeException</span>(<span class="tx-string">"ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค: $csvPath"</span>);
}
<span class="tx-comment">// ํ์ผ ๋ด์ฉ ์ฝ๊ธฐ</span>
$content = <span class="tx-func">file_get_contents</span>($csvPath);
<span class="tx-comment">// BOM ์ ๊ฑฐ</span>
$content = <span class="tx-func">ltrim</span>($content, <span class="tx-string">"\xEF\xBB\xBF"</span>);
<span class="tx-comment">// ์ธ์ฝ๋ฉ ๋ณํ (EUC-KR โ UTF-8)</span>
<span class="tx-keyword">if</span> (<span class="tx-func">strtoupper</span>($encoding) !== <span class="tx-string">'UTF-8'</span>) {
$content = <span class="tx-func">mb_convert_encoding</span>($content, <span class="tx-string">'UTF-8'</span>, $encoding);
}
<span class="tx-comment">// ์์ ํ์ผ๋ก ์ฒ๋ฆฌ (๋ฉ๋ชจ๋ฆฌ ํจ์จ)</span>
$tempFile = <span class="tx-func">tmpfile</span>();
<span class="tx-func">fwrite</span>($tempFile, $content);
<span class="tx-func">rewind</span>($tempFile);
$result = [];
$headers = <span class="tx-keyword">null</span>;
<span class="tx-keyword">while</span> (($row = <span class="tx-func">fgetcsv</span>($tempFile, <span class="tx-num">0</span>, $delimiter)) !== <span class="tx-keyword">false</span>) {
<span class="tx-comment">// ๋น ํ ์คํต</span>
<span class="tx-keyword">if</span> (<span class="tx-func">count</span>($row) === <span class="tx-num">1</span> && $row[<span class="tx-num">0</span>] === <span class="tx-keyword">null</span>) <span class="tx-keyword">continue</span>;
<span class="tx-keyword">if</span> ($headers === <span class="tx-keyword">null</span>) {
<span class="tx-comment">// ํค๋ ํ ์ฒ๋ฆฌ</span>
$headers = <span class="tx-func">array_map</span>(<span class="tx-string">'trim'</span>, $row);
} <span class="tx-keyword">else</span> {
<span class="tx-comment">// ๋ฐ์ดํฐ ํ ์ฒ๋ฆฌ</span>
$rowData = [];
<span class="tx-keyword">foreach</span> ($headers <span class="tx-keyword">as</span> $index => $header) {
$value = isset($row[$index]) ? <span class="tx-func">trim</span>($row[$index]) : <span class="tx-keyword">null</span>;
$rowData[$header] = <span class="tx-func">autoConvertType</span>($value);
}
$result[] = $rowData;
}
}
<span class="tx-func">fclose</span>($tempFile);
<span class="tx-comment">// JSON ํ์ผ ์ ์ฅ</span>
<span class="tx-keyword">if</span> ($jsonPath !== <span class="tx-keyword">null</span>) {
$jsonStr = <span class="tx-func">json_encode</span>(
$result,
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);
<span class="tx-func">file_put_contents</span>($jsonPath, $jsonStr);
<span class="tx-func">echo</span> <span class="tx-string">"โ
๋ณํ ์๋ฃ: "</span> . <span class="tx-func">count</span>($result) . <span class="tx-string">"๊ฐ ๋ ์ฝ๋\n"</span>;
}
<span class="tx-keyword">return</span> $result;
}
<span class="tx-comment">/**
* ๋ฌธ์์ด์ ์ ์ ํ ํ์
์ผ๋ก ๋ณํ
*/</span>
<span class="tx-keyword">function</span> <span class="tx-func">autoConvertType</span>(?string $value): mixed {
<span class="tx-keyword">if</span> ($value === <span class="tx-keyword">null</span> || $value === <span class="tx-string">''</span>) <span class="tx-keyword">return</span> <span class="tx-keyword">null</span>;
$lower = <span class="tx-func">strtolower</span>($value);
<span class="tx-keyword">if</span> ($lower === <span class="tx-string">'true'</span>) <span class="tx-keyword">return</span> <span class="tx-keyword">true</span>;
<span class="tx-keyword">if</span> ($lower === <span class="tx-string">'false'</span>) <span class="tx-keyword">return</span> <span class="tx-keyword">false</span>;
<span class="tx-keyword">if</span> (<span class="tx-func">is_numeric</span>($value)) {
<span class="tx-keyword">return</span> <span class="tx-func">strpos</span>($value, <span class="tx-string">'.'</span>) !== <span class="tx-keyword">false</span>
? (<span class="tx-keyword">float</span>) $value
: (<span class="tx-keyword">int</span>) $value;
}
<span class="tx-keyword">return</span> $value;
}
<span class="tx-comment">// ์ฌ์ฉ ์์</span>
$data = <span class="tx-func">csvToJson</span>(<span class="tx-string">'input.csv'</span>, <span class="tx-string">'output.json'</span>);
<span class="tx-comment">// EUC-KR ํ์ผ ์ฒ๋ฆฌ</span>
$data = <span class="tx-func">csvToJson</span>(<span class="tx-string">'korean.csv'</span>, <span class="tx-string">'korean.json'</span>, <span class="tx-string">'EUC-KR'</span>);
<span class="tx-comment">// TSV(ํญ ๊ตฌ๋ถ) ํ์ผ ์ฒ๋ฆฌ</span>
$data = <span class="tx-func">csvToJson</span>(<span class="tx-string">'data.tsv'</span>, <span class="tx-string">'data.json'</span>, <span class="tx-string">'UTF-8'</span>, <span class="tx-string">"\t"</span>);
JSON_UNESCAPED_UNICODE ํ๋๊ทธ๋ฅผ ๊ผญ ๋ฃ์ด์ค! ์ด๊ฒ ์์ผ๋ฉด ํ๊ธ์ด \uD55C\uAE00๋ก ์ ์ฅ๋ผ. JSON_PRETTY_PRINT๋ ๊ฐ๋ฐ ์ค์๋ง ์ฐ๊ณ ํ๋ก๋์
์์ ๋นผ๋ฉด ํ์ผ ํฌ๊ธฐ๊ฐ ์ค์ด๋ค์ด.
๐ก๏ธ 10. ์ฃ์ง์ผ์ด์ค & ํธ๋ฌ๋ธ์ํ ์๋ฒฝ ๊ฐ์ด๋
์ด ์น์
์ด ์ง์ง ํต์ฌ์ด์ผ. ๊ธฐ๋ณธ ๋ณํ์ ๋๊ตฌ๋ ํ๋๋ฐ,
์ค๋ฌด์์ ํฐ์ง๋ ๊ฑด ํญ์ ์ฃ์ง์ผ์ด์ค๊ฑฐ๋ . ๋ฏธ๋ฆฌ ๋๋นํ์! ๐ง
๐ค ์ฃ์ง์ผ์ด์ค 1: ์ธ์ฝ๋ฉ ์๋ฒฝ ์ฒ๋ฆฌ (Python)
<span class="tx-keyword">import</span> chardet
<span class="tx-keyword">def</span> <span class="tx-func">safe_read_csv</span>(file_path):
<span class="tx-string">"""์ธ์ฝ๋ฉ ์๋ ๊ฐ์ง + ์์ ํ CSV ์ฝ๊ธฐ"""</span>
<span class="tx-comment"># 1๋จ๊ณ: ๋ฐ์ด๋๋ฆฌ๋ก ์ฝ์ด์ ์ธ์ฝ๋ฉ ๊ฐ์ง</span>
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(file_path, <span class="tx-string">'rb'</span>) <span class="tx-keyword">as</span> f:
raw_data = f.<span class="tx-func">read</span>()
detected = chardet.<span class="tx-func">detect</span>(raw_data)
encoding = detected[<span class="tx-string">'encoding'</span>]
confidence = detected[<span class="tx-string">'confidence'</span>]
<span class="tx-func">print</span>(<span class="tx-string">f"๊ฐ์ง๋ ์ธ์ฝ๋ฉ: {encoding} (์ ๋ขฐ๋: {confidence:.1%})"</span>)
<span class="tx-comment"># 2๋จ๊ณ: ๊ฐ์ง๋ ์ธ์ฝ๋ฉ์ผ๋ก ์๋, ์คํจ์ ๋์ ์๋</span>
encodings_to_try = [encoding, <span class="tx-string">'utf-8-sig'</span>, <span class="tx-string">'cp949'</span>, <span class="tx-string">'euc-kr'</span>, <span class="tx-string">'latin-1'</span>]
<span class="tx-keyword">for</span> enc <span class="tx-keyword">in</span> encodings_to_try:
<span class="tx-keyword">if</span> enc <span class="tx-keyword">is</span> <span class="tx-keyword">None</span>:
<span class="tx-keyword">continue</span>
<span class="tx-keyword">try</span>:
text = raw_data.<span class="tx-func">decode</span>(enc)
<span class="tx-func">print</span>(<span class="tx-string">f"โ
{enc}์ผ๋ก ์ฑ๊ณต์ ์ผ๋ก ๋์ฝ๋ฉ"</span>)
<span class="tx-keyword">return</span> text
<span class="tx-keyword">except</span> (UnicodeDecodeError, LookupError):
<span class="tx-keyword">continue</span>
<span class="tx-comment"># ์ตํ์ ์๋จ: errors='replace'๋ก ๊ฐ์ ๋์ฝ๋ฉ</span>
<span class="tx-func">print</span>(<span class="tx-string">"โ ๏ธ ์ธ์ฝ๋ฉ ๊ฐ์ง ์คํจ, ๋์ฒด ๋ฌธ์๋ก ์ฒ๋ฆฌ"</span>)
<span class="tx-keyword">return</span> raw_data.<span class="tx-func">decode</span>(<span class="tx-string">'utf-8'</span>, errors=<span class="tx-string">'replace'</span>)
๐ ์ฃ์ง์ผ์ด์ค 2: ๋ ์ง ํ์ ์ฒ๋ฆฌ
<span class="tx-keyword">from</span> datetime <span class="tx-keyword">import</span> datetime
<span class="tx-keyword">import</span> re
<span class="tx-keyword">def</span> <span class="tx-func">parse_date</span>(value):
<span class="tx-string">"""๋ค์ํ ๋ ์ง ํ์์ ISO 8601๋ก ํต์ผ"""</span>
date_formats = [
<span class="tx-string">'%Y-%m-%d'</span>, <span class="tx-comment"># 2024-01-15</span>
<span class="tx-string">'%Y/%m/%d'</span>, <span class="tx-comment"># 2024/01/15</span>
<span class="tx-string">'%d/%m/%Y'</span>, <span class="tx-comment"># 15/01/2024</span>
<span class="tx-string">'%m/%d/%Y'</span>, <span class="tx-comment"># 01/15/2024</span>
<span class="tx-string">'%Y.%m.%d'</span>, <span class="tx-comment"># 2024.01.15</span>
<span class="tx-string">'%Y-%m-%dT%H:%M:%S'</span>, <span class="tx-comment"># ISO 8601</span>
<span class="tx-string">'%Y๋
%m์ %d์ผ'</span>, <span class="tx-comment"># ํ๊ตญ์</span>
]
<span class="tx-keyword">for</span> fmt <span class="tx-keyword">in</span> date_formats:
<span class="tx-keyword">try</span>:
dt = datetime.<span class="tx-func">strptime</span>(value.<span class="tx-func">strip</span>(), fmt)
<span class="tx-keyword">return</span> dt.<span class="tx-func">isoformat</span>() <span class="tx-comment"># ISO 8601๋ก ํต์ผ</span>
<span class="tx-keyword">except</span> ValueError:
<span class="tx-keyword">continue</span>
<span class="tx-keyword">return</span> value <span class="tx-comment"># ํ์ฑ ์คํจ์ ์๋ณธ ๋ฐํ</span>
<span class="tx-comment"># ๋ ์ง ์ปฌ๋ผ์ ์ง์ ํด์ ๋ณํํ๋ ์์</span>
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_with_dates</span>(csv_path, date_columns=None):
<span class="tx-keyword">import</span> csv, json
date_columns = date_columns <span class="tx-keyword">or</span> []
result = []
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_path, <span class="tx-string">'r'</span>, encoding=<span class="tx-string">'utf-8-sig'</span>) <span class="tx-keyword">as</span> f:
reader = csv.DictReader(f)
<span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader:
processed = {}
<span class="tx-keyword">for</span> key, value <span class="tx-keyword">in</span> row.items():
<span class="tx-keyword">if</span> key <span class="tx-keyword">in</span> date_columns:
processed[key] = <span class="tx-func">parse_date</span>(value)
<span class="tx-keyword">else</span>:
processed[key] = value
result.append(processed)
<span class="tx-keyword">return</span> result
<span class="tx-comment"># ์ฌ์ฉ: 'birth_date', 'created_at' ์ปฌ๋ผ์ ๋ ์ง๋ก ์ฒ๋ฆฌ</span>
data = <span class="tx-func">csv_to_json_with_dates</span>(<span class="tx-string">'users.csv'</span>, [<span class="tx-string">'birth_date'</span>, <span class="tx-string">'created_at'</span>])
๐ ์ฃ์ง์ผ์ด์ค 3: ์ค๋ณต ํค๋ ์ฒ๋ฆฌ
<span class="tx-keyword">def</span> <span class="tx-func">deduplicate_headers</span>(headers):
<span class="tx-string">"""์ค๋ณต ํค๋๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌ (name โ name_1, name_2 ...)</span>
<span class="tx-string"> """</span>
seen = {}
result = []
<span class="tx-keyword">for</span> header <span class="tx-keyword">in</span> headers:
header = header.<span class="tx-func">strip</span>()
<span class="tx-keyword">if</span> header <span class="tx-keyword">in</span> seen:
seen[header] += <span class="tx-num">1</span>
result.append(<span class="tx-string">f"{header}_{seen[header]}"</span>)
<span class="tx-keyword">else</span>:
seen[header] = <span class="tx-num">0</span>
result.append(header)
<span class="tx-keyword">return</span> result
<span class="tx-comment"># ์์: ['name', 'age', 'name', 'name']</span>
<span class="tx-comment"># ๊ฒฐ๊ณผ: ['name', 'age', 'name_1', 'name_2']</span>
๐๏ธ 11. ๋์ฉ๋ CSV ์ฒ๋ฆฌ ์ ๋ต โ ๋ฉ๋ชจ๋ฆฌ ๊ฑฑ์ ๋
100๋ง ํ์ง๋ฆฌ CSV๋ฅผ ํ ๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ฆฌ๋ฉด? ๐ ์๋ฒ๊ฐ ์ฃฝ์ด.
๋์ฉ๋ ํ์ผ์ ์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํด์ผ ํด!
๐ Python ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ (๋์ฉ๋)
<span class="tx-keyword">import</span> csv
<span class="tx-keyword">import</span> json
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_streaming</span>(csv_path, json_path, chunk_size=<span class="tx-num">1000</span>):
<span class="tx-string">"""
์คํธ๋ฆฌ๋ฐ ๋ฐฉ์์ผ๋ก ๋์ฉ๋ CSV๋ฅผ JSON์ผ๋ก ๋ณํ
๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ต์ํํ๋ฉด์ ์ฒ๋ฆฌ
"""</span>
total_rows = <span class="tx-num">0</span>
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_path, <span class="tx-string">'r'</span>, encoding=<span class="tx-string">'utf-8-sig'</span>, newline=<span class="tx-string">''</span>) <span class="tx-keyword">as</span> csv_file, \
<span class="tx-func">open</span>(json_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> json_file:
reader = csv.DictReader(csv_file)
<span class="tx-comment"># JSON ๋ฐฐ์ด ์์</span>
json_file.<span class="tx-func">write</span>(<span class="tx-string">'[\n'</span>)
first = <span class="tx-keyword">True</span>
<span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader:
<span class="tx-keyword">if</span> <span class="tx-keyword">not</span> first:
json_file.<span class="tx-func">write</span>(<span class="tx-string">',\n'</span>)
<span class="tx-comment"># ๊ฐ ํ์ ์ฆ์ ์ง๋ ฌํํ์ฌ ํ์ผ์ ์</span>
json_str = json.<span class="tx-func">dumps</span>(
<span class="tx-func">dict</span>(row),
ensure_ascii=<span class="tx-keyword">False</span>
)
json_file.<span class="tx-func">write</span>(<span class="tx-string">f' {json_str}'</span>)
first = <span class="tx-keyword">False</span>
total_rows += <span class="tx-num">1</span>
<span class="tx-comment"># ์งํ ์ํฉ ์ถ๋ ฅ (chunk_size๋ง๋ค)</span>
<span class="tx-keyword">if</span> total_rows % chunk_size == <span class="tx-num">0</span>:
<span class="tx-func">print</span>(<span class="tx-string">f"โณ {total_rows:,}ํ ์ฒ๋ฆฌ ์ค..."</span>, end=<span class="tx-string">'\r'</span>)
<span class="tx-comment"># JSON ๋ฐฐ์ด ์ข
๋ฃ</span>
json_file.<span class="tx-func">write</span>(<span class="tx-string">'\n]'</span>)
<span class="tx-func">print</span>(<span class="tx-string">f"\nโ
์๋ฃ! ์ด {total_rows:,}ํ ์ฒ๋ฆฌ๋จ"</span>)
<span class="tx-keyword">return</span> total_rows
<span class="tx-comment"># pandas ์ฒญํฌ ์ฒ๋ฆฌ ๋ฐฉ์</span>
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_json_pandas_chunks</span>(csv_path, json_path, chunksize=<span class="tx-num">10000</span>):
<span class="tx-string">"""pandas chunksize๋ฅผ ์ด์ฉํ ๋์ฉ๋ ์ฒ๋ฆฌ"""</span>
<span class="tx-keyword">import</span> pandas <span class="tx-keyword">as</span> pd
all_data = []
<span class="tx-keyword">for</span> i, chunk <span class="tx-keyword">in</span> <span class="tx-func">enumerate</span>(
pd.<span class="tx-func">read_csv</span>(csv_path, encoding=<span class="tx-string">'utf-8-sig'</span>, chunksize=chunksize)
):
<span class="tx-comment"># NaN โ None ๋ณํ</span>
chunk = chunk.<span class="tx-func">where</span>(pd.<span class="tx-func">notnull</span>(chunk), <span class="tx-keyword">None</span>)
all_data.extend(chunk.<span class="tx-func">to_dict</span>(orient=<span class="tx-string">'records'</span>))
<span class="tx-func">print</span>(<span class="tx-string">f"โณ ์ฒญํฌ {i+1} ์ฒ๋ฆฌ ์๋ฃ ({len(all_data):,}ํ)"</span>, end=<span class="tx-string">'\r'</span>)
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(json_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> f:
json.<span class="tx-func">dump</span>(all_data, f, ensure_ascii=<span class="tx-keyword">False</span>)
<span class="tx-func">print</span>(<span class="tx-string">f"\nโ
์๋ฃ! ์ด {len(all_data):,}ํ"</span>)
<span class="tx-keyword">return</span> all_data
๐ข Node.js ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ
<span class="tx-keyword">const</span> fs = <span class="tx-func">require</span>(<span class="tx-string">'fs'</span>);
<span class="tx-keyword">const</span> { parse } = <span class="tx-func">require</span>(<span class="tx-string">'csv-parse'</span>);
<span class="tx-keyword">const</span> { stringify } = <span class="tx-func">require</span>(<span class="tx-string">'JSONStream'</span>); <span class="tx-comment">// npm install JSONStream</span>
<span class="tx-keyword">function</span> <span class="tx-func">csvToJsonStream</span>(inputPath, outputPath) {
<span class="tx-keyword">return new</span> <span class="tx-func">Promise</span>((resolve, reject) => {
<span class="tx-keyword">let</span> count = <span class="tx-num">0</span>;
<span class="tx-keyword">const</span> readStream = fs.<span class="tx-func">createReadStream</span>(inputPath, { encoding: <span class="tx-string">'utf8'</span> });
<span class="tx-keyword">const</span> writeStream = fs.<span class="tx-func">createWriteStream</span>(outputPath, { encoding: <span class="tx-string">'utf8'</span> });
<span class="tx-keyword">const</span> csvParser = <span class="tx-func">parse</span>({
columns: <span class="tx-keyword">true</span>,
skip_empty_lines: <span class="tx-keyword">true</span>,
trim: <span class="tx-keyword">true</span>,
cast: <span class="tx-keyword">true</span>
});
<span class="tx-keyword">const</span> jsonStringifier = stringify.<span class="tx-func">stringify</span>(<span class="tx-string">'*'</span>);
csvParser.<span class="tx-func">on</span>(<span class="tx-string">'data'</span>, () => {
count++;
<span class="tx-keyword">if</span> (count % <span class="tx-num">10000</span> === <span class="tx-num">0</span>) {
process.stdout.<span class="tx-func">write</span>(<span class="tx-string">`\rโณ ${count.toLocaleString()}ํ ์ฒ๋ฆฌ ์ค...`</span>);
}
});
writeStream.<span class="tx-func">on</span>(<span class="tx-string">'finish'</span>, () => {
console.<span class="tx-func">log</span>(<span class="tx-string">`\nโ
์๋ฃ! ์ด ${count.toLocaleString()}ํ`</span>);
<span class="tx-func">resolve</span>(count);
});
readStream
.<span class="tx-func">pipe</span>(csvParser)
.<span class="tx-func">pipe</span>(jsonStringifier)
.<span class="tx-func">pipe</span>(writeStream);
readStream.<span class="tx-func">on</span>(<span class="tx-string">'error'</span>, reject);
csvParser.<span class="tx-func">on</span>(<span class="tx-string">'error'</span>, reject);
});
}
<span class="tx-comment">// ์คํ</span>
<span class="tx-func">csvToJsonStream</span>(<span class="tx-string">'./big_data.csv'</span>, <span class="tx-string">'./big_data.json'</span>)
.<span class="tx-func">then</span>(count => console.<span class="tx-func">log</span>(<span class="tx-string">`์ฒ๋ฆฌ ์๋ฃ: ${count}ํ`</span>))
.<span class="tx-func">catch</span>(console.error);
๐ JSON Lines (JSONL) ํ์ โ ๋์ฉ๋์ ์ง์ง ํด๋ต
<span class="tx-comment"># JSONL: ๊ฐ ํ์ด ๋
๋ฆฝ์ ์ธ JSON ๊ฐ์ฒด (์ค๋ฐ๊ฟ์ผ๋ก ๊ตฌ๋ถ)</span>
<span class="tx-comment"># {"name":"Alice","age":30,"city":"Seoul"}</span>
<span class="tx-comment"># {"name":"Bob","age":25,"city":"Busan"}</span>
<span class="tx-comment"># {"name":"Carol","age":28,"city":"Incheon"}</span>
<span class="tx-keyword">def</span> <span class="tx-func">csv_to_jsonl</span>(csv_path, jsonl_path):
<span class="tx-string">"""CSV๋ฅผ JSONL(JSON Lines) ํ์์ผ๋ก ๋ณํ โ ๋์ฉ๋ ์ต์ """</span>
<span class="tx-keyword">import</span> csv, json
count = <span class="tx-num">0</span>
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_path, <span class="tx-string">'r'</span>, encoding=<span class="tx-string">'utf-8-sig'</span>) <span class="tx-keyword">as</span> csv_f, \
<span class="tx-func">open</span>(jsonl_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> jsonl_f:
reader = csv.DictReader(csv_f)
<span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader:
<span class="tx-comment"># ๊ฐ ํ์ ํ ์ค์ JSON์ผ๋ก ์ฆ์ ๊ธฐ๋ก</span>
jsonl_f.<span class="tx-func">write</span>(
json.<span class="tx-func">dumps</span>(<span class="tx-func">dict</span>(row), ensure_ascii=<span class="tx-keyword">False</span>) + <span class="tx-string">'\n'</span>
)
count += <span class="tx-num">1</span>
<span class="tx-func">print</span>(<span class="tx-string">f"โ
JSONL ๋ณํ ์๋ฃ: {count:,}ํ"</span>)
<span class="tx-keyword">return</span> count
๐ฏ 12. ์ค์ ํ์ฉ ํจํด & ๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง ๋ฐฐ์ด ๋ด์ฉ์ ์ค์ ํ๋ก์ ํธ์์ ์ด๋ป๊ฒ ํ์ฉํ๋์ง ์ ๋ฆฌํด๋ณด์.
๊ทธ๋ฆฌ๊ณ ์ด ๋ชจ๋ ๊ฑธ ํ๋๋ก ๋ฌถ์ ์์ฑํ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ ๋ง๋ค์ด๋ณผ๊ฒ! ๐
๐๏ธ ์์ฑํ Python ์ ํธ๋ฆฌํฐ ํด๋์ค
<span class="tx-keyword">import</span> csv
<span class="tx-keyword">import</span> json
<span class="tx-keyword">import</span> os
<span class="tx-keyword">from</span> typing <span class="tx-keyword">import</span> Optional, List, Dict, Any, Callable
<span class="tx-keyword">from</span> datetime <span class="tx-keyword">import</span> datetime
<span class="tx-keyword">class</span> <span class="tx-func">CsvToJsonConverter</span>:
<span class="tx-string">"""
ํ๋ก๋์
๋ ๋ CSV โ JSON ๋ณํ๊ธฐ
Features:
- ์ธ์ฝ๋ฉ ์๋ ๊ฐ์ง (chardet)
- BOM ์๋ ์ฒ๋ฆฌ
- ํ์
์๋ ๋ณํ
- ์ปค์คํ
๋ณํ ํจ์ ์ง์
- ์คํธ๋ฆฌ๋ฐ ๋ชจ๋ (๋์ฉ๋)
- ์งํ ์ํฉ ์ฝ๋ฐฑ
- ์๋ฌ ํธ๋ค๋ง
"""</span>
<span class="tx-keyword">def</span> <span class="tx-func">__init__</span>(
self,
delimiter: str = <span class="tx-string">','</span>,
encoding: Optional[str] = <span class="tx-keyword">None</span>,
auto_type: bool = <span class="tx-keyword">True</span>,
skip_empty_rows: bool = <span class="tx-keyword">True</span>,
strip_whitespace: bool = <span class="tx-keyword">True</span>
):
self.delimiter = delimiter
self.encoding = encoding
self.auto_type = auto_type
self.skip_empty_rows = skip_empty_rows
self.strip_whitespace = strip_whitespace
self._custom_converters: Dict[str, Callable] = {}
<span class="tx-keyword">def</span> <span class="tx-func">add_converter</span>(self, column: str, func: Callable):
<span class="tx-string">"""ํน์ ์ปฌ๋ผ์ ์ปค์คํ
๋ณํ ํจ์ ๋ฑ๋ก"""</span>
self._custom_converters[column] = func
<span class="tx-keyword">return</span> self <span class="tx-comment"># ๋ฉ์๋ ์ฒด์ด๋ ์ง์</span>
<span class="tx-keyword">def</span> <span class="tx-func">_detect_encoding</span>(self, file_path: str) -> str:
<span class="tx-keyword">try</span>:
<span class="tx-keyword">import</span> chardet
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(file_path, <span class="tx-string">'rb'</span>) <span class="tx-keyword">as</span> f:
raw = f.<span class="tx-func">read</span>(<span class="tx-num">50000</span>)
result = chardet.<span class="tx-func">detect</span>(raw)
enc = result.get(<span class="tx-string">'encoding'</span>, <span class="tx-string">'utf-8'</span>)
<span class="tx-keyword">return</span> <span class="tx-string">'utf-8-sig'</span> <span class="tx-keyword">if</span> enc <span class="tx-keyword">and</span> <span class="tx-string">'utf'</span> <span class="tx-keyword">in</span> enc.lower() <span class="tx-keyword">else</span> enc
<span class="tx-keyword">except</span> ImportError:
<span class="tx-keyword">return</span> <span class="tx-string">'utf-8-sig'</span>
<span class="tx-keyword">def</span> <span class="tx-func">_convert_value</span>(self, key: str, value: str) -> Any:
<span class="tx-comment"># ์ปค์คํ
๋ณํ๊ธฐ ์ฐ์ ์ ์ฉ</span>
<span class="tx-keyword">if</span> key <span class="tx-keyword">in</span> self._custom_converters:
<span class="tx-keyword">return</span> self._custom_converters[key](value)
<span class="tx-keyword">if</span> self.strip_whitespace <span class="tx-keyword">and</span> value:
value = value.<span class="tx-func">strip</span>()
<span class="tx-keyword">if</span> value == <span class="tx-string">''</span>:
<span class="tx-keyword">return</span> <span class="tx-keyword">None</span>
<span class="tx-keyword">if</span> <span class="tx-keyword">not</span> self.auto_type:
<span class="tx-keyword">return</span> value
lower = value.lower()
<span class="tx-keyword">if</span> lower <span class="tx-keyword">in</span> (<span class="tx-string">'true'</span>, <span class="tx-string">'yes'</span>): <span class="tx-keyword">return</span> <span class="tx-keyword">True</span>
<span class="tx-keyword">if</span> lower <span class="tx-keyword">in</span> (<span class="tx-string">'false'</span>, <span class="tx-string">'no'</span>): <span class="tx-keyword">return</span> <span class="tx-keyword">False</span>
<span class="tx-keyword">try</span>: <span class="tx-keyword">return</span> <span class="tx-func">int</span>(value)
<span class="tx-keyword">except</span> ValueError: <span class="tx-keyword">pass</span>
<span class="tx-keyword">try</span>: <span class="tx-keyword">return</span> <span class="tx-func">float</span>(value)
<span class="tx-keyword">except</span> ValueError: <span class="tx-keyword">pass</span>
<span class="tx-keyword">return</span> value
<span class="tx-keyword">def</span> <span class="tx-func">convert</span>(
self,
csv_path: str,
json_path: Optional[str] = <span class="tx-keyword">None</span>,
indent: int = <span class="tx-num">2</span>,
progress_callback: Optional[Callable] = <span class="tx-keyword">None</span>
) -> List[Dict]:
<span class="tx-string">"""๋ฉ์ธ ๋ณํ ๋ฉ์๋"""</span>
<span class="tx-keyword">if</span> <span class="tx-keyword">not</span> os.path.<span class="tx-func">exists</span>(csv_path):
<span class="tx-keyword">raise</span> <span class="tx-func">FileNotFoundError</span>(<span class="tx-string">f"ํ์ผ ์์: {csv_path}"</span>)
encoding = self.encoding <span class="tx-keyword">or</span> self.<span class="tx-func">_detect_encoding</span>(csv_path)
result = []
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(csv_path, <span class="tx-string">'r'</span>, encoding=encoding, newline=<span class="tx-string">''</span>) <span class="tx-keyword">as</span> f:
reader = csv.DictReader(f, delimiter=self.delimiter)
<span class="tx-keyword">if</span> reader.fieldnames:
reader.fieldnames = [
h.<span class="tx-func">strip</span>() <span class="tx-keyword">for</span> h <span class="tx-keyword">in</span> reader.fieldnames
]
<span class="tx-keyword">for</span> i, row <span class="tx-keyword">in</span> <span class="tx-func">enumerate</span>(reader):
<span class="tx-keyword">if</span> self.skip_empty_rows:
<span class="tx-keyword">if</span> <span class="tx-func">all</span>(v == <span class="tx-string">''</span> <span class="tx-keyword">or</span> v <span class="tx-keyword">is</span> <span class="tx-keyword">None</span> <span class="tx-keyword">for</span> v <span class="tx-keyword">in</span> row.values()):
<span class="tx-keyword">continue</span>
converted = {
k: self.<span class="tx-func">_convert_value</span>(k, v <span class="tx-keyword">or</span> <span class="tx-string">''</span>)
<span class="tx-keyword">for</span> k, v <span class="tx-keyword">in</span> row.items()
<span class="tx-keyword">if</span> k <span class="tx-keyword">is</span> <span class="tx-keyword">not</span> <span class="tx-keyword">None</span>
}
result.append(converted)
<span class="tx-keyword">if</span> progress_callback <span class="tx-keyword">and</span> (i + <span class="tx-num">1</span>) % <span class="tx-num">1000</span> == <span class="tx-num">0</span>:
<span class="tx-func">progress_callback</span>(i + <span class="tx-num">1</span>)
<span class="tx-keyword">if</span> json_path:
<span class="tx-keyword">with</span> <span class="tx-func">open</span>(json_path, <span class="tx-string">'w'</span>, encoding=<span class="tx-string">'utf-8'</span>) <span class="tx-keyword">as</span> f:
json.<span class="tx-func">dump</span>(result, f, ensure_ascii=<span class="tx-keyword">False</span>, indent=indent)
<span class="tx-keyword">return</span> result
<span class="tx-comment"># ===== ์ฌ์ฉ ์์ =====</span>
<span class="tx-comment"># ๊ธฐ๋ณธ ์ฌ์ฉ</span>
converter = <span class="tx-func">CsvToJsonConverter</span>()
data = converter.<span class="tx-func">convert</span>(<span class="tx-string">'input.csv'</span>, <span class="tx-string">'output.json'</span>)
<span class="tx-comment"># ๊ณ ๊ธ ์ฌ์ฉ: ์ปค์คํ
๋ณํ๊ธฐ + ์งํ ์ํฉ ์ถ๋ ฅ</span>
<span class="tx-keyword">from</span> datetime <span class="tx-keyword">import</span> datetime
converter = (
<span class="tx-func">CsvToJsonConverter</span>(delimiter=<span class="tx-string">','</span>, auto_type=<span class="tx-keyword">True</span>)
.<span class="tx-func">add_converter</span>(<span class="tx-string">'birth_date'</span>, <span class="tx-keyword">lambda</span> v: datetime.<span class="tx-func">strptime</span>(v, <span class="tx-string">'%Y-%m-%d'</span>).<span class="tx-func">isoformat</span>() <span class="tx-keyword">if</span> v <span class="tx-keyword">else</span> <span class="tx-keyword">None</span>)
.<span class="tx-func">add_converter</span>(<span class="tx-string">'phone'</span>, <span class="tx-keyword">lambda</span> v: v.<span class="tx-func">replace</span>(<span class="tx-string">'-'</span>, <span class="tx-string">''</span>) <span class="tx-keyword">if</span> v <span class="tx-keyword">else</span> <span class="tx-keyword">None</span>)
)
data = converter.<span class="tx-func">convert</span>(
<span class="tx-string">'users.csv'</span>,
<span class="tx-string">'users.json'</span>,
progress_callback=<span class="tx-keyword">lambda</span> n: <span class="tx-func">print</span>(<span class="tx-string">f"โณ {n:,}ํ ์ฒ๋ฆฌ ์ค..."</span>, end=<span class="tx-string">'\r'</span>)
)
<span class="tx-func">print</span>(<span class="tx-string">f"\n๐ ์๋ฃ! {len(data):,}๊ฐ ๋ ์ฝ๋"</span>)
๐ REST API ์๋ํฌ์ธํธ๋ก ๋ง๋ค๊ธฐ (Flask)
<span class="tx-keyword">from</span> flask <span class="tx-keyword">import</span> Flask, request, jsonify
<span class="tx-keyword">import</span> csv, json, io
app = <span class="tx-func">Flask</span>(__name__)
<span class="tx-comment"># POST /convert โ CSV ํ์ผ ์
๋ก๋ โ JSON ๋ฐํ</span>
@app.<span class="tx-func">route</span>(<span class="tx-string">'/convert'</span>, methods=[<span class="tx-string">'POST'</span>])
<span class="tx-keyword">def</span> <span class="tx-func">convert_csv</span>():
<span class="tx-keyword">if</span> <span class="tx-string">'file'</span> <span class="tx-keyword">not in</span> request.files:
<span class="tx-keyword">return</span> <span class="tx-func">jsonify</span>({<span class="tx-string">'error'</span>: <span class="tx-string">'ํ์ผ์ด ์์ต๋๋ค'</span>}), <span class="tx-num">400</span>
file = request.files[<span class="tx-string">'file'</span>]
<span class="tx-keyword">if</span> <span class="tx-keyword">not</span> file.filename.<span class="tx-func">endswith</span>(<span class="tx-string">'.csv'</span>):
<span class="tx-keyword">return</span> <span class="tx-func">jsonify</span>({<span class="tx-string">'error'</span>: <span class="tx-string">'CSV ํ์ผ๋ง ํ์ฉ๋ฉ๋๋ค'</span>}), <span class="tx-num">400</span>
<span class="tx-keyword">try</span>:
content = file.<span class="tx-func">read</span>().<span class="tx-func">decode</span>(<span class="tx-string">'utf-8-sig'</span>)
reader = csv.DictReader(io.<span class="tx-func">StringIO</span>(content))
result = [<span class="tx-func">dict</span>(row) <span class="tx-keyword">for</span> row <span class="tx-keyword">in</span> reader]
<span class="tx-keyword">return</span> <span class="tx-func">jsonify</span>({
<span class="tx-string">'success'</span>: <span class="tx-keyword">True</span>,
<span class="tx-string">'total'</span>: <span class="tx-func">len</span>(result),
<span class="tx-string">'data'</span>: result
})
<span class="tx-keyword">except</span> Exception <span class="tx-keyword">as</span> e:
<span class="tx-keyword">return</span> <span class="tx-func">jsonify</span>({<span class="tx-string">'error'</span>: <span class="tx-func">str</span>(e)}), <span class="tx-num">500</span>
<span class="tx-keyword">if</span> __name__ == <span class="tx-string">'__main__'</span>:
app.<span class="tx-func">run</span>(debug=<span class="tx-keyword">True</span>)
๐ ์ธ์ด๋ณ ์ถ์ฒ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋ฆฌ
pandas
chardet
papaparse
fast-csv
Jackson
Apache Commons
(ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
(๋ด์ฅ ํจ์)
smarter_csv
โ ์ต์ข ์ฒดํฌ๋ฆฌ์คํธ
- โ๏ธ ์ธ์ฝ๋ฉ: UTF-8 BOM ์ฒ๋ฆฌ + EUC-KR ๋์ ํ์ธ
- โ๏ธ ํน์๋ฌธ์: ์ผํ/์ค๋ฐ๊ฟ/๋ฐ์ดํ ํฌํจ๋ ๊ฐ ํ ์คํธ
- โ๏ธ ๋น ๊ฐ: ๋น ๋ฌธ์์ด โ null ๋ณํ ํ์ธ
- โ๏ธ ํ์ : ์ซ์/๋ถ๋ฆฌ์ธ ํ์ ๋ณํ ํ์ธ
- โ๏ธ ํค๋: ๊ณต๋ฐฑ ์ ๊ฑฐ, ์ค๋ณต ํค๋ ์ฒ๋ฆฌ
- โ๏ธ ๋์ฉ๋: 10๋ง ํ ์ด์ ์คํธ๋ฆฌ๋ฐ ์ฒ๋ฆฌ
- โ๏ธ ์๋ฌ ์ฒ๋ฆฌ: ํ์ผ ์์, ์๋ชป๋ ํ์ ์์ธ ์ฒ๋ฆฌ
- โ๏ธ ํ๊ธ: ensure_ascii=False / JSON_UNESCAPED_UNICODE ์ค์
CSV โ JSON ๋ณํ, ๊ฒ๋ณด๊ธฐ์ ๋จ์ํด ๋ณด์ด์ง๋ง ์ค์ ๋ก๋ ์ธ์ฝ๋ฉ, ํน์๋ฌธ์, ํ์ ๋ณํ, ๋์ฉ๋ ์ฒ๋ฆฌ ๋ฑ ์ ๊ฒฝ ์จ์ผ ํ ๊ฒ ๊ฝค ๋ง์.
์ด ๊ฐ์ด๋์์ ๋ค๋ฃฌ ์ฝ๋๋ค์ ์ค๋ฌด์์ ๋ฐ๋ก ์ธ ์ ์๋ ์์ค์ผ๋ก ๋ง๋ค์์ผ๋, ํ๋ก์ ํธ์ ๋ง๊ฒ ์ปค์คํฐ๋ง์ด์งํด์ ํ์ฉํด๋ด! ๐ช
๊ฐ๋ฐ ๊ด๋ จ ๋ค์ํ ์ฌ๋ฅ์ ์ฐพ๊ณ ์๋ค๋ฉด ์ฌ๋ฅ๋ท์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ, API ๊ฐ๋ฐ, ์๋ํ ์คํฌ๋ฆฝํธ ๋ฑ ๋ค์ํ ๊ฐ๋ฐ ์ฌ๋ฅ์ ๊ฐ์ง ์ ๋ฌธ๊ฐ๋ค์ ๋ง๋๋ณผ ์ ์์ด. ํผ์ ํด๊ฒฐํ๊ธฐ ์ด๋ ค์ด ๋ณํ ์์ ์ด ์๋ค๋ฉด ์ ๋ฌธ๊ฐ์ ๋์์ ๋ฐ๋ ๊ฒ๋ ์ข์ ์ ํ์ด์ผ! ๐
CSV JSON Python JavaScript Java Go PHP ๋ฐ์ดํฐ๋ณํ ํ๋ก๊ทธ๋๋ฐ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.