다양한 활동/SKT 데보션 영

[활동/데보션 영] 도커(docker) 테크 세미나 후기🐳 : DEVOCEAN YOUNG 3기

토끼개발자 조르디 2024. 10. 30. 22:42

도커(docker), 그것이 알고싶다!

지난 9월 26일, 37차 테크 세미나가 열렸습니다!

주제는 바로바로 ~ 'Docker를 활용한 효율적 개발 및 보안전략' 이었습니다.

 

저는 사실 도커와 깊은 인연(?), 악연(?)을 가지고 있는데요 ㅋㅋㅋㅋ

대학교에서 처음으로 진행한 개발 프로젝트에서 도커를 사용하게 되었는데 그냥 망했었습니다. ^^

별이세개인 회사의 어떠한 모델을 사용하고 있을 적,,, 노트북에서 프로그램이 잘 돌아가지도 않았고 그때 당시 개발이 처음이라 오류만 잔뜩 얻어간 기억이 있습니다. 

 

그리고 2022년에 하게 된 스타트업 인턴에서 도커를 활용하는 업무가 있어서 다시 만나게 되었고 그때 트라우마를 좀 극복할 수 있었습니다. ㅋㅋ 물론 그때도 다양하고 많은 오류를 경험했습니다 🥹

 

*아래 링크 참고*

 

 

[Docker error] installation failed : 다른 프로세스에서 사용 중이므로 프로세스에서 액세스할 수 없습니

docker 를 처음이자 마지막으로 사용한 2021년... 오류 컬렉터인 나는 당연하게도 오류로 악명 높은 docker를 사용하면서 정말 다양한 아이들을 만났다. 오류를 만나면 우선 긴장했던 주니어도 아닌 B

bunnydev-jordy.tistory.com

 

인턴이 이후로는 도커와는 별 인연이 없는듯 했지만, 세상이 도커-쿠버네티스를 원하니 자연스럽게 제 삶에도 침투.

데보션영 프로젝트에서 도커 파일을 활용하게 되었습니다. 🐳

 

그리고 캡스톤에 이어서 계속 디벨롭 하고 있는 메이저인 프로젝트에 MSA 구조를 적용하고 싶다는 생각이 들면서 다시 찾게 된 도커!!

 

그러던 와중에 럭키하게도🍀 데보션에서 도커 세미나를 열어주신다길래 바로 신청했습니다 🔥

 

사실 평일 저녁 세미나라 인턴 끝나고 퇴근하는 시간과 겹쳐서 😂 들을 수 있을까? 생각했지만,,,,

뭐 솔직히 마음만 먹으면 어떻게든 들을 수는 있다고 생각해서 알람 설정도 완료 했습니다. ㅋㅋㅋㅋㅋㅋ

(아직 남아있는 알람 내역 ㅋㅋ)

 

기본어플 중에 제일 활용도가 높음

 

그리고 무사히(?) 퇴근길에 테크 세미나를 듣게 되었습니다.

버스줄 서고 있을 때 시작해서 처음엔 휴대폰으로 듣다가 몇 분 후에 버스에 타서 들을 수 있었습니다👍

 

낑긴채로듣기

 

 

그렇다면 저의 세미나 신청 배경 및 과정은 여기까지 쓰도록 하겠구요,,

이 아래에서 세미나에 어떤 유익한 내용이 있었는지 정리해보도록 하겠습니다🔥

 


Docker를 활용한 효율적 개발 및 보안전략

발표자분 간략 소개

성함 : 염근철(님)

) 당근 SRE 소속 : ‘컨트롤이라는 배포플랫폼 만들고 쿠버네티스 관리

) Docker Captain 🔥

 

발표 목표

흔히 사용되는 Docker의 핵심 기능을 보다 효율적으로 사용하는 방법을 소개

개발자들이 속도와 보안을 개선할 수 있는 구체적인 기법들을 배워볼 수 있는 기회를 제공

또한, Docker Scout Build Cloud 와 같은 최신 기능들을 탐구해보는 시간을 가지려고 한다.

 

Inner Loop 개발자 워크플로우

개발자를 위한 환경을 제공하고자 하는 도커!

 


 

이미지 빌드(image building)

도커 파일

어떤 베이스 이미지를 기반으로 해서, 어떤 디렉토리에서 어떤 파일을 카피를 하고 어떤 명령어를 실행하는지 등 차근차근 정리를 해서 순서대로 실행 후, 이미지를 만드는 것을 도와주는 파일

 

