์๋ก
๊ฐ๋ฐ์๋ก์ ๋๊ท๋ชจ ํ๋ซํผ์ ๋ฏธ๋์ด ๋ฐฐํฌ ๋ฉ์ปค๋์ฆ์ ์ดํดํ๋ ๊ฒ์ ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ๋์ ์
๋๋ค. ๋น์ฆ๋์ค ์์
๋คํธ์ํฌ์ ๊ฑฐ๋์ธ LinkedIn์ ์ฌ์ฉ์ ํ๊ฒฝ์ ์ต์ ํ๋ ๋ฏธ๋์ด ์ ๋ฌ์ ์ํด ๊ณ ๋ํ๋ CSRF ๋ณดํธ, ๋์ API ์๋ช
, ๊ทธ๋ฆฌ๊ณ ์ ๊ตํ HLS(HTTP Live Streaming) ์ํคํ
์ฒ๋ฅผ ์ฑํํ๊ณ ์์ต๋๋ค.
๊ณผ๊ฑฐ์ ๋จ์ํ MP4 ์ ์ ๋งํฌ ์ถ์ถ ๋ฐฉ์์ ๋ ์ด์ ์ ํจํ์ง ์์ต๋๋ค. ๋ณธ ์ํฐํด์์๋ ์ ๊ฐ ๊ฐ๋ฐํ LinkedIn ๋น๋์ค ๋ค์ด๋ก๋์ ๋ฐฑ์๋ ์ค๊ณ๋ฅผ ๋ฐํ์ผ๋ก, HLS ํ๋กํ ์ฝ ์ญ๊ณตํ, ๋น๋๊ธฐ I/O ์ํคํ
์ฒ, ๊ทธ๋ฆฌ๊ณ FFmpeg๋ฅผ ์ด์ฉํ ๋ฌด์์ค ๋จธ์ง(Muxing) ๊ธฐ์ ์ ์ฌ์ธต ๋ถ์ํฉ๋๋ค.
1. ๋ฏธ๋์ด ๋ฐฐํฌ ํ๋กํ ์ฝ์ ์งํ: MP4์์ HLS๋ก
์ด๊ธฐ ์น ๋น๋์ค๋ ๋จ์ผ MP4 ํ์ผ๋ก ์ถฉ๋ถํ์ต๋๋ค. ํ์ง๋ง LinkedIn๊ณผ ๊ฐ์ ๊ธ๋ก๋ฒ ํ๋ซํผ์ ๋คํธ์ํฌ ๋์ญํญ์ ๋ฐ๋ผ ํ์ง์ ๋์ ์ผ๋ก ์กฐ์ ํ๋ HLS ๋๋ DASH๋ฅผ ํ์ค์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
HLS์ ํต์ฌ ๊ตฌ์กฐ
HLS๋ ๋จ์ผ ํ์ผ์ด ์๋๋ผ ์ฌ์ ๋ชฉ๋ก ๊ธฐ๋ฐ์ ๊ตฌ์กฐ์
๋๋ค.
- Master Playlist (.m3u8): ๋ค์ํ ํด์๋(480p, 720p, 1080p ๋ฑ)๋ฅผ ๊ฐ์ง ํ์ ์ฌ์ ๋ชฉ๋ก์ ์ธ๋ฑ์ค์ ๋๋ค.
- Media Playlist: ํน์ ํด์๋ ๋ด์์ ๋ช ์ด ๋จ์๋ก ์ชผ๊ฐ์ง ๋น๋์ค ์ธ๊ทธ๋จผํธ(.ts ๋๋ .m4s) ํ์ผ๋ค์ ๋ชฉ๋ก์ ๋๋ค. ๊ธฐ์ ์ ๊ณผ์ : ์ถ์ถ ์์ง์ .m3u8 ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๋ถ์ํด์ผ ํฉ๋๋ค. ๋น์ฌ์ ์๊ณ ๋ฆฌ์ฆ์ ์ต๊ณ ๋นํธ๋ ์ดํธ(Highest Bitrate) ํธ๋์ ์๋์ผ๋ก ์๋ณํ์ฌ, ์ฌ์ฉ์๊ฐ ์ ๋์ญํญ ํ๊ฒฝ์ ์ ํ์ง ์์์ด ์๋ ์ต์์ ์๋ณธ ํ์ง์ ํ๋ณดํ ์ ์๋๋ก ์ค๊ณ๋์์ต๋๋ค.
2. ์ญ๊ณตํ: LinkedIn์ ์ธ์ฆ ๊ฒ์ดํธ์จ์ด ์ฐํ
LinkedIn์ ๋ด๋ถ API๋ ๋งค์ฐ ์๊ฒฉํ๊ฒ ๋ณดํธ๋ฉ๋๋ค. ์ผ๋ฐ์ ์ธ curl ์์ฒญ์ ๋ณด๋ด๋ฉด ๋๋ถ๋ถ 401 Unauthorized ๋๋ 403 Forbidden ์๋ฌ๋ฅผ ๋ง์ฃผํ๊ฒ ๋ฉ๋๋ค.
๋์ ํ ํฐ ๋ฐ ์ธ์
๊ด๋ฆฌ
LinkedIn์ ๋ค์ธต์ ์ธ ๊ฒ์ฆ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํฉ๋๋ค.
โข CSRF ํ ํฐ: HTML ํค๋๋ ์ฟ ํค์ ํฌํจ๋ ๋์ ๊ฒ์ฆ ๊ฐ.
โข JSESSIONID: ์ธ์
์ถ์ ์ ์ํ ํต์ฌ ์๋ณ์.
๊ตฌํ ์ ๋ต: ๋ฐฑ์๋์๋ ์๊ฐ ์น์ ํ ์ธ์
ํ(Self-healing Session Pool)์ ๊ตฌ์ถํ์ต๋๋ค. ์ถ์ถ ์์ง์ด ์์ฒญ์ ๋ณด๋ผ ๋, ํ๋์ ์ธ ๋ธ๋ผ์ฐ์ ์ ์ ์ฒด ์์ฒญ ํค๋(User-Agent, Referer, ์ํธํ ์๋ช
๋ฑ)๋ฅผ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค. ๋ง์ฝ ํ ํฐ ๋ง๋ฃ๋ ์๋ ์ ํ(Rate Limit)์ด ๊ฐ์ง๋๋ฉด, ๋ฐฑ์๋๋ ํค๋๋ฆฌ์ค ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ์ต์ํ์ ์กํฐ๋ธ ๋์์ ์๋ฎฌ๋ ์ด์
ํ์ฌ ์๋ก์ด ์ธ์ฆ ์ปจํ
์คํธ๋ฅผ ์๋ ๊ฐฑ์ ํฉ๋๋ค.
3. ๋ฐฑ์๋ ์ํคํ ์ฒ: ๋น๋๊ธฐ I/O๋ฅผ ํตํ ๊ณ ๊ฐ์ฉ์ฑ ์ฒ๋ฆฌ
๊ธ๋ก๋ฒ ํธ๋ํฝ์ ๊ฐ๋นํ๊ธฐ ์ํด linkedin_downloader_ko ๋ฐฑ์๋๋ ์ ํต์ ์ธ ๋ธ๋กํน ๋ฐฉ์ ๋์ Python Asyncio + Httpx ๊ธฐ๋ฐ์ ์์ ๋น๋๊ธฐ ์คํ์ ์ฑํํ์ต๋๋ค.
์ ๋น๋๊ธฐ(Asynchronous)์ธ๊ฐ?
๋น๋์ค ์ถ์ถ์ ์ ํ์ ์ธ I/O-bound ์์
์
๋๋ค. ๋จ์ผ ์์ฒญ์ ๋ค์์ ํฌํจํฉ๋๋ค:
- LinkedIn ํ์ด์ง HTML ํ์ฑ ๋ฐ ๋ฉํ๋ฐ์ดํฐ ์ถ์ถ.
- GraphQL ๋๋ ๋ด๋ถ REST API๋ฅผ ํตํ ๋ฏธ๋์ด ์ค์ ์ฟผ๋ฆฌ.
- ๋คํธ์ํฌ๋ฅผ ํตํ ๋ค๋จ๊ณ .m3u8 ํ์ผ ์ฌ๊ท์ fetch. ๋๊ธฐ์ ๋ชจ๋ธ์์๋ ๋คํธ์ํฌ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์์ปค ํ๋ก์ธ์ค๊ฐ ์ ํด ์ํ๊ฐ ๋ฉ๋๋ค. ๋ฐ๋ฉด asyncio๋ฅผ ํ์ฉํ๋ฉด ๋จ์ผ ํ๋ก์ธ์ค๋ก ์์ฒ ๊ฐ์ ์ถ์ถ ์์ ์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ ์ ์์ด, ์๋ฒ ํ๋์จ์ด ๋น์ฉ์ ์ ๊ฐํ๋ฉด์ ์๋ต ์๋๋ฅผ ๊ทน๋ํํ ์ ์์ต๋๋ค.
4. ๋น๋์ค ํฉ์ฑ: FFmpeg๋ฅผ ํ์ฉํ Lossless Muxing
HLS ์ธ๊ทธ๋จผํธ๋ฅผ ๋ชจ๋ ๋ถ์ํ ํ, ๋ง์ง๋ง ๋จ๊ณ๋ ์๋ฐฑ ๊ฐ์ .ts ํ์ผ์ ํ๋์ MP4 ํ์ผ๋ก ํฉ์ณ ์ฌ์ฉ์์๊ฒ ์ ๋ฌํ๋ ๊ฒ์
๋๋ค.
์คํธ๋ฆผ ๋ณต์ฌ(Stream Copying) vs ์ธ์ฝ๋ฉ
์ฐ๋ฆฌ๋ ์๋ฒ ์ธก ํ์ดํ๋ผ์ธ์ FFmpeg๋ฅผ ํตํฉํ์ต๋๋ค. ์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ ์ต์ ํ ํฌ์ธํธ๋ Stream Copying ๊ธฐ์ ์
๋๋ค.
Bash
ffmpeg -i "concat:segment1.ts|segment2.ts|..." -c copy -map 0โ๏ธ0 -map 1๐
ฐ๏ธ0 output.mp4
๊ธฐ์ ์ ํต์ฐฐ: -c copy ํ๋๊ทธ๊ฐ ํต์ฌ์
๋๋ค. ์ด๋ FFmpeg์๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ธ์ฝ๋ฉํ์ง ์๊ณ , ๋จ์ํ ๋ฐ์ดํฐ ํจํท์ TS ์ปจํ
์ด๋์์ MP4 ์ปจํ
์ด๋๋ก '์ฌ๋ฐฐ์น'ํ๋๋ก ์ง์ํฉ๋๋ค. ์ด ๊ณผ์ ์ CPU์ ๊ฑฐ์ ๋ถํ๋ฅผ ์ฃผ์ง ์์ผ๋ฉฐ, ์ฒ๋ฆฌ ์๊ฐ์ด ๊ฑฐ์ ์ฆ๊ฐ์ ์ผ ๋ฟ๋ง ์๋๋ผ 100% ์๋ณธ ํ์ง์ ๊ทธ๋๋ก ์ ์งํฉ๋๋ค.
5. ํ๋ก ํธ์๋ ์ต์ ํ: ์ ํธ๋ฆฌํฐ ์ค์ฌ์ UX
๊ฐ๋ฐ์๊ฐ ์ ํธํ๋ ๋๊ตฌ๊ฐ ๋๊ธฐ ์ํด ํ๋ก ํธ์๋์์๋ ๋ถํ์ํ ์์๋ฅผ ์ ๊ฑฐํ์ต๋๋ค.
โข Vanilla JS ๊ธฐ๋ฐ: ๋ฌด๊ฑฐ์ด ํ๋ ์์ํฌ๋ฅผ ๋ฐฐ์ ํ๊ณ ์์ JavaScript๋ก ๋ก์ง์ ์์ฑํ์ฌ FCP(First Contentful Paint)๋ฅผ 1์ด ๋ฏธ๋ง์ผ๋ก ๋จ์ถํ์ต๋๋ค.
โข PWA ์ง์: ํ๋ก๊ทธ๋ ์๋ธ ์น ์ฑ ๊ท๊ฒฉ์ ์ค์ํ์ฌ ๋ชจ๋ฐ์ผ์ด๋ ๋ฐ์คํฌํฑ์ ์ฑ์ฒ๋ผ ์ค์นํด ์ฌ์ฉํ ์ ์์ต๋๋ค.
โข ๋ณด์ ๋ฐ ๊ฐ์ธ์ ๋ณด: ๋ชจ๋ ํ๋ก์ธ์ค๋ ์๋ฒ ์ฌ์ด๋์์ ์๋ฃ๋๋ฏ๋ก, ์ฌ์ฉ์๋ ๊ฐ์ธ์ ๋ณด ์ ์ถ ์ํ์ด ์๋ ๋ธ๋ผ์ฐ์ ํ์ฅ ํ๋ก๊ทธ๋จ์ ์ค์นํ ํ์๊ฐ ์์ต๋๋ค.
6. ์ค๋ฆฌ์ ๊ฐ์ด๋๋ผ์ธ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
์ด๋ฌํ ๋๊ตฌ๋ฅผ ๊ตฌ์ถํ ๋๋ ์ ์ฉ์ฑ๊ณผ ๊ท์ ์ค์ ์ฌ์ด์ ๊ท ํ์ด ํ์ํฉ๋๋ค.
โข ๊ฐ์ธ์ ๋ณด ๋ณดํธ: ๋น์ฌ๋ ์ฌ์ฉ์์ ๋น๋์ค ํ์ผ์ ์๊ตฌ์ ์ผ๋ก ๋ณด๊ดํ์ง ์์ต๋๋ค. ์์ ๋ฐ์ดํฐ๋ ์ ๋ฌ ์งํ ์ฆ์ ์ญ์ ๋ฉ๋๋ค.
โข ์๋ ์ ํ ์ค์: ๋ด๋ถ ํ(Queuing) ์์คํ
์ ๊ตฌํํ์ฌ LinkedIn ์ธํ๋ผ์ ๋ถํ์ํ ๋ถํ๋ฅผ ์ฃผ์ง ์๋๋ก ๊ด๋ฆฌํฉ๋๋ค.
๊ฒฐ๋ก
๊ณ ์ฑ๋ฅ ๋น๋์ค ๋ค์ด๋ก๋๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ ๋จ์ํ ํฌ๋กค๋ง ์์
๊ทธ ์ด์์
๋๋ค. ์ด๋ ํ๋์ ์ธ ์น ํ๋กํ ์ฝ, API ์ญ๊ณตํ, ๊ทธ๋ฆฌ๊ณ ํจ์จ์ ์ธ ๋ฏธ๋์ด ์ฒ๋ฆฌ ๊ธฐ์ ์ ๋ํ ์ฌ๋ ์๋ ์ดํด๋ฅผ ํ์๋ก ํฉ๋๋ค. HLS ํ์ฑ ๋ก์ง์ ์ต์ ํ์ ๋น๋๊ธฐ ๋ฐฑ์๋ ์ํคํ
์ฒ์ ๊ฒฐํฉ์ ํตํด ์ฐ๋ฆฌ๋ ์ด๊ณ ์ ๋น๋์ค ์ถ์ถ ๊ฒฝํ์ ๊ตฌํํ์ต๋๋ค.
LinkedIn์ ์์คํ ์ธ๋ฏธ๋ ์์์ด๋ ๋น์ฆ๋์ค ์๋ฃ๋ฅผ ์์ ํ๊ณ ๊นจ๋ํ๊ฒ ์์ฅํ๊ณ ์ถ์ ๊ฐ๋ฐ์๋ผ๋ฉด ์ง๊ธ ๋ฐ๋ก ํ์ธํด ๋ณด์ธ์.
๐ ์๋น์ค ๋งํฌ: LinkedIn ๋น๋์ค ๋ค์ด๋ก๋ (ํ๊ตญ์ด ๋ฒ์ )
๊ธฐ์ ์คํ ์์ฝ:
โข Backend: Python / Django / Redis / FFmpeg
โข Architecture: Asyncio / Distributed Crawling
โข Frontend: HTML5 / Tailwind CSS / Vanilla JS
โข Infrastructure: Cloudflare / Docker / Nginx
HLS ํ์ฑ์ด๋ FFmpeg ๋จธ์ง, ํน์ LinkedIn์ ์คํธ๋ฆฌ๋ฐ ์๊ณ ๋ฆฌ์ฆ์ ๋ํด ์๊ฒฌ์ด ์๋ค๋ฉด ๋๊ธ๋ก ์์ ๋กญ๊ฒ ํ ๋ก ํด ์ฃผ์ธ์!














