βμ€μκ° λ°©μ‘, λμΉμ§ λ§κ³ CatchLive νμΈμ!β
βλΉμ μ μ€νΈλ¦¬λ¨Έμ μ€νΈλ¦¬λ° μκ°μ μλμΌλ‘ μΊμΉν΄λ립λλ€.β
- νλ‘μ νΈ κ°μ
- νλ‘μ νΈ λκΈ°
- λ ν¬μ§ν°λ¦¬ μν
- ν΅μ¬ κΈ°λ₯
- κΈ°μ μ€ν
- κ°λ° μ€ κ³ λ―Όκ³Ό ν΄κ²°
- λ©€λ² μκ°
- νκ³
- νλ‘μ νΈλͺ : CatchLive
- κΈ°κ°: 2025.5.26 ~ 2025.6.20 (κΈ°ν 1μ£Ό / κ°λ° λ° λ°°ν¬ 4μ£Ό)
- λͺ©μ : μ€μκ° λΌμ΄λΈ μ€νΈλ¦¬λ° λ Ήνλ₯Ό μν νλ‘μ νΈ
- λμ μ¬μ©μ: λΌμ΄λΈ μ€νΈλ¦¬λ° λ°©μ‘ μκ°μ μ½μμ΄ μμ΄μ λ³΄μ§ λͺ»νλ μ¬λλ€
μ€μκ° λΌμ΄λΈ μ€νΈλ¦¬λ°μ μ μ λ λ§μ μ½ν μΈ κ° μμ±λκ³ μλΉλλ ν΅μ¬ νλ«νΌμ΄ λκ³ μμ΅λλ€. νμ§λ§ νλ«νΌ μ체μμ λΌμ΄λΈ λ°©μ‘μ λ€μ 보기 κΈ°λ₯ μμ΄ μ’ λ£ν΄λ²λ¦¬λ κ²½μ°κ° λ§κ³ , μ¬μ©μλ€μ΄ λμΉ λ°©μ‘μ λ€μ μμ²ν μ μλ λ°©λ²μ μ νμ μ λλ€.
νΉν ν¬λ€ μ€μ¬μ μ½ν μΈ μλΉκ° νλ°ν μ§κΈ, μ€μκ° μ€νΈλ¦¬λ°μ λμΉλ©΄ μμ λ³Ό μ μλ μμ¬μμ μ¬μ©μμκ² ν° λΆνΈν¨μ΄ λ©λλ€. λν ν¬λ¦¬μμ΄ν°λ λ°μ΄ν° λΆμκ° μ μ₯μμλ λ°©μ‘ κΈ°λ‘μ 보κ΄νκ±°λ νμ μ½ν μΈ μ μμ νμ©ν μ μλ μλ¨μ΄ νμν©λλ€.
μ΄ νλ‘μ νΈλ YouTube, μΉμ§μ§(Chzzk) λ± λ€μν νλ«νΌμμ μ€μκ° λ°©μ‘μ΄ μμλλ©΄ μλμΌλ‘ κ°μ§νκ³ , λ°©μ‘ μ’ λ£ μκΉμ§ μμ μ μΌλ‘ λ Ήνν΄μ£Όλ λ°±μλ μμ€ν μ ꡬνν κ²μ λλ€.
μ±λ ꡬλ β λΌμ΄λΈ κ°μ§ β λ Ήν μμ β S3 μ λ‘λ β μλ£ μλ¦Ό β μμ λ€μ΄λ‘λκΉμ§ μλνλ νμ΄νλΌμΈμ ν΅ν΄ ν¬, ν¬λ¦¬μμ΄ν°, νλ«νΌ μ΄μμ λͺ¨λμκ² μ μ©ν μ€νΈλ¦¬λ° λ°±μ μμ€ν μ λ§λλ κ²μ΄ λͺ©νμμ΅λλ€.
ν΄λΌμ΄μΈνΈ λ ν¬μ§ν 리 | μλ² λ ν¬μ§ν 리
ν΄λΉ λ ν¬μ§ν 리λ CatchLive μλΉμ€μ μλ² κ΄λ ¨ μ½λλ₯Ό κ΄λ¦¬νλ μ μ₯μμ λλ€.
νλμ λ ν¬μ§ν 리 λ΄μμ λ€μκ³Ό κ°μ μΈ κ°μ§ μλ²λ₯Ό ν¨κ» μ΄μν©λλ€
- API μλ²: ν΄λΌμ΄μΈνΈμ ν΅μ νλ©° μ¬μ©μ μΈμ¦, μΌμ , μ±ν , ꡬλ λ± λΉμ¦λμ€ λ‘μ§μ μ²λ¦¬ν©λλ€.
- λͺ¨λν°λ§ μλ²: λ Ήν μν νμΈ, μ컀 ν¬μ€μ²΄ν¬ λ± μμ€ν μ μνλ₯Ό λͺ¨λν°λ§ν©λλ€.
- λ Ήν μ컀 μλ²: μ€μκ° λ°©μ‘μ λ°±κ·ΈλΌμ΄λμμ λ Ήννκ³ , μ²λ¦¬ λ° μ μ₯μ λ΄λΉν©λλ€.
βΈ»
κΈ°μ‘΄μ λ μ΄μ΄λ μν€ν μ²(Layered Architecture) μ ν΄λ¦° μν€ν μ²(Clean Architecture) μ¬μμ μ μ©ν΄μ λ€μκ³Ό κ°μ 4κ°μ μ£Όμ λ μ΄μ΄λ‘ ꡬμ±λμ΄ μμ΅λλ€.
-
Domain λ μ΄μ΄ β’ μλΉμ€μ ν΅μ¬ λΉμ¦λμ€ κ·μΉκ³Ό λλ©μΈ λͺ¨λΈμ μ μν©λλ€. β’ κΈ°μ ꡬνκ³Ό 무κ΄ν μμν λ‘μ§(μν°ν°, λλ©μΈ μλΉμ€ λ±)μ ν¬ν¨ν©λλ€. β’ μ μ₯μμ λν μ κ·Όμ μ§μ νμ§ μμΌλ©°, repository interfaceλ§ μ μν©λλ€.
-
Application λ μ΄μ΄ β’ μ€μ μ¬μ©μμ μμ²μ λν μ μ€μΌμ΄μ€λ₯Ό μ μν©λλ€. β’ λλ©μΈ κ°μ²΄λ€μ μ‘°ν©νμ¬ κ΅¬μ²΄μ μΈ μμ νλ¦μ ꡬμ±ν©λλ€. β’ νΈλμμ μ μ΄, μλΉμ€ νΈμΆ μμ κ΄λ¦¬ λ± μ²λ¦¬ νλ¦μ λ΄λΉν©λλ€.
-
Interface λ μ΄μ΄ β’ μΈλΆμμ μ°κ²° μ§μ μΌλ‘, Controller, Module, DTO λ±μ΄ ν¬ν¨λ©λλ€. β’ ν΄λΌμ΄μΈνΈ μμ²μ λ°μ application layerμ μ μ€μΌμ΄μ€λ₯Ό νΈμΆνκ³ , μλ΅μ λ°νν©λλ€. β’ μΈμ¦, κΆν 체ν¬, μμ²κ° κ²μ¦ λ±μ μν λ μ΄ λ μ΄μ΄μμ μ²λ¦¬ν©λλ€.
-
Infrastructure λ μ΄μ΄ β’ λ°μ΄ν°λ² μ΄μ€, νμΌ μμ€ν , μΈλΆ API λ± μΈλΆ μμ€ν κ³Όμ μ°κ²°μ λ΄λΉν©λλ€. β’ repository interfaceμ μ€μ ꡬν체λ€μ΄ μ΄κ³³μ μμΉν©λλ€. β’ Prisma ORM, S3, Redis λ±μ μΈλΆ λꡬλ₯Ό μ¬μ©νλ ꡬ체μ μΈ μ½λκ° ν¬ν¨λ©λλ€.
- μ¬μ©μλ μνλ μ€νΈλ¦¬λ¨Έλ₯Ό ꡬλ
ν μ μμ΅λλ€.(CHZZK or YOUTUBE)
- μ΅λ 5λͺ κΉμ§ μ€νΈλ¦¬λ¨Έλ₯Ό ꡬλ ν μ μμ΅λλ€.
- ꡬλ ν μμ λΆν° μ€νΈλ¦¬λ¨Έκ° λΌμ΄λΈ μ€μΌ κ²½μ° μλμΌλ‘ λ Ήνκ° μμλ©λλ€.
- μ¬μ©μλ νμ¬ μμ μ΄ κ΅¬λ μ€μΈ λ Ήν μν©μ λ³Ό μ μμ΅λλ€.
- λ°©μ‘μ΄ μ’
λ£λ κ²½μ°, λ€μ΄λ‘λλ₯Ό ν΅ν΄ λ
Ήν νμΌμ νμΈν μ μμ΅λλ€.
- μ΅λ 3μΌκΉμ§ λ€μ΄λ‘λ κ°λ₯ν©λλ€.
- κ²μμ ν΅ν΄ μμ μ΄ μ°Ύκ³ μΆμ λ Ήν νμΌμ μ°Ύμ μ μμ΅λλ€.
- Language: Node 18
- Framework: NestJS 11
- Database: MySQL 8.xx
- Infrastructure: Redis 7.x
- ORM: Prisma 6.8
- Authentication: OAuth2 + JWT
- CI/CD: GitHub Actions + Docker + AWS Elastic Beanstalk
- Middleware: AWS ElasticCache, AWS S3, AWS RDS
Nest.jsλ λͺ¨λ κΈ°λ° μν€ν μ²μ μμ‘΄μ± μ£Όμ κΈ°λ₯, λ°μ½λ μ΄ν° κΈ°λ₯λ€μ μ 곡νλ TypeScript μ€μ¬μ Node.js νλ μμν¬μ λλ€. Node.jsλ₯Ό κΈ°λ°μΌλ‘ νκΈ° λλ¬Έμ λΉλλ 컨ν μ΄λμ ν¬κΈ°κ° μκ³ , λ°νμμ κΈ°λ³Έμ μΌλ‘ μ μ νλ 리μμ€λ μ μ΄ μ κ· μλΉμ€λ₯Ό μ μνκ³ μ΄μνλλ° μ ν©ν©λλ€.
Express.js μ λΉκ΅νμ¬, λ°μ½λ μ΄ν°μ λͺ¨λ μμ‘΄μ± μ»¨νΈλ‘€ λ±μ μΆκ°λ‘ νμ΅ν΄μΌ λμ§λ§, λ‘κ·ΈμΈ, ν ν° κ΄λ¦¬ κ°μ λ리 μ°μ΄λ κΈ°λ₯λ€μ λ°μ½λ μ΄ν°λ₯Ό ν΅ν΄ μ½κ² μ¬μ©ν μ μκ³ , 리μμ€ μ μ λ λΉλλ 컨ν μ΄λ νμΌλ±μ΄ μ 체μ μΌλ‘ κ°λ³κΈ° λλ¬Έμ AWS λ°°ν¬μλ μ ν©νλ€κ³ νλ¨λμ΄ Nest.js λ₯Ό μ¬μ©νκΈ°λ‘ νμ΅λλ€.
Prismaλ μ μΈν μ€ν€λ§μ μλ λ§μ΄κ·Έλ μ΄μ , νμ μ μΈκ³Ό κ²μ¬, μ§κ΄μ APIλ‘ κ°λ° μμ°μ±κ³Ό μμ μ±μ κ·Ήλννλ ORMμ λλ€. μμ±ν μ€ν€λ§λ₯Ό ν΅ν΄ μ€μ DBμ ꡬ쑰λ₯Ό μλ μμ±ν μ μμΌλ©°, SQLλμ Prismaμμ μ 곡νλ κΈ°λ₯μ μ¬μ©νμ¬ μ€μ λ‘ μΏΌλ¦¬λ₯Ό μμ²νκΈ° μ μ μλ¬λ₯Ό κ°μ§ν μ μκ³ , transaction κ°μ κΈ°λ₯λ€λ Prismaλ₯Ό ν΅ν΄ κ°λ¨νκ² μ¬μ©ν μ μμ΅λλ€.
TypeORMλ SQL λμ μ 곡νλ κΈ°λ₯λ€μ μΈ μ μμΌλ, μ»΄νμΌ λ¨κ³μμ νμ κ²μ¬λ₯Ό νμ§ μμ μ€λ₯ κ²μ¬, μμ μ΄ λ²κ±°λ‘κ³ , Prismaμ λΉν΄ μλμΌλ‘ μ 곡νλ κΈ°λ₯μ΄ μ μ΄ κ°λ° μμκ° λμ΄λ μ μμ΅λλ€. κ·Έλμ μ’ λ κ°νΈνκ² μ¬μ©ν μ μκ³ λ€μν κΈ°λ₯λ€μ μ 곡νλ Prismaλ₯Ό μ¬μ©νκΈ°λ‘ νμ΅λλ€.
MySQLμ μ€ν μμ€ κΈ°λ°μ κ΄κ³ν λ°μ΄ν°λ² μ΄μ€ κ΄λ¦¬ μμ€ν μΌλ‘, μμ μ μ΄κ³ ν¨μ¨μ μΌλ‘ λμ©λ λ°μ΄ν°λ₯Ό μ μ₯Β·κ΄λ¦¬ν μ μμ΅λλ€. λ°μ΄ν°μ νμ μ μ μνμ¬ μλͺ»λ κ°μ΄ κΈ°λ‘λ μν©μ λ°©μ§ν μ μμΌλ©°, νΈλμμ μ μ£Όμ μμ±μΈ ACIDλ₯Ό μ€μν©λλ€. AWSλ₯Ό λΉλ‘―ν λ§μ ν΄λΌμ°λνλ«νΌμμ MySQLμ μ§μνκΈ° λλ¬Έμ λ€μν μν©, νκ²½μμλ μμ μ μΌλ‘ μ¬μ©ν μ μμ΅λλ€.
MongoDBλ±μ ν¬ν¨ν NoSQLμ μ μ°ν λ°μ΄ν° ꡬ쑰λ₯Ό κ°μ§ μ μμΌλ, νμ¬ κ°λ° νλ‘μ νΈλ λͺ νν λ°μ΄ν° ꡬ쑰λ₯Ό κ°μ§κ³ μκ³ , μ΄λ₯Ό μλμΌλ‘ μ격νκ² κ΄λ¦¬ν΄μΌ νκΈ° λλ¬Έμ κ΄κ³ν λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©νκΈ°λ‘ νμ΅λλ€.
Redisλ λ©λͺ¨λ¦¬ κΈ°λ°μ κ³ μ±λ₯ ν€-κ° λ°μ΄ν° μ μ₯μλ‘, μ¬μ©μμ μλ², μλ²μ μλ² μ¬μ΄μμ μμλ‘ μ¬μ©νλ λ°μ΄ν°λ€μ κ΄λ¦¬νλλ° μ¬μ©ν©λλ€. λ¬Έμμ΄(string), 리μ€νΈ(list), μ§ν©(set), μ λ ¬λ μ§ν©(sorted set), ν΄μ(hash) λ± λ€μν λ°μ΄ν° ꡬ쑰λ₯Ό λ©λͺ¨λ¦¬μμ μ§μ μ§μν΄ λ³΅μ‘ν μΊμΒ·νλ₯Ό μμ½κ² ꡬνν μ μμ΅λλ€. λν Pub/Subκ³Ό Streams κΈ°λ₯μ νμ©ν΄ μ€μκ° λ©μμ§, μ΄λ²€νΈ κΈ°λ° μ²λ¦¬, μμ νμ΄νλΌμΈ κΈ°λ₯μ ν΅ν΄ λΆμ° μμ€ν μ μ§μν μ μμ΅λλ€
νμ¬ κ°λ° νλ‘μ νΈμμλ λ Ήν μμ μ μννλ λΆμ° μμ€ν μ μ§μν κΈ°λ₯λ€μ΄ νμνμ¬ Redisλ₯Ό μ¬μ©νκΈ°λ‘ νμ΅λλ€.
μλ¦Όμ΄λ μν λͺ©λ‘λ€μ μΌμ λ²μ μμλ€ μμ±νκ³ , μ΄λ₯Ό μ€ν¬λ‘€ν΄μ λ³Ό μ μλλ‘ κ³ννκ³ κ°λ°μ μμνμ΅λλ€.
κ·Έλ¬λ μν λͺ©λ‘λ€μ΄ μΌμ λ²μ λ°μ λ²μ΄λμ νλ¨ λ€λΉκ²μ΄μ λ°λ₯Ό λ°μ΄λ΄κ±°λ, λ²μ λ°κΉ₯μΌλ‘ κ³μ μμ±λκ³ , μ€ν¬λ‘€ λ°λ κ³ν μΈμ λΆλͺ¨ 컨ν μ΄λμ μ μ©λμ΄ λͺ©λ‘ μΈ μ»¨ν μ΄λλ€λ κ°μ΄ μ€ν¬λ‘€λλ μ¦μμ΄ λ°μνμ΅λλ€.
width λ heightμ min, maxλ±μ μ§μ νμ§ μμΌλ©΄ λν΄νΈ μ€μ μΈ autoκ° λκ³ ,
λλΆλΆμ κ²½μ°, width, height λ₯Ό λ€μκ³Ό κ°μ 곡μμΌλ‘ κ³μ°ν©λλ€.
'width' + 'μ’μ° margin' + 'μ’μ° border' + 'μ’μ° padding' = blockμ μ 체 widthμ€ν¬λ‘€ λμμΈ μμ 컨ν
μ΄λλ€λΆν° μ΅μλ¨κΉμ§, μ΄λ νλλΌλ auto κ°μΌλ‘ μ€μ λμ΄μλ€λ©΄
λ³ΈμΈμ ν¬κΈ°λ₯Ό μμ 컨ν
μ΄λμ ν¬κΈ°λ₯Ό ꡬν λ€μ κ·Έ κ°μ λ§μΆκΈ° λλ¬Έμ μλμΉ μμ λΆλͺ¨ 컨ν
μ΄λμ μ€ν¬λ‘€μ΄ μ μ©λκ±°λ, λ€λ₯Έ 컨ν
μΈ λ€μ΄ νλ©΄ λ°μΌλ‘ λ°λ €λ μ μμ΅λλ€.
λ°λΌμ μμ 컨ν
μ΄λλΆν° μ΅μλ¨ λΆλͺ¨ 컨ν
μ΄λκΉμ§, auto μ€μ μ΄ λμ§ μλλ‘ min-h-0 κ°μ μ΅μ
λ€μ μμ±ν΄μΌ μλν λλ‘ μΌμ λ²μμμ μμ 컨ν
μ΄λλ€μ΄ μκ³ , μ€ν¬λ‘€ν΄μ λͺ¨λ μμ 컨ν
μ΄λλ₯Ό λ³Ό μ μλλ‘ ν μ μμ΅λλ€.
μκ°μ§λ λͺ»ν CSS λ¬Έμ μκΈ°μ κ½€ μ€λ μκ°μ΄ μμλμ΅λλ€. auto λ μμ 컨ν
μ΄λμ κ°μ λ¨Όμ ꡬνκ³ , κ·Έ κ°μ λ§μΆ°μ λΆλͺ¨μ κ°μ ꡬνλ€λκ²μ λͺ
μ¬ν΄μΌκ² λ€κ³ μκ°νμ΅λλ€.
μ΄μ μ μμ±λ useInfinityQueryλ₯Ό λ³λλ‘ ν
νλ¦Ών μμΌμ, useInfinityQuery λ₯Ό μ¬μμ±ν νμ μμ΄, μ ν΄μ§ ν
νλ¦Ώλλ‘ μ
λ ₯νλ©΄ λμνλλ‘ κ΅¬ννκ³ μμμ΅λλ€.
리ν΄κ°μ νμ μΆλ‘ μ μ€ν¨νμ¬ κ³μ νμ μ€ν¬λ¦½νΈ μ€λ₯κ° λ°μνμμ΅λλ€.
μ΄μ μ μμ±λ μ½λμμ κ³ μ λ μ΅μ
κ°μ μΆκ°λ‘ μ
λ ₯λ°μμ μλλ‘ ...options λ₯Ό μΆκ°νμλλ°, μ΄λ κ² μ΅μ
κ°μ΄ κ³ μ μ΄ μλ λ³μκ° λλ©΄ 리ν΄κ°μ νμ
μΆλ‘ νλλ° μ€ν¨νλκ²μΌλ‘ 보μ
λλ€. λ°λΌμ μ΄μ μλ μλμΌλ‘ InfiniteData<T, number | null>λ‘ λ³νν΄μ λ³ λ¬Έμ μμ΄ μ€νλ λ¦¬ν΄ νμ
T λ₯Ό InfiniteData<T, number | null>λ‘ μ μΈνμ¬ μ¬λ°λ₯Έ 리ν΄κ° νμ
μ μΆλ‘ νλλ‘ μμ νμμ΅λλ€.
μ΅μ κ°μ΄ κ³ μ μ΄μμλ μλμΌλ‘ νμ μ λ³ννμ¬ λ¦¬ν΄νκΈΈλ μλμΌλ‘ νμ μ λ³νν΄μ£Όλ κΈ°λ₯μ΄ λΌμ΄λΈλ¬λ¦¬μ μλ€κ³ μκ°νμ¬ μ€λμκ° λ€λ₯Έ λ°©ν₯μμ λ¬Έμ μ μμΈμ μ°Ύμμ΅λλ€. λ¬Έμ μ μμΈμ μΆλ‘ ν λ μ’ λ μ€ν λ§μΈλλ‘ κ°μ€μ μΈμΈ νμκ° μλ€κ³ μκ°νμ΅λλ€.
μμ λ‘κ·ΈμΈ κΈ°λ₯μ ꡬννλ©΄μ κ°μ₯ κ³ λ―Όνλ λΆλΆμ μΉ΄μΉ΄μ€, λ€μ΄λ², ꡬκΈμ²λΌ μλ‘ λ€λ₯Έ νλ«νΌμ μΈμ¦ λ°©μκ³Ό μλ΅ ν¬λ§·μ μ΄λ»κ² μΌκ΄λκ² μ²λ¦¬ν κ²μΈκ°μμ΅λλ€.
μ²μμλ μΈμ¦ λ‘μ§μ νλμ μλΉμ€(AuthService) μμ λͺ¨λ μμ±νμ΅λλ€. νλ«νΌμ λ°λΌ if λ¬ΈμΌλ‘ μΈμ¦ νλ¦μ λΆκΈ°νλλ°, μ΄ λ°©μμ λΉμ₯μ λμνμ§λ§ μ μ κ΅¬μ‘°κ° λ¬΄κ±°μμ‘μ΅λλ€.
κ° νλ«νΌλ§λ€ μΈκ° μ½λ μμ², ν ν° λ°κΈ, μ¬μ©μ μ 보 μ‘°ν νλ¦μ μ μ¬νμ§λ§, μΈλΆ νλΌλ―Έν°λ API μλν¬μΈνΈ, μλ΅ ν¬λ§·μ΄ λ¬λΌ λΉμ·ν λ‘μ§μ΄ λ°λ³΅λμκ³ , κ·Έλ‘ μΈν΄ νλμ νμΌ λ΄ μ½λλμ΄ λ§μμ§λ©΄μ κ°λ μ±μ΄ μ μ λ¨μ΄μ§λ λ¬Έμ κ° λ°μνμ΅λλ€.
λν μλ‘μ΄ μμ λ‘κ·ΈμΈ λ°©μμ μΆκ°ν λλ§λ€ κΈ°μ‘΄ μ½λμ μμ λμΌ νκ³ , μ΄λ ν₯ν νμ₯μ±κ³Ό μμ μ± λͺ¨λμ μ’μ§ μλ€κ³ νλ¨νμ΅λλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ μ λ΅ ν¨ν΄(Strategy Pattern) μ λμ νμ΅λλ€. ν΅μ¬ μμ΄λμ΄λ νλ«νΌλ³ μΈμ¦ λ‘μ§μ κ°κ°μ μ λ΅ ν΄λμ€λ‘ λΆλ¦¬νκ³ , μ΄λ€μ 곡ν΅λ μΈν°νμ΄μ€λ‘ λ¬Άμ΄ μΌκ΄λ λ°©μμΌλ‘ μ€νν μ μλ ꡬ쑰λ₯Ό λ§λλ κ²μ΄μμ΅λλ€.
λ¨Όμ , μΉ΄μΉ΄μ€, λ€μ΄λ², κ΅¬κΈ λ± κ° μμ λ‘κ·ΈμΈ νλ«νΌμ λν΄ λ³λμ μ λ΅ ν΄λμ€λ₯Ό λ§λ€μμ΅λλ€. κ° μ λ΅ ν΄λμ€λ ν΄λΉ νλ«νΌμ νΉνλ μΈκ° μ½λ μ²λ¦¬, ν ν° λ°κΈ, μ¬μ©μ μ 보 μ‘°ν λ‘μ§λ§μ μ± μμ§λ©°, λͺ¨λ 곡ν΅λ λ©μλ ꡬ쑰λ₯Ό λ°λ¦ λλ€.
κ·Έλ€μ, μ λ΅ κ°μ²΄λ₯Ό μ ννκ³ μ€ννλ ν©ν 리 ν΄λμ€λ₯Ό ꡬμ±νμ¬, μμ λ‘κ·ΈμΈ μμ²μ΄ λ€μ΄μ¬ λ μ΄λ€ νλ«νΌμΈμ§μ λ°λΌ μ μ ν μ λ΅μ μ°Ύμ μ€ννλλ‘ νμ΅λλ€. μ¦, μΈμ¦ νλ¦μ μ§μ μ μμλ βμ΄λ€ μ λ΅μ μ¬μ©ν μ§β κ²°μ λ§ νκ³ , μ€μ μΈμ¦ λ‘μ§μ μ λ΅ ν΄λμ€μ μν μ μμνλ κ΅¬μ‘°λ‘ λ°λ κ²μ λλ€.
μ΄λ¬ν ꡬ쑰 λλΆμ, λλ©μΈ μλΉμ€ κ³μΈ΅(AuthService)μμλ μΉ΄μΉ΄μ€λ λ€μ΄λ²λ ꡬκΈμ΄λ μκ΄μμ΄, λ¨μν getAccessToken, getUserInfo κ°μ κ³΅ν΅ λ©μλλ₯Ό νΈμΆνκΈ°λ§ νλ©΄ λ©λλ€.
νλ«νΌμ μΈλΆ ꡬνμ λͺ°λΌλ λμΌν λ°©μμΌλ‘ λ‘μ§μ μ²λ¦¬ν μ μκ² λμκ³ , λ‘μ§μ μΆμν μμ€μ΄ λμμ Έ κ°λ
μ±κ³Ό μ μ§λ³΄μμ±μ΄ λν ν₯μλμμ΅λλ€.
μ λ΅ ν¨ν΄μ λμ ν λ€λ‘ λ€μκ³Ό κ°μ μ₯μ μ΄ μμμ΅λλ€
- μΈμ¦ λ‘μ§μ΄ κ° μ λ΅ ν΄λμ€μ λͺ ννκ² λΆλ¦¬λμ΄ μμ΄, μ½λλ₯Ό μ΄ν΄νκ³ μ μ§λ³΄μνκΈ° ν¨μ¬ μ¬μμ‘μ΅λλ€.
- μλ‘μ΄ μμ λ‘κ·ΈμΈ νλ«νΌμ μΆκ°ν λλ, κΈ°μ‘΄ λ‘μ§μ μμ νμ§ μκ³ μ λ΅ ν΄λμ€λ₯Ό μλ‘ μΆκ°νκ³ λ±λ‘λ§ νλ©΄ λλ―λ‘ νμ₯μ±μ΄ λ°μ΄λ¬μ΅λλ€.
- μΈμ¦ νλ¦μ΄ νμ€νλλ©΄μ ν μ€νΈ μμ±μ΄ μ¬μμ§κ³ , νλ«νΌλ³ λ¬Έμ λ₯Ό μ λ΅ λ¨μλ‘ λ 립μ μΌλ‘ λλ²κΉ ν μ μμμ΅λλ€.
- κ²°κ³Όμ μΌλ‘ OCP(κ°λ°©-νμ μμΉ) μ μΆ©μ€ν μ§ν€λ κ΅¬μ‘°κ° λμ΄, μ΄νμλ μμ μ μΌλ‘ κΈ°λ₯μ νμ₯ν΄ λκ° μ μλ κΈ°λ°μ λ§λ ¨ν μ μμμ΅λλ€.
μν©
- μ¬μ©μκ° μνλ μ€νΈλ¦¬λ¨Έλ₯Ό ꡬλ
νλ©΄, ν΄λΉ μ€νΈλ¦¬λ¨Έκ° μ€μκ° λ°©μ‘μ μμν λ μλμΌλ‘ λ
Ήνλ₯Ό μννλ μμ€ν
- ꡬλ β μ€μκ° μ€νΈλ¦¬λ¨Έκ° λΌμ΄λΈ μ€μΈμ§ μ£ΌκΈ°μ μΌλ‘ νμΈ β λ Ήν μ§ν
λ¬Έμ
- λ¨μΌ μλ² κ΅¬μ‘°μμλ λ€μκ³Ό κ°μ λ¬Έμ κ° λ°μκ°λ₯
- νμ₯μ± λΆμ‘±: μ€νΈλ¦¬λ¨Έκ° λ§μμ§μλ‘ κ° μ€νΈλ¦¬λ° νλ«νΌμ λν΄ μ£ΌκΈ°μ μΈ Live μν 체ν¬, λ Ήν μ²λ¦¬, νμ²λ¦¬ λ±μ΄ ν μλ²μ μ§μ€λμ΄ λ³λͺ©μ΄ λ°μ
- λΆμμ ν νλ‘μΈμ€ κ΄λ¦¬: λ Ήν μ€μΈ μ€νΈλ¦¬λ°μ μ€λ¨μ΄λ μ€λ₯ λ°μ μ μλ λ³΅κ΅¬κ° μ΄λ €μ
ν΄κ²°
- μμ€ν
μ μλμ κ°μ΄ μν λΆλ¦¬ λ° λΆμ° μ²λ¦¬ κ΅¬μ‘°λ‘ μ¬μ€κ³
- Main Server: μ μ ꡬλ κ΄λ¦¬, λ Ήν μμ²/κ²°κ³Ό νμΈ λ° μμ λ€μ΄λ‘λ, μλ¦Ό, λ§μ΄ νμ΄μ§
- Monitoring Server: κ° νλ«νΌμ μ€νΈλ¦¬λ¨Έ Live μνλ₯Ό μ€μκ° κ°μ§, κ°μ§ μ μ컀μκ² λ Ήν μμ² μ μ‘
- Recording Worker: κ° μ컀λ λ 립μ μΌλ‘ Streamlink κΈ°λ° λ Ήν μν, λ³λ ¬ λ Ήν κ°λ₯, λ Ήν κ²°κ³Όλ₯Ό S3μ μ λ‘λνκ³ DB κΈ°λ‘
νκ³
- μ΄ κ΅¬μ‘° λλΆμ μ€νΈλ¦¬λ¨Έ μκ° λμ΄λλ μμ μ μΌλ‘ λ Ήνκ° κ°λ₯ν΄μ§
- λ¨μΌ μλ² κ΅¬μ‘°μλ€λ©΄ λΆκ°λ₯νλ νμ₯μ±κ³Ό μμ μ±μ ν보ν μ μμκ³ , μ€μ μ΄μ μ€μΈ μμ€ν μμλ μ₯μ 격리, λ³λ ¬μ±, μ₯μ 볡ꡬμ μ΄μ μ΄ λͺ νν΄μ§
μν©
- λͺ¨λν°λ§ μλ²λ λΌμ΄λΈ λ°©μ‘μ κ°μ§νκ³ , μ컀λ λ Ήν νλ‘μΈμ€λ₯Ό μ€ννλ©°, μ΄ λμ TCP μ°κ²°μ ν΅ν΄ λ°μ΄ν°λ₯Ό μ§μ ν΅μ νκ³ ννΈλΉνΈ μ§ν
λ¬Έμ
- μ΄κΈ°μλ TCP κΈ°λ°μ μ§μ μ°κ²°λ‘ μ컀μ λͺ¨λν°λ§ μλ² κ°μ μν νμΈ λ° Job μ λ¬μ μννμ§λ§, μλΉμ€κ° νμ₯λλ©΄μ λ€μκ³Ό κ°μ λ¬Έμ κ° λ°μ
- μ°κ²° κ΄λ¦¬ λΆλ΄ μ¦κ°: μ컀 μκ° λ§μμ§μλ‘, TCP μ°κ²° μκ° κΈ°νκΈμμ μΌλ‘ λμ΄λ μ°κ²° μν μ μ§(keep-alive)μ μ¬μ°κ²°μ λν λΆλ΄μ΄ 컀μ§
- μν κ΄λ¦¬ μ± μμ λΆλͺ νμ±: μμ»€κ° μμλ‘ scale-out/in λλ©΄μ λκ° μ΄λ€ μ컀μ μνλ₯Ό μΆμ νκ³ μ₯μ λ₯Ό κ°μ§ν μ§ μ± μ λΆλ¦¬κ° λͺ¨νΈν΄μ§
- μ μ§λ³΄μ λ° μ₯μ λμ μ΄λ €μ: TCP κΈ°λ°μ ping-pong ꡬ쑰λ μ¬μ°κ²° μ μν 볡ꡬλ job 볡μ λ°©μ§κ° μ΄λ ΅κ³ , λͺ¨λν°λ§ μλ²κ° λ¨μΌ μ₯μ μ (SPOF)μ΄ λ μ μμ
ν΄κ²°
- TCP κΈ°λ° μν κ΄λ¦¬λ₯Ό Redis κΈ°λ° λ©μμ§/μν μμ€ν
μΌλ‘ μμ ν μ΄κ΄νκ³ , λͺ¨λ Job μ λ¬, ννΈλΉνΈ, μν μΆμ μ Redis ν€ μ€μ¬μΌλ‘ μ€κ³
| ν€ μ΄λ¦ | νμ | μν | TTL |
|---|---|---|---|
job:waiting:queue |
List | λͺ¨λν°λ§ μλ²κ° μ컀μκ² μ λ¬ν μμ λκΈ° ν | μμ |
job:fail:queue |
List | μ€ν¨ν μμ μ¬μλ ν | μμ |
recording:worker:<WORKER_ID> |
Set | ν΄λΉ μμ»€κ° μ²λ¦¬ μ€μΈ μΈμ ID 리μ€νΈ | μμ |
job:meta |
Hash | μΈμ ID β μμ μ 보 | μμ |
job:done:queue |
List | μλ£λ μμ ν | μμ |
heartbeat:worker:<WORKER_ID> |
String (TTL) | μ컀 μμ‘΄ νμΈμ© ν€ | 3μ΄ |
νκ³
- Redis κΈ°λ°μΌλ‘ μ νν μ΄ν μμ€ν μ νμ₯μ±, μμ μ±, 볡ꡬ κ°λ₯μ± μΈ‘λ©΄μμ ν¬κ² ν₯μ
- TCP μ°κ²° κΈ°λ° λ°©μμ μκ·λͺ¨ μμ€ν μλ μ ν©νμ§λ§, μν νμ₯μ±κ³Ό μ₯μ 볡μλ ₯μ΄ μꡬλλ νκ²½μμλ ꡬ쑰μ νκ³κ° λλ¬λ¨
- Redis ν€ μ€κ³λ₯Ό μΈλΆννκ³ μν μ λͺ νν λλλ©΄μ, μ₯μ λ°μ μμλ λͺ νν κΈ°μ€μ λ°λΌ μ컀 μνλ₯Ό νλ¨νκ³ μ¬μ²λ¦¬ν μ μκ² λμμ
μν©
- μ컀λ Streamlinkλ₯Ό ν΅ν΄
.tsν¬λ§·μΌλ‘ μμμ μ μ₯νλ©°, λ°©μ‘μ΄ μ’ λ£λ λκΉμ§ λ Ήνλ₯Ό μ§μνλλ‘ μ€κ³λμ΄ μμ
λ¬Έμ
- μ₯μκ° λ°©μ‘ λ
Ήν μκ° μ ν μμ
- λΌμ΄λΈκ° μ μκ° μ΄μ μ§μλλ©΄ μμ»€κ° κ³μ λ Ήννμ¬ μμ μ μ κ° κΈΈμ΄μ§κ³ , κ³Όλν νμΌ ν¬κΈ°κ° λ°μ
- μ€νΈλ¦¬λ¨Έκ° μ€μλ‘ λ°©μ‘μ λμ§ μμΌλ©΄ μμΌκ° λ Ήνκ° μ΄μ΄μ§ μ μλ ꡬ쑰
- 1μκ°λΉ μ½ 1GBμ λ¬νλ
.tsνμΌμ S3 μ μ₯ λΉμ© λ° λ€νΈμν¬ λμνμ λΆλ΄μ μ€
ν΄κ²°
- λ
Ήν νμμμ μ ν λμ
- λ Ήν λ‘μ§μ 6μκ° μ ν λ‘μ§μ μΆκ°ν΄, μ₯μκ° λ°©μ‘ λ Ήνλ₯Ό μλμΌλ‘ μ’ λ£νλλ‘ κ°μ
- .mp4 λ³ν λ° μ©λ μμΆ μΆκ°
- λ
Ήν μλ£ ν
ffmpegλ₯Ό νμ©ν΄.tsβ.mp4μ¬μΈμ½λ© κ³Όμ μΆκ° - μ΅λ μ©λ 50% μ κ°
- λ
Ήν μλ£ ν
νκ³
- λ°μ΄ν° μ μ‘ λ° μ μ₯ λΉμ©μ μ€μ΄κΈ° μν΄ mp4 μμΆ κ³Όμ μ λμ
ν κ²μ μ€μ§μ μΈ λΉμ© μ κ°
- λ€λ§, CPU μμμ λ§μ΄ μλͺ¨νλ μΈμ½λ© μμ μ μμ»€κ° μ§μ μνν κ²½μ°, λ Ήν μ±λ₯ μ νλ μ§μ°μ΄ λ°μν μ μμ΄ λ³λ μλ²λ‘ λΆλ¦¬νλ ꡬ쑰μ νμμ± λλ
- νμμμ κΈ°λ° λ Ήν μ’ λ£λ₯Ό ν΅ν΄ μμ€ν μμ μ±μ λμ΄κ³ , μ₯μ λ μ¬μ©μ μ€μλ‘ μΈν μ₯κΈ° 리μμ€ μ μ λ₯Ό ν¨κ³Όμ μΌλ‘ λ°©μ§
| Name | GitHub | |
|---|---|---|
| λ°κ²½ν | [email protected] | https://github.com/smileboy0014 |
| μ΄μΉλ―Ό | [email protected] | https://github.com/leesm0218 |
| μ΄νμ | [email protected] | https://github.com/soo96 |
λ°κ²½ν
μκ°μκ°μ κΈΈκ² λκ»΄μ‘μ§λ§, μ§λκ³ λ³΄λ ν λ¬μ μ°Έ μ§§μ μκ°μ΄μμ΅λλ€. μΉμ΄νκ² κ³ λ―Όνκ³ ν λ‘ νλ©° κ²°κ³Όλ¬Όμ λ§λ€μ΄κ°λ κ³Όμ μ κ²°μ½ μ½μ§ μμμ§λ§, μΈν μ΄μμ μμνμ΄ μμλ κ°μ§ μκ°μ΄μλ€κ³ μκ°ν©λλ€. νλ‘μ νΈ μμ΄λμ΄ μ μ λΆν° Git μ λ΅, μ»€λ° λ° μ΄μ ν νλ¦Ώ, μ½λ 컨벀μ , κΈ°μ μ€νκΉμ§β 무μ νλ μ΄μ μμ΄ μ ν κ²μ μμμ΅λλ€. μ΄ κ²½νμ λ°νμΌλ‘, μμΌλ‘ μ΄λ€ νκ²½μμ λꡬμ μμ νλλΌλ κ·Έλμ κ³ λ―Όκ³Ό μ νμ κΈ°μ΅νλ©° μ΅μ μ κ²°κ³Όλ₯Ό λΌ μ μμ κ²μ΄λΌ λ―Ώμ΅λλ€.μ’μλ μ : μ€κ³λΆν° λ°°ν¬κΉμ§ μλΉμ€ κ°λ°μ μ 체 μ¬μ΄ν΄μ μ§μ κ²½νν΄λ³Ό μ μμλ μ μ΄ κ°μ₯ μ’μμ΅λλ€.
λ¨μν κΈ°μ μ μ ννλ λ° κ·ΈμΉμ§ μκ³ , ν©λΉν μ΄μ λ₯Ό λ°νμΌλ‘ ν©λ¦¬μ μΈ κ²°μ μ λ΄λ¦¬λ μ¬κ³ λ°©μμ λ°°μΈ μ μμλ κ²λ ν° μνμ΄μμ΅λλ€.
λν, μ½λ 리뷰λ₯Ό ν΅ν΄ μλ‘μ μκ°μ 곡μ νκ³ ν λ‘ νλ κ³Όμ μ ν΅ν΄ ν κ°λ°μ μ§μ ν μλ―Έλ₯Ό 체κ°ν μ μμλ μκ°μ΄μμ΅λλ€.
μμ¬μ λ μ : ν λ¬μ΄λΌλ μ§§μ κΈ°κ° μμ νλ‘μ νΈ κΈ°νλΆν° λ°°ν¬κΉμ§ λͺ¨λ κ³Όμ μ μννλ κ²μ μ½μ§ μμμ΅λλ€.
νΉν μ견 μΆ©λμ΄ μμμ λ, μ‘°κΈ λ μ°μνκ² μ‘°μ¨νκ³ μ€λνλ€λ©΄ λΆνμν μκ° μλͺ¨λ₯Ό μ€μΌ μ μμμ κ²μ΄λΌλ μμ¬μμ΄ λ¨μ΅λλ€.
μμΌλ‘λ μ견 μ°¨μ΄κ° μκΈ°λ©΄ λͺ
νν κ·Όκ±°μ μλ£λ₯Ό ν¨κ» μ€λΉν΄ λννλ λ°©μμ ν΅ν΄ λμ± μμ°μ μΈ λ
Όμλ₯Ό μ΄λμ΄λ³΄κ³ μΆμ΅λλ€.
보μν μ : νΌλλ°± μκ°μ λ°μ μ견λ€μ λ°μν΄, μλ₯Ό λ€μ΄ κ²μ κΈ°λ₯ κ°μ μ΄λ λ Ήν μ€ μ€νΈλ¦¬λ¨Έμ ꡬλ μκ° μ무λ μμ κ²½μ° μλμΌλ‘ λ Ήνλ₯Ό μ’ λ£νλ κΈ°λ₯ λ±μ 보μνλ©΄ μλΉμ€ μμ±λλ₯Ό νμΈ΅ λ λμΌ μ μμ κ²μ΄λΌ μκ°ν©λλ€.
μ΄μΉλ―Ό
μμ΄λμ΄ λ°κ΅΄ κΈ°κ°μ΄ ν¬ν¨λ κ°λ°κΈ°κ°μ μ λ§ μ§§λ€λκ²μ λκΌμ΅λλ€. NodeJsλ‘ κ°λ¨ν νλ‘κ·Έλλ°λ§ νμκΈ°μ λ°±μλμ λ μ΄μ΄λ μν€ν μ³μ λͺ¨λνμ ν΄λ¦° μν€ν μ³μ μ΅μνμ§ μμμ λλμ± μ§§μ μκ°μ΄μλκ² κ°μ΅λλ€. μ΄λ¬ν κ²½νμ΄ μ’ λ λμ μ€λ ₯μ λ°λ°νμ΄ λλλ‘ λμ± λ Έλ ₯νκ² μ΅λλ€.μ’μλμ : νμλΆλ€μ μ½λ λ
Ένμ°μ μκ°μ 리뷰λ₯Ό ν΅ν΄ λ³Ό μ μμμ΅λλ€.
μκ²¬μ΄ μκ°λ¦¬λλΌλ μλ‘ λλ¦μ κ·Όκ±°λ₯Ό μ μνλ©΄μ ν λ‘ νλκ²λ μ’μμ΅λλ€.
μμ¬μ λμ : μμλ³΄λ€ κ°λ° μλκ° λλμ Έμ λ€λ₯Έ νμλΆλ€κ³Ό κ²°κ³Όλ¬Όμ κ°μ λ°©ν₯μ λκ³ μλ‘ μ΄μΌκΈ°λ₯Ό ν΄λ³΄κ³ μΆμλλ° κ·Έλ¬μ§ λͺ»ν΄ μμ¬μ μ΅λλ€.
보μν μ : 미리 κ³νν κ°λ°κ³νκ³Ό μ€κ³λ λ§μ κ°λ°μ΄ μμλλ λ°λΌκ°κΈ°μ κΈκΈνκ³ , μ€λ₯μ λν μ 보λ₯Ό μ°ΎκΈ° νλ€μ΄ μμλ³΄λ€ κΈ°κ°μ΄ λ§μ΄ μμλμμ΅λλ€. μμΌλ‘ μ€κ³ν λ μ°Έκ³ νμ¬ κ³νμ μ립νκ±°λ, μ΄λ¬ν μν©μ λμ²νλ λ Ένμ°κ° μλμ§ μμλ΄μΌ λκ² μ΅λλ€.
μ΄νμ
μ΄λ² νλ‘μ νΈλ₯Ό ν΅ν΄ μ€κ³λΆν° κ°λ°, λ°°ν¬κΉμ§μ μ κ³Όμ μ νμλ€κ³Ό ν¨κ» κ²½νν μ μμμ΅λλ€. κΈ°ν λ¨κ³λΆν° μ΄λ€ κ΅¬μ‘°λ‘ μ ν리μΌμ΄μ μ μ€κ³ν μ§ κ³ λ―Όνκ³ , μ΄λ₯Ό μ€μ μ½λλ‘ κ΅¬ννλ©°, λ§μ§λ§μλ λ°°ν¬κΉμ§ μ± μμ§λ κ³Όμ μ ν λ¨μλ‘ μννλ€λ μ μμ μ€λ¬΄μ κ°κΉμ΄ κ²½νμ μμ μ μμμ΅λλ€.μ’μλ μ : κΈ°λ₯μ νλνλ κ°λ°ν΄λκ°λ κ³Όμ μμ λͺ¨λ μμ¬κ²°μ μ νμλ€κ³Ό ν¨κ» λ
Όμνκ³ ν©μν΄ λκ°λ€λ μ μ΄ μ’μμ΅λλ€.
μ΄λ€ λ°©ν₯μ΄ λ λμ μ νμΌμ§ λμμμ΄ λννλ©° κ²°μ νκ³ , μμμΉ λͺ»ν λ¬Έμ κ° λ°μνμ λλ κ°μ ν΄κ²°μ±
μ μ μνκ³ ν¨κ» κ³ λ―Όνλ©° νμ΄κ°λ νμν¬κ° νλ‘μ νΈμ ν° μλλ ₯μ΄ λμμ΅λλ€.
μμ¬μ λ μ : μ΄κΈ°μ μμ
λ‘κ·ΈμΈ κΈ°λ₯μ μΉ΄μΉ΄μ€, λ€μ΄λ², κ΅¬κΈ μΈ κ°μ§ λͺ¨λ ꡬννλ €λ€ λ³΄λ, μμλ³΄λ€ λ§μ 리μμ€κ° μ΄λ°μ μ§μ€λμμ΅λλ€.
κ° νλ«νΌλ§λ€ μΈμ¦ λ°©μμ΄ λ¬λΌ ꡬν λμ΄λμ ν
μ€νΈ λΆλ΄μ΄ μ»Έκ³ , μ΄λ‘ μΈν΄ ν΅μ¬ κΈ°λ₯ κ°λ°μ΄ μ§μ°λλ κ²°κ³Όλ‘ μ΄μ΄μ‘μ΅λλ€.
λμ΄μΌλ³΄λ©΄ μ²μλΆν° λͺ¨λ νλ«νΌμ ꡬνν기보λ€λ ν κ°μ§(μ: μΉ΄μΉ΄μ€)λ§ μ°μ λμ
νκ³ , μ£Όμ κΈ°λ₯ κ°λ°μ μ§μ€νμΌλ©΄ νλ‘μ νΈμ μ λ°μ μΈ μμ±λμ μΌμ μΈ‘λ©΄μμ λ λμ κ²°κ³Όλ₯Ό μ»μ μ μμμ κ²μ΄λΌ μμ¬μμ΄ λ¨μ΅λλ€.
보μν μ : μ΄λ² κ²½νμ ν΅ν΄ κΈ°λ₯λ³ μ€μλμ λμ΄λ, μ¬μ©μ μν₯λλ₯Ό κ³ λ €ν μμ μ°μ μμ μ€μ μ νμμ±μ λκΌμ΅λλ€. μμΌλ‘λ μ΄κΈ° μ€κ³ λ¨κ³μμ μ 체 λ‘λλ§΅μ μ μ°νκ² μ€κ³νκ³ , κΌ νμν κΈ°λ₯λΆν° μ°μ ꡬννμ¬ μ μ§μ μΌλ‘ νμ₯ν΄λκ°λ μ λ΅μ μ μ©νλ € ν©λλ€. μ΄λ₯Ό ν΅ν΄ νμ λ μκ°κ³Ό μμμ λ³΄λ€ ν¨μ¨μ μΌλ‘ μ¬μ©ν μ μλλ‘ κ°μ ν΄λκ° κ³νμ λλ€.