👉 도커에서 독자적으로 만들었으며 계속 개선되고 있는 피쳐

$ docker build -t node-docker
$ docker run -d -p 8080:8000 node-docker

 


Best Practices

#1. Prefer Leaner Docker Images

베이스 이미지를 사용할 때의 이야기

같은 이미지여도 이미지를 여러가지 타입을 쓸 수가 있다!

그래서 여러가지 버전을 제공을 해주는데, 이때 보통 슬림이나 알파인, 이런 단어들이 들어가 있는 이미지들을 같이 배포를 해준다.

 

이때  가능한 슬림이미지나 알파인 성격의 이미지를 쓰는 것을 권장

 

왜?  이미지 크기 차이가 많이 난다!

 

1) 보안 : 이미지 용량이 작아지면 안에 취약점이 될 수 있는 여러가지 패키지들도 같이 빠지기 때문에 보안적인 측면에서도 안전하다

 

2) 용량 : 이미지 용량이 커진다 👉 디스크를 포함해서 실행될 때 여러 가지 자원들을 훨씬 적게 소모한다

베이스 이미지가 작아지면 프로덕션에 ready 되어서 올라가는 시스템 상에서도 이미지 용량에 따라서 한 서버 안에 적재할 수 있는 시스템 양이 굉장히 크게 달라진다. 컨테이너는 한 서버안에 여러 이미지가 적재되는 시스템 이라서 이런 이미지용량이 굉장히 중요하다.

 

3) 시간 : 용량이 작아지면, 이미지 빌드하는 시간이 줄어든다. 

 

#2. Use explicit Base Image reference instead latest

Latest 이미지 안 쓰는 것을 강력하게 권장드린다.

 

왜?   Latest 이미지는 항상 오버라이드되는 이미지이다. 그래서 새로운 버전이 나오면 의도치 않게 기존에 쓰던 배포 환경에서 latest 이미지가 새로 받아지면서 모든 이미지 시스템이 깨지는 경우가 많다.

 

따라서   특정 버전을 명시해서 쓰는 것을 권장드린다.

 

#3. Use Multi-Stage Build  

Multi-Stage Build 를 하는 것을 권장드린다.

 

** 보통 FROM 구문으로 나눠지는데

** FROM 부터 CMD(커맨드) 구문까지가 하나의 스테이지

 

여러 스테이지를 활용해서 빌드를 하는 방식이 이미지 용량 측면에서 유리한 이유

최종 만들어지는 이미지는 가장 마지막에 반영되는 스테이지에서 반영되는 파일들만 최종 이미지에 같이 들어간다.

 

EX : 빌드를 하기 위한 스테이지를 별도로 두고 최종 프로덕션에 반영 하기 위한 스테이지를 따로 두게 되면 빌드 스테이지에서는 ( 예를 들어 어떤 프로젝트를 개발한다고 했을 때) 개발을 위한 패키지를 설치한 다음에 서비스를 빌드하는 과정을 거친다. 근데 실제로 프로덕션에 반영하는 서비스에서는 빌드 되어서 나온 결과의 에셋파일을 (최종 빌드된 결과물만) nginx 컨테이너라던지 다른 경량 웹서버를 동작시키기 위한 형식의 시스템에 옮기게 된다.

 

잔여패키지의 용량이 크다. 이 잔여패키지는 스테이지를 나눠서 그 이전 스테이지에서 다음 스테이지로 간다고하면 그 작은 용량의 에셋 파일들만 가지고 갈 수가 있다.   따라서 멀티 스테이지를 활용해서 빌드를 하게 되면 최종 이미지 용량을 또 한번 줄일수가 있다.

 

#4. Add HEALTHCHECK  

HEALTHCHECK 라는 커맨드

컨테이너가 실행이 되었을 때 이 컨테이너의 정상 동작 여부를 판가름 해줄 수 있는 커맨드

 

- 실제 리눅스 커맨드 같은 것들을 활용해 어느 경로에 요청을 보내고 이게 잘 안되면 컨테이너를 실패시킨다던지,,, 이런 역할을 한다.

 

