첫 회사에서는 Node.js를 기반으로 자바스크립트 언어를 사용해 웹 서버를 구성하고 MongoDB, RabbitMQ, Nginx를 사용하여 IOT 관제 및 제어 웹 사이트를 솔루션 프로그램으로 개발하게 되었습니다. 개발 이후에는 윈도우, 리눅스(우분투) 서버에 직접 배포해야 했고, 배포를 하러 다녔었습니다(현재도 다니는 중). 그래서 IT 인프라에 대한 기본적인 지식이 있으면 좋겠다는 생각을 하였고 '그림으로 공부하는 개정판 IT인프로 구조'라는 책을 스터디하게 되었습니다. 이 책을 읽고 모든 내용을 정리하지는 않았으나 최소한 응용 소프트웨어 개발자로서 알아두면 좋을 정보들을 정리한 글입니다.
아키텍처 구조
아키텍처 구조란?
쉽게 말해서 데이터를 처리하는 구조이다.(서버의 분산 등..)
궁극의 아키텍처 구조를 사용할 수는 없을까?
각 아키텍처마다 장단점이 있으며 궁극의 아키텍처라는 것이 있다면 좋겠지만 각 아키텍처 그리고 설계 요소에는 반드시 장점과 단점이 존재한다.
집약형 아키텍처
대형 컴퓨터를 이용하여 모든 업무를 처리하는 형태이다.
장점
- 한 대의 대형 컴퓨터만 있으면 되므로 구성이 간단하다.
- 대형 컴퓨터의 리소스 관리나 이중화에 의해 안정성이 높고 고성능이다
단점
- 대형 컴퓨터의 도입 비용과 유지 비용이 비싸다
- 확장성에 한계가 있다
분할형 아키텍처
여러 대의 컴퓨터를 조합해서 하나의 시스템을 구축하는 구조다.(서로가 연결되어 데이터를 교환한다)
장점
- 낮은 비용으로 시스템을 구축할 수 있다.
- 서버 대수를 늘릴 수 있어서 확장성이 높다
단점
- 대수가 늘어나면 관리 구조가 복잡해진다.
- 한 대가 망가지면 영향 범위를 최소화하기 위한 구조를 검토해야 한다.
물리 서버와 논리 서버의 차이
분할형 아키텍처에서 이용되는 컴퓨터를 '서버'라고 한다. 서버라는 용어는 컴퓨터 자체를 가리키는 경우도 있고, 컴퓨터에서 동작하고 있는 소프트웨어를 가리키는 경우도 있다. 서버라는 용어는 원래 '특정 역할에 특화된 것'을 의미한다. 레스토랑의 웨이터를 서버라고 부르는 경우도 있다고 한다.(주문 접수나 음식을 내오는 것에 특화되어있고 요리는 하지 않기 때문이다)
클라이언트-서버형 아키텍처
업무 애플리케이션, 미들웨어, 데이터베이스 등의 소프트웨어를 '물리 서버' 상에서 운영하고 있다. 클라이언트-서버형의 특징은 클라이언트 측에 전용 소프트웨어를 설치해야 한다는 것이다. 예를 들어 주식 판매 시스템은 그래프 표시나 주가 흐름 분석은 PC에서 하고, 필요에 따라 서버에서 주가 데이터를 취득하는 방식이 많다고 한다. 이 방식에서 서버 측은 데이터 입출력만 하면 되기에 처리당 부하가 낮아서 많은 pc 가 동시에 요청을 보내도 문제가 없다.
하지만 버그가 있을 수도 있고 개선사항이 있을 때마다 정기적으로 업데이트가 필요하다는 단점이 있다. 흔히 우리가 사용하는 애플리케이션들이 그러하다. 업데이트 내용을 적용시켜야 할 때는 플레이스토어로 강제 이동시켜 업데이트를 해야 들어갈 수 있는 경우가 있을 것이다.
장점
- 클라이언트 측에서 많은 처리를 실행할 수 있어서 소수의 서버로 다수의 클라이언트를 처리할 수 있다.
단점
- 클라이언트 측의 소프트웨어 정기 업데이트가 필요하다.
- 서버 확장성에 한계가 발생할 수 있다.(클라이언트 PC의 한계)
3계 층형 아키텍처
프레젠테이션 계층, 애플리케이션 계층, 데이터 계층의 3층 구조로 분할되어 있는 것이 3계 층형 아키텍처이다. 내가 잘 아는 MVC 패턴과도 같은 구조인 것 같다.
프레젠테이션 계층
- 사용자의 입력을 받는다.
- 웹 브라우저 화면을 표시한다
애플리케이션 계층
- 사용자 요청(Request)에 따라 업무 처리를 한다.
데이터 계층
- 애플리케이션 계층의 요청에 따라 데이터를 입출력을 한다.
장점
- 서버 부하 집중 개선
- 클라이언트 단말의 정기 업데이트가 불필요
- '처리 반환'에 의한 서버 부하 저감
단점
- 구조가 클라이언트-서버 구성보다 복잡하다
수평 분할형 아키텍처
'수평 분할형 아키텍처'란 용도가 같은 서버를 늘려나가는 방식이다. 참고로 수직 분할형과 수평 분할형은 배타적인 관계가 아니며, 대부분의 시스템이 이 두 가지 방식을 함께 채택하고 있다. 예를 들자면 프레젠테이션 계층, 애플리케이션 계층, 데이터 계층 수직분할형 아키텍처와 같은 형태이나 서울, 부산, 대전 등 각 지역별로 서버를 나누는 것이다. 다른 지역의 정보를 알고 싶다면 그 지역의 시스템에 접속하여 확인하면 된다.
- 서울 -> 프레젠테이션 계층 -> 애플리케이션 계층 -> 데이터 계층(서울의 정보뿐이다)
- 부산-> 프레젠테이션 계층 -> 애플리케이션 계층 -> 데이터 계층(부산의 정보뿐이다)
장점
- 수평으로 서버를 늘리기 때문에 확장성이 향상된다.
- 분할한 시스템이 독립적으로 운영되므로 서로 영향을 주지 않는다.(서울 쪽의 서버가 다운되더라도 부산의 서버는 멀쩡히 돌아갈 수 있다)
단점
- 데이터를 일원화해서 볼 수 없다.
- 애플리케이션 업데이트는 양쪽을 동시에 해 주어야 한다
- 처리량이 균등하게 분할돼 있지 않으면 서버별 처리량에 치우침이 생긴다.(사용하는 클라이언트의 수는 다른데 둘 다 서버 크기가 같아 많이 이용하는 쪽은 서버에 부하가 걸리고 조금 이용하는 곳은 서버가 놀게 되는 것이다)
공유형 아키텍처
일반 기업 시스템이라면 아주 사이가 나쁘지 않은 한 서울과 부산에서 다른 애플리케이션을 이용하는 경우는 드물다. 공유형에서는 단순 분할형과 달리 일부 계층에서 상호접속이 이루어진다.(데이터 계층에서 서울과 부산의 데이터를 동기 처리)
장점
- 수평으로 서버를 늘리기 때문에 확장성이 향상된다
- 분할한 시스템이 서로 다른 시스템의 데이터를 참조할 수 있다
단점
- 분할한 시스템 간 독립성이 낮아진다.
- 공유한 계층의 확장성이 낮아진다.
직렬/병렬
직렬/병렬이란?
간단한 예시로 3차선 도로와 1차선 도로를 생각할 수 있다. 1차선 도로는 직렬, 2차선 이상의 도로는 병렬이라고 볼 수 있는데, 이때에 1차선 도로의 요금소를 통과한다면 차가 밀릴 때는 줄줄이 대기하는 현상이 벌어질 것이다. 이때 도로를 3차선으로 나누고 요금소를 3개를 배치해준다면 1차선으로 요금소에 일을 처리하는 것보다 훨씬 수월해질 것이다.
병목현상이란?
3차선 도로에서 요금소 3개를 배치하여 수월하게 일을 처리하던 도중 도로가 1개로 합쳐지는 합류점이 있고, 합류점의 1차선 구간은 사고가 발생하기 쉽다. 3차선의 차들이 모두 1개의 차선으로 들어가야 하기 때문이다. 1차선 구간은 전체 흐름을 느리게 만드는 원인으로 '병목지점(Bottleneck)'이 된다.
그렇다면 전부다 병렬 처리하면 되는 게 아닐까?
처리 특성에 따라서 병렬화할 수 있는 것과 없는 것이 있다. 따라서 직렬 처리가 분기해서 병렬로 되거나, 다시 합류에서 직렬로 되기도 한다. 이 합류점, 직렬화 위치, 분기점이 병목 현상이나 문제가 발생하기 쉬운 지점이 된다. 병렬 처리를 할 때에는 가능 한 병렬화해서 직렬 부분을 줄이고, 어쩔 수 없이 직렬 화해야 하는 경우네는 효율성을 높이는 것이 중요하다. 또한 병렬화에서는 분담해서 일을 진행한 것을 한 곳에 모으는 데 오버헤드가 걸린다고 한다. 그렇기에 무리해서 병렬화하면 직렬 처리에 의해 속도가 느려지는 경우가 있다. 잘 파악해서 어떤 부분을 병렬화할지 파악하는 것이 중요하다.
병목 현상은 어떻게 해결할까?
1. 병목 현상이 발생하고 있는 위치를 정확히 파악한다. 이를 위해서는 각 서버의 처리량이나 응답 상황 로그를 취득해서 어느 서버가 병목지점이 되고 있는지를 파악해야 한다. (3 계층의 그림을 그려가며 파악하는 것이 다른 사람과의 정보 공유도 되고 쉽고 빠르게 파악할 수 있다.)
2. 병목 위치를 파악했다면 튜닝을 하는 것이다. 병목 위치를 더 작은 단위로 '세분화'해서 병목 영역을 더 '집중적으로' 파헤치는 접근법이 유효하다.
3. 또 다른 방법으로는 시스템의 이용자 수를 제한하는 것이다. 그렇게 해도 될까?라고 생각할 수 도 있지만, 이것은 유량 제어라는 이름이 붙어 있을 정도로 매우 직관적인 방법이라고 한다.
유량제어란?
적절한 계층에서 이용자 수를 제한하는 접근법이다. 예를 들어, 일반적인 웹 시스템 등에서도 '해당 사이트는 트랙픽 초과로 차단되었습니다' 또는 티켓팅 시 대기인원 500명 남았습니다. 등 서버에 부하가 걸리지 않게 웹 서버 계층에서 유량 제어를 하는 것이다.
다만 메시지가 아닌 실제 에러 코드가 표기되는 경우가 있는데, 이것은 유량 제어가 실패해서 AP 서버나 DB 서버 계층의 어딘가에서 리소스가 최대치를 넘었기 때문에 에러라는 형태로 제어 결과를 표시하는 것이다.
4. 유량 제어를 했음에도 에러를 뱉어줄 경우 '수평분할(Sharding)'을 통해서 서버를 증설함으로써 시스템 전체 허용량을 늘리는 접근법을 병용할 필요가 있다.
병목 현상의 숙명의 적, 데이터베이스
사용자 측에서 유량 제어를 하지 않고 웹 서버 및 AP 서버를 늘리면 최종적으로는 DB 서버가 병목 지점이 되는 경우가 대부분이다. '파라미터만 바꾸면 빨라지는 거 아니야?'라고 말할 수 있지만 그런 마법과 같은 파라미터는 존재하지 않고, 이미 설계 시점에 설정이 끝난 상태이다. 그래서 튜닝 시점에는 애플리케이션 개발자의 협조가 반드시 필요하다고 한다. 개발은 협업이다 소통하며 개발하자.
폴링이란?
폴링(Polling)은 정기적으로 질의하는 것을 가리킨다. 정기적으로 질의함으로써 상대가 어떤 상태인지, 어떤 요구를 가지고 있는지 등을 알 수 있다. 웹 앱 개발자가 가장 이해하기 쉬운 예로는 배치시스템이다. 스케쥴링에 따라 정기적으로 데이터를 조회하여 일을 처리한다. 예를 들어 정기적으로 이메일 발송을 하는 것도 이러할 것이다. 비밀번호를 3개월마다 변경해야 하고 그것을 알려줄 메일을 발송해야 한다. 이럴 때에 배치 시스템을 사용하여 3개월마다 주기적으로 비밀번호 변경한 지 3개월이 지난 유저들을 체크하여 발송해주는 것이다.
폴링의 특징
- 질의 방향이 단방향이다.
- 질의는 일정 간격을 따라 정기적으로 발생한다.
폴링의 주요 장점
- 반복(루프)만 하면 되기에 프로그래밍이 쉽다.
- 상대가 응답하는지 확인할 수 있다.
- 모아서 일괄적으로 처리할 수 있다.
계층구조
컴퓨터 세계에서는 많은 부분에서 계층 구조를 적용하고 있다. 이것 또한 모델, 뷰, 컨트롤러는 생각하면 쉬울 것이다. 뷰에서는 특정 url로 요청을 보낸다. 이후에 컨트롤러에서 받은 것을 서비스 계층으로 전달한다. 서비스 계층은 데이터 계층과 연결되어 있으며 자신의 역할에 따라 비즈니스 로직을 처리한다.
계층구조는 왜 사용할까?
계층 구조에서는 데이터나 기능 호출 흐름에 따라 계층 간 역할이 나누어진다는 특징이 있다. 역할이 나누어져 있기 때문에 각 층은 자신이 담당하는 일만 책임을 지며, 다른 일은 다른 계층이 책임을 진다. 상호 연결돼 있는 계층들에서는 교환 방법, 즉 인터페이스만 정해 두면 된다. 이 또한 모델, 뷰, 컨트롤러로 생각하면 쉬울 것이다.
프로토콜
네트워크에 대해 언급할 때 빠트릴 수 없는 것이 프로토콜이다. 프로토콜은 영어로는 사전에 정해 놓은 순서를 의미한다. 컴퓨터가 서로 소통하기 위해 정한 규약을 가리킨다. 미국인과 한국인이 있고 이 둘은 서로의 언어밖에 모르는 상황이다 이때에 둘이 대화를 한다면 소통이 되지 않고 이것은 프로그램도 마찬가지이다.
컴퓨터의 거의 모든 곳에 프로토콜이 사용된다. 떨어진 곳에 있는 두 개의 장비는 사전에 절차를 정해 두지 않으면 서로 통신할 수 없다. 그래서 네트워크와 프로토콜은 떼려야 땔 수 없는 관계다. 우리가 흔히 사용하는 마우스 usb 또한 프로토콜이 존재한다.
인터넷 프로토콜 스택의 4 계층
- 애플리케이션 계층 - HTTP, FTP
- 전송 계층 - TCP, UDP
- 인터넷 계층 - IP
- 네트워크 인터페이스 계층
IP 인터넷 프로토콜
- 지정한 IP 주소에 데이터를 전달.
- 패킷(패키지로 이해하면 된다)이라는 통신 단위로 데이터를 전달.(IP 패킷: 내 IP, 상대방의 IP를 담아준다)
인터넷 망에서는 서버들이 다 이 규약을 따르고 있기 때문에 출발지와 도착지를 알아서 던져준다.
상대방에서 메시지를 잘 받은 후 받았다는 응답을 다시 보내주면 상대방이 잘 받은 것을 알 수 있다.
문제점
비연결성
- 패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷 전송 (상대의 서버가 꺼져있어도 확인하지 않고 보낸다)
비신뢰성
- 중간에 패킷이 사라질 수 있다.(중간중간 많은 노드(서버)들을 경유하여 상대 서버에 도착하는데 중간서버에 문제가 발생하여 패킷이 소실되어도 알 수 없다)
- 패킷이 순서대로 도착하지 않을 수 있는 문제가 있다.(패킷의 용량이 클 때가 있고 작을 때가 있는데 패킷의 용량이 약 1500 바이트가 넘어간다면 그것을 적당한 크기로 분할하여 보낸다. 그러나 이것이 노드를 타고 상대 서버로 보내질 때에 다른 노드를 타고 갈 수 있는데 순서가 다르게 도착할 수 있는 문제가 있다. 메인 메뉴와 디저트를 함께 보냈는데 사이즈가 너무 커서 분할되었고 디저트가 먼저 도착하고 이후에 메인 메뉴가 도착하는 문제가 발생할 수 있다는 것이다.)
프로그램 구분
- 같은 ip를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이라면?
TCP/IP 프로토콜 (전송 제어 프로토콜)
IP 프로토콜에는 전송 순서, 상대방이 잘 받았는지에 대한 검증에 대한 문제 등... 이 있었다. 그러나 TCP에서는 이것들을 해결해 준다. TCP 세그먼트라는 것에 출발지 PORT와, 목적지 PORT, 전송 제어, 순서, 검증 정보 등을 담아서 보내준다.
TCP의 특징
- 연결 지향 - TCP 3 way handshake(가상 연결)
- 데이터 전달 보증
- 순서 보장
3 way handhaske 란?
- 클라이언트 측에서 SYN이라는 메시지를 보낸다.
- 상대측에서 잘 받았다고 ACK라는 메시지와 함께 연결해줘 라는 SYN을 다시 보내고
- 클라이언트에서 상대측이 보낸 메시지를 잘 받았다고 ACK와 함께 데이터를 상대측에 다시 보내준다.
- 상대측에서는 데이터를 잘 받았다는 메시지를 전송해준다.
데이터 전달 보증
IP 로만 데이터를 보낸다면 같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이라면 문제가 될 것이다. 그렇기에 PORT 번호를 담아 보내서 구분하도록 한다.
순서 보장
패킷의 용량이 커서 분할하여 보낼 때 문제점은 서로 다른 노드로 이동하게 된다면 어떠한 순서로 도착할지 모른다는 것이었다. 그러나 패킷마다 순서(시퀀스 번호)를 달아주어 순서대로 받을 수 있게 보장해주는 것이다. 패킷 1, 패킷 2, 패킷 3 이 있고 1보다 2가 먼저 들어온다면 받은 상대측에서는 1을 다시 보내줘라고 메시지를 보내는 방식으로 순서를 보장한다.
흐름 제어와 폭주 제어
데이터 보증을 시퀀스 번호와 ACK를 통해 처리하면 정말 장점이 많으나 이렇게 된다면 데이터를 보내고 ACK를 받기를 계속 기다리는 작업을 반복 처리하다 보면 시간이 많이 걸린다.
동기로 통신을 하면 효율이 나쁘기 때문에 ACK를 기다리지 않고 전송하는 것이 좋은데 TCP는 어느 정도의 세그먼트 수라면 ACK를 기다리지 않고 전송하는 윈도우 개념을 가지고 있으며, ACK를 기다리지 않고 전송 가능한 데이터 크기를 윈도우 크기라고 한다.
폭주 제어는 무엇일까?
송신 측 윈도우를 폭주 제어라고 부른다. 이 송신 측 윈도우 크기는 네트워크 폭주 상태(혼잡 상태)에 맞추어 변경시키기 대문이다. 네트워크가 혼잡하면 폭주 윈도우 크기를 작게 해서 전송 데이터 양을 줄인다. 이것이 폭주 제어다. TCP는 주변에 영향을 주지 않도록 자중하는 프로토콜이다. 만약 전송 프로토콜을 만든다면 무조건 성능이 좋고 빠르다고 좋은 것은 아니다. 주변 네트워크에 민폐를 끼치지 않고 잘 전달해 줄 수 있어야 한다.
네트워크 계층의 프로토콜 IP
IP의 역할은 간단히 말하자면, '지정한 대상 서버까지 전달받은 데이터를 전해 주는 것'이라 할 수 있다. 간단하지만 TCP/IP 중에서도 가장 중요한 기능이다. 단 IP에서는 반드시 전달을 보장하지 않는 점 그리고 IP 담당하는 기능은 중요하지만 그리 많지 않다.
IP의 중요한 기능
- IP주소를 이용해서 최종 목적지에 데이터 전송
- 라우팅
라우팅이란?
송신 및 수신 시에 서버 내에서만 처리되는 TCP와 달리 IP는 경로 도중에 다양한 처리가 이루어진다. 라우팅도 그중 하나다. 더욱 쉽게 이해한다면 데이터를 전송할 때에 여러 노드(서버)를 거쳐서 전송한다고 하였는데 그 과정을 라우팅이라 하는 것이다.
데이터 전송 시 어떻게 최종 목적지의 IP주소가 있는 서버를 아는가?
외부와 접속하는 네트워크는 보통 기본 게이트웨이(Default Gateway)라는 라우터가 설치돼 있다. 라우터와 서버는 자신이 알고 있는 목적지 정보를 라우팅 테이블(경로표)이라 하는 형태로 목록화하여 가지고 있다. 출발 서버에서 어느 곳으로 도착할지 모르기에 기본 게이트웨이로 보내주고 외부 네트워크와 접속된 게이트웨이는 라우팅 테이블에 따라 아는 범위 내에서 데이터를 전송해준다.
패킷의 좀비화
IP 헤더는 TTL(Time To Live)이라는 생존 시간 정보를 가지고 있다. 예를 들어 TTL = 64부터 시작한다고 할 때 라우터를 하나씩 경유할 때마다 라우터가 IP 헤더의 TTL을 1 씩 줄여서 전송해준다. 경유할 때마다 64,63,62,61.... 0 이 되는데 0이 되는 시점에는 라우터가 패킷을 파기한다. 정상적으로 전송된 경우에는 64개나 라우터를 경유할 이유가 없기 때문이다. 만약 정해진 TTL 값이 없다면 패킷이 좀비가 되어 배회하고 다닐 것이다.
패킷 하나의 데이터는 총 1500 바이트를 전송할 수 있는데 TCP 헤더가 20바이트, IP 헤더가 20바이트를 사용하기 때문에 (TCP20 + IP20 = 40) 정확히 데이터는 총 1460 바이트를 전송할 수 있다.
고갈되는 IP주소(Ipv4, Ipv6)
IP 주소가 고갈된다는 이야기를 들어본 적은 없지만 어디선가 들린다고 한다. 2010년 이후부터 그 심각성이 부각되면서 다양한 대책이 논의됐다.
현재 사용되고 있는 IP는 Ipv4인데, 주소를 32비트로 표현하고 있다. 이 경우 약 43억 개의 IP 주소를 만들 수 있지만, 인터넷의 폭발적인 보급과 함께 43억 개의 주소가 거의 고갈돼 가고 있다. 이것을 보완하기 위한 간단한 방법은 IP 주소를 늘리는 것이다. IP 주소를 32비트에서 128비트로 늘리는 방법으로 문제를 해결하였다.
IPV6의 문제점
Ipv6는 Ipv4와 호환성을 가지고 있지 않다. Ipv4를 전제로 한 네트워크 장비나 애플리케이션은 Ipv6를 사용할 수 없다. 또한, 상호 통신을 하기 위해서는 기본적으로 웹 서비스 제공 측과 이용 측 쌍방이 Ipv6에 대응하는 네트워크 장비와 애플리케이션을 사용해야 한다. 그러나 2000년 전후로 사양 및 구현 방법이 소개된 Ipv6는 조금씩 Ipv6 대응 환경으로 바뀌어서 이제는 Ipv6를 사용할 준비가 거의 끝났다고 할 수 있다.
참고로 , Ipv4와 Ipv6가 호환성이 없다고 말했는데, TCP 및 그 윗단계의 HTTP는 양쪽 버전을 모두 지원하기 때문에 사용자는 Ipv4로 통신을 하고 있는지 Ipv6로 통신을 하고 있는지 의식할 필요가 없다.
참조 및 책 후기
이 글은 '그림으로 공부하는 개정판 IT 인프라 구조' 를 읽고 응용 소프트웨어 개발자로서 알아두면 좋다고 생각되는 정보들을 정리한 글입니다.
이 책을 읽으며 몰랐던 개념들에 대해 많이 알게 되었다. 병목현상, 폴링, IPV4와 IPV6의 차이, TCP/IP 가 어떻게 동작하는지, 직렬/병렬 처리 등... 많은 내용을 더 자세히 알게 되어 좋았다. 이 책에는 이 외에도 더 많은 것을 담고 있고, 책에 나온 모든 내용을 이곳에 정리한 것은 아니다 프로세스, 스레드, 메모리, 캐시 등... 책에는 더 많은 내용들이 담겨있다.
서버직뿐만 아니라 웹 개발에 종사한다면 이 책을 한번 읽어보는 것을 추천한다. 그림으로 많은 내용들이 설명되어있어 글로만 보는 것보다 이해하기 쉽고 다가가기 쉽다고 느꼈다.
스터디
이 책은 회사에서 사내 스터디를 하며 읽은 책이기에 아직은 둘 뿐이지만 정리한 내용을 스터디 멤버들에게 리뷰해주었다.
회사에 갓 입사했을 때에 2달간의 공부 기간을 받았었다. 매주 배운 것을 발표하는 시간을 갖었었는데 실전 프로젝트에 투입되며 발표할 일이 없었는데, 아직은 둘 뿐이지만 사내 스터디로 진행하며 발표하니 목소리가 떨렸다. 실제로는 그림으로 설명하기 위해 칠판에 그려가며 설명했는데 사진은 한컷 뽑으려고 어정쩡한 자세와 함께 프로젝트 빔과 함께 찍었다ㅎㅎ.
'Read Book > 짧은 내용의 책' 카테고리의 다른 글
읽기 좋은 코드가 좋은 코드다 (0) | 2022.06.27 |
---|