이미지에 헬스 체크 옵션을 포함해서 빌드를 하고 나서 실행을 하고       Docker ps      명령어로 확인을 해보면   헬스 체크 관련 문구가 따로 보여진다. 이걸 활용하면 도커 컴포즈 같은 기능에서도 좋게 활용을 해볼 수도 있고 단일 stand alone으로 실행을 할때도 유용하게 활용할 수가 있다.

 

실제로 쿠버네티스 환경에 이미지가 최종으로 올라갈 때 참고하는데 많은 도움을 준다.

 

실제로 프로덕션에서 이런 Liveness, Readiness 작성을 또 추가로 해줘야 하는데, 그때 어떤 기준으로 이걸 작성을 해줘야하는지 좋은 참고자료나 근거가 된다. 따라서 기록으로 남겨놓는것도 큰 의미가 있다.

 

#5. Use .dockerignore

Dockerignore 파일도 잘 활용하시는 것을 추천한다.

 

도커 빌드를 할 때, Dockerignore 에 명시되어 있는 폴더나 파일은 검사하지 않는다.

Copy 명령어를 쓸 때, Dockerignore 에 무시하고 싶은 내용을 작성하면 도커파일을 보다 간결하고 범용성있게 작성할 수 있다.

 

보안적측면, 이미지 용량적 측면에서 위험해질 수 있기 때문에 Dockerignore 를 활용해서 잘 차단을 해주자.

 

#6. Using     --mount=type=??

<< NEW >>  새로운 피쳐 이다.

 

특정 커맨드를 실행하는 RUN 이라는 커맨드에 같이 결합해서 사용할 수 있는 실행 옵션

(다양한 타입을 지원하는 피쳐)

 

타입 종류

Cache : 빌드 속도를 빠르게 만들 수 있다

 

Binding : 현재 내가 지금 개발하고 있는 (로컬) 디렉토리랑 연결하는 옵션

 

시크릿 : 비밀 정보를 관리할때 쓸 수 있는, 빌드할때 arg 를 사용하는게 아니라 시크릿을 넘겨주어 실행

👉 나중에 이미지를 만들고 나서 이미지를 열어봤을때 arg env 로 받아서 실행하는 것들은 시크릿 정보가 이미지 안에 다 남아있다

👉 시크릿 옵션을 사용하면 보안적인 측면에서 전혀 검사가 안된다. 정보가 남지 않는다.

 

옵션의 역할

RUN 커맨드를 실행하게 되면 기본적으로 특정 리눅스 커맨드를 컨테이너 내부에서 빌드하는 과정에서 실행하게 된다.

 

예를 들어 ls 명령어를 쓰던 아니면 빌드 명령어를 쓰든   리눅스 명령어가 RUN 커맨드 뒤에서 실행이 되는데,
--mount=type=??   을 같이 붙여서 쓰게 되면 그 옵션의 성격에 맞는 볼륨이나 디렉토리 같은 것들을 커맨드를 실행할 때를 한정으로 마운트를 시켜준다.

 

<예시>

App 이라는 디렉토리를 모니터링

 

 

👉  이거 설명해주실때 라이브로 새로운 예시를 알려주시느라 중간에 작은 문제(?) 들이 있었는데, 당황은 조금 하셨지만 그것마저도 즐기시는 것 같아서 🤭 그만큼 강사님의 도커에 대한 사랑과 열정(? 을 느낄 수 있었다.

 


 

Speed for developers

Inner-Loop Developer Workflow

속도에 집중해서 이야기하는 파트

 

이너루프 란?

개발자들이 코드작성을 하고 로컬에서 테스트하고 피드백 받아서 다시 코드 개선하고 하는 그런 과정, vscode 에서 작업하는 그런 사이클 👉  이너루프 워크플로우

 

그런 작업을 효율적으로 관리하는 방법에 대한 이야기

** 로컬에서는 컨테이너를 쓰지 않고 개발하면 CI 에서 실패할 수 있는 확률이 많아진다.

 

도커는 애저를 싫어하나요? ㅋㅋㅋㅋㅋ 라고 질문나온 그 ppt

 


[생산성] 1. $ docker init

도커 관련 초기 에셋들 초기 이니셜라이징해주는 명령어

 

<예시 – flask>

Docker file 에서 디테일을 잡아주는 부분.

 

1) 파이썬 버전 명시, 파이썬 버전에 따라 유지보수할 수 있게 변수로 잡아준것

, slim 버전으로 받아줌

 

2) pythondontwritebytecode

활성화 안해주면 .pyc 라는 바이너리 파일들이 생긴다. 이 코드를 널어줘서 바이너리 파일 생성을 막는다. 

 

3) pythonunbuffers

실시간으로 로그를 내려주도록 한다. 

 

4) ARG, RUN 부분

보안 관련해서 루트유저 안쓰고 쉘 권한 없는 유저 넣어주는 역할

 

5) 마운트 타입 캐시 ------ 아까 얘기하신 부분!

패키지 설치할때마다 .cache/pip 디렉토리를 마운트를 해서 패키지 설치할때 엄청 빨리 반복할 수 있게 해주는

동시에 바인드 옵션을 통해 로컬 디렉토리랑 연결을 시켜줘서 requirements.txt 파일 을 컨테이너 내부랑 외부를 연결시켜 준다. 실시간으로 개발할때 유용하다.

 

 

Docker 리드미 file 에서 디테일을 잡아주는 부분 -  더 간결(?)해짐

docker ignore 에서 디테일을 잡아주는 부분.

compose 파일 에서 디테일을 잡아주는 부분.

 

DB 관련 주석으로 다 달아주고, 확장할 것 까지 고려해서 작성

 


 

[생산성] 2. compose watch

** 도커 컴포즈 기능을 적극적으로 활용한 기능 / 로컬환경을 위해서 추가된 옵션

 

특정 파일들을 모니터링을 해서 컴포즈로 올려놓은 시스템이 어느 특정 파일을 기준으로 변경이 감지가 되면 이 도커 컴포즈 서비스에 동작 하고 있는 컨테이너를 재시작 하거나 어떤 파일을 컨테이너 내부로 동기화 해주거나 ,,, 이런것들을 지원해주는 옵션

 

도커 컴포즈 활용해서 로컬에서 컨테이너를 올리게 되면 컴포즈 실행동작 확인하는 것밖에 안 됨. 그런데 watch 라는 옵션을 같이 쓰게 되면 원하는 개발 소스가 변경이 되었을 때 저장하면 실시간으로 파일을 감지를 해서 컨테이너를 재시작하거나 파일을 옮겨주는 목적으로 활용 가능

 

파일 모니터링 할 때 결과 액션 관련 옵션

1) Sync

파일이 바뀐걸 감지하면 그 파일을 컨테이너 내부로 옮겨주는 옵션

 

2) Rebuild

파일이 바뀐게 감지가 되면 컨테이너를 다시 빌드해서 시작을 시키는 옵션

 

3) sync + restart

파일을 그냥 옮기기만 하는게 아니라 파일을 옮긴 다음에 컨테이너를 재시작 시켜주는 옵션

 

 

개발하면서 실시간으로 파일 저장만 하면 개발 환경이 계속 알아서 뜬다

 

경우1)

Requirements -> 수정 반영됨

리빌드 하고 있다고 뜸, 서버 재시작

 

경우2)

App.py -> 수정했는데 반영 안됨

/ ? -> 싱크 옵션을 썼는데 실행할 때 디버그 옵션 같은걸 추가하고 한게 아니라 그냥 파이썬 app.py 이렇게 시작을 해서, 재시작을 안해주면 파일이 실시간으로 감지가 안된다. 서버 입장에서는 반영이 안된것.

그래서   sync + restart.   로 수정해야 한다.

 

 


 

[생산성] 3. compose profile

실행할 때, 개발 환경 프로덕션 환경을 컴포즈 파일한테 가정을 해서 특정 프로필을 지정을 해주면, 그 컴포즈 서비스만 뜨게끔 규약을 해주는 기능. 앞에서 소개한 compose watch 와 함께 쓰면 잘 쓸 수 있다.

 

sync + restart.

 

개발환경에서는 컨테이너가 자동으로 파일이 변경되면 서버가 리로드 될 수 있는 그런 디버그 옵션 같은 것을 활성화해서 실행을 할 수 있게 환경변수를 따로 넣어준다던지 등의 선택이 가능해진다.

 

 

 

프로필 지정을 통해, 원하는 프로필 서비스에 해당하는 것만 실행을 할지 선택이 가능! 

 


 

[생산성] 4. docker build cloud 🔥🔥🔥

<< NEW >>  새로운 피쳐 이다.

 

빌드를 로컬 pc 나 특정 어떤 환경에서 하는게 아니라 도커가 제공해주는 빌드 클라우드 라는 환경에서 실행을 할 수 있게 도와주는 피쳐

 

엄청나게강조하셨던기능

 

장점 >> 캐시 공유 / 빌드 속도에서의 베네핏

도커 캐시 같은 파일은 로컬에서 빌드하면 로컬에만 남아있는다.

특히 리모트 CI 환경에서 빌드를 하게 되면 (환경마다 다르겠지만) (예를 들어 : 젠킨스 같은 환경을 서버에이전트를 해서 쓰게 되면) 환경들이 계속 초기화가 된다던지 아니면 깃허브 액션만 하더라도 빌드할 때마다 CI 환경이 초기화가 되어서 캐시가 유지가 안된다.

 

그런데 빌드 클라우드 기능을 활용하면 로컬에서 빌드, CI 환경에서 빌드 상관없이 빌더를 클라우드 타입으로 설정을 해서 빌드 명령어를 실행을 해주면 무조건 빌드 클라우드 환경에 가서 빌드가 실행이 된다.

👉 로컬 혹은 CI 환경에서 빌드 명령어를 썼을 때 빌드가 되는 장소가 한군데가 되는 것이고 캐시가 공유가 된다는 의미이다.

👉 빌드 속도의 측면에서 CI 환경이 베네핏을 가져갈 수 있는 기능.

 

++ 추가로 이것도 ARM 아키텍처에서 이미지가 다르게 빌드가 되는데, 그런거를 고민하지 않아도 되는것.

빌드 클라우드에서 빌드가 되니까 !!

 

엄청나게 강조하시는 전문가님

 

단점 >> 비쌈 !! 그것도 매우 !! 💰

괴연 이것을 내가 써볼 일이 있을까...?

 

과금이슈

 

그렇네요 ㅠㅠ

 

 

빌드 클라우드 동작 실습

** TIP

일반 유저도 한달에 200분까지는무료.. / 단, 무료 계정은 빌더를 하나까지 쓸 수 있다..

 

실습화면1

 

빌더를 사용하는 두가지 타입

1) 현재 내 로컬 디렉터리 기준으로 내 폴더에 있는 내용들을 활용해서 빌드하는 방법 👉 일반적인 빌드 방법

2) 깃 저장소 이름을 줘서 빌드하는 방법 👉 클론 받아서 빌드

 

도커가 컨셉이 좀 바뀌면서 빌더 라는 개념이 생겼다.

사용할 빌더를 지정을 해서 사용하도록 하는 방식인데, 예를 들면,,,

 

ARM 빌더,,, 리눅스 AMD 빌더,,, 등 세팅해서 선택할 수 있게, 디폴트로 사용할 빌더가 뭘지 선택할 수 있게 한다.

 

실습화면2

 

실습화면3

 

실습화면4

 

 

** 참고 링크 : 도커 빌드 클라우드 사이트

 

https://www.docker.com/products/build-cloud/

 

Build Docker Images Faster | Docker Build Cloud

Docker Build Cloud helps developers build Docker images faster using the cloud while preserving existing workflows and freeing up local resources.

www.docker.com

 


 

[보안] 5docker scout 

위험성 & 필요성

SSH 관련된 ** XZ attack 이후로 supply chain (공급망) 보안 관련된 중요성이 굉장히 부각되고 있다. 소프트웨어를 개발할 때 굉장히 다양한 부분으로 구성이 되는데, 다양한 의존성들이 있고 또 오픈소스 컴포넌트들이 다수 포함되어있다. 모든 오픈소스들은 잠재적으로 취약점을 가진다. 특히 어떠한 조직 내부에서 개발한 오픈소스도 있지만, 오픈소스 특성상, 다수의 익명의 사용자들이 개발에 참여하게 되고 여러가지 악의적인 코드들이 유입될 수 있는 가능성이 있다. 그리고 이걸 사람이 일일이 잡아내는게 무리가 있다.

 

Docker Scout  자체가 취약점 스캐닝도구가 아니다 👾

여러가지 취약점 스캐닝 도구들 힘을 빌려서 정보를 잘 취합해서 보여주는 헬퍼도구이다.

이미지 내에 있는 여러가지 패키지들을 리스팅을 해서 다른 써드파티 어플리케이션에 요청을 보낸다. 👉 정보를 취합해서 보여주는 것.

 

Docker Scout SBOMs : 패키지들을 리스팅할 수 있음.

 

https://docs.docker.com/scout/how-tos/view-create-sboms/

 

Docker Scout SBOMs

Use Docker Scout to extract the SBOM for your project.

docs.docker.com

 

실제 사용 화면 - 도커데스크탑

이미지를 선택하면, 취약점을 바로 보여준다. 

 

 

++ Scout CI 환경에서 통합해서 쓰는 예시

 

깃허브 액션탭 빌드 summary 에서 볼 수 있게 해준다.

 

이거슨무료

 

 

** 위 자료의 깃허브 페이지

 

https://github.com/ajeetraina/scout-demo-service/tree/main

 

GitHub - ajeetraina/scout-demo-service

Contribute to ajeetraina/scout-demo-service development by creating an account on GitHub.

github.com

 

 

 

** XZ attack 관련 기사

https://m.boannews.com/html/detail.html?idx=128372

 

XZ Utils 백도어 악성코드, 2021년부터 공들여 준비해온 공급망 공격이었다

리눅스와 GNU 운영체제에서 제공되는 범용 데이터 압축 형식 프로그램 XZ Utils에서 백도어 취약점이 발견돼 이용자들의 각별한 주의가 요구된다. 특히 XZ Utils는 리눅스 OS 운영체제에서 기본적으

m.boannews.com

 

https://yozm.wishket.com/magazine/detail/2597/

 

‘XZ Utils 백도어 사태’로 살펴보는 공급망 보안 | 요즘IT

지난 3월 29일, 마이크로소프트의 소프트웨어 엔지니어 ‘Andres Freund’는 무손실 데이터 압축 유틸리티 XZ Utils(이전에는 LZMA Utils) 5.6.0과 5.6.1버전에 SSH 백도어가 존재한다고 밝혔다. XZ Utils 백도어

yozm.wishket.com

 

 

https://www.sonatype.com/blog/cve-2024-3094-the-targeted-backdoor-supply-chain-attack-against-xz-and-liblzma

 

CVE-2024-3094 The targeted backdoor supply chain attack against XZ and liblzma

Learn about a new, targeted backdoor supply chain attack against the popular XZ compression utility seen in many Linux distributions such as fedora and debian. Understand its impact, potential risks and what you can do about it.

www.sonatype.com

 


 

[확장성] 6. Docker Extensions  

도커 데스크탑에도 익스텐션 기능이 있다.

 

전문가님께서 사용하고 있는 익스텐션 예시

 

- Disk usage

- Logs explorer

- Resource usage  

 


 

Docker 커뮤니티 소개

다양한 커뮤니티의 장이 있는 도커...

 

 

** 도커 커뮤니티 포럼 링크

 

https://forums.docker.com/

 

Docker Community Forums

Docker Community Forums

forums.docker.com

 


 

아주 짧은 후기 🍀

워낙 도커와 악연이어서 ㅋㅋㅋ 재밌게 들을 수 있을까... 걱정했는데

일단 너무 설명을 잘해주시고 라이브의 묘미인,,, 준비되지 않은 실습까지 보여주셔서 너무 즐거웠다.

 

정말 다양한 도커의 숨겨진(?) 기능을 알게 되어서 나름 뿌듯했고 (나중에 다 사용해볼 수 있을지는...미지수...)

외부 프로젝트에 도커를 도입하려고 하는데, 이번에 배운 내용을 가지고 적용해보고 싶다는 생각도 들었다.

 

마지막에 Q&A 시간도 있었는데, 질문 하나하나에 정말 정성껏 대답해주셔서 ,,,

무언가 하나를 정말 좋아하고 재밌어하게 되면 이런 시간도 즐길 수 있게 되는구나,,, 라고 느껴졌다.

 

과연 나도 나중에 누군가에게 도움이 되는 그런 사람이 될 수 있을지... ㅎ-ㅎ

여러모로 큰 깨달음을 받은 세미나였다. 

 

모두 도커 하세용~ 특히 빌드 클라우드 사용해보기~ 🐳

 

열심히 해보자고 내 전공이니까

 


참고 링크

유튜브 풀버전이 궁금하신 분들은 아래의 링크를 접속해서 들어주세요~🐳

유익한 내용이 정말 많이 있습니다 ㅎㅎ

 

https://www.youtube.com/live/Er2FNbMZhuA?si=sj7R1NztSDnTNRaX