[우아한테크코스 8기] 프리코스 오픈미션 회고

2025. 12. 2. 16:36·우아한테크코스 8기

[오픈 미션에 들어가며]

프리코스를 진행하면서 정해진 시간 내에 Java로 코드를 짜고 문제를 해결하는 과정을 통해 객체 지향적 설계, 리팩터링, 코드리뷰를 통한 학습 등 많이 배웠습니다. 이번에 처음 도입한 오픈 미션은 내가 주도적으로 미션을 설계하고 계획에 맞게 기능을 구현하는 미션이였습니다. 이전 기수와 달리 진짜 내가 해보고 싶은 것을 도전할 수 있다는 점이 너무 설레고 두근거렸습니다. 평소 경험을 떠올리며 내가 할 줄 아는 것이 아닌 해보고 싶은 것이 어떤 게 있는 지 떠올리며 고민했습니다.

저는 평소 다양한 서비스 기업의 테크 블로그를 읽고, 최신 기술을 실제 서비스 기업에서 어떻게 도입할 수 있을지 고민해보는 과정을 좋아합니다. 이번에는 ‘최신 기술을 어떤 상황에서 어떻게 도입해볼까?’로 생각을 마무리짓지 말고, 그 기술의 아키텍쳐에 대해 공부하고 내가 직접 해볼 수 있는 범위에서 만들어보고 싶다는 생각을 했습니다. 그러던 중 최근에 재밌게 읽었던 올리브영의 기술 블로그 글이 떠올랐습니다.

올리브영은 올영세일을 진행하는 기간동안 00시마다 쿠폰을 선착순으로 발급해줍니다. 몇 일전 쿠폰을 받으려고 올리브영 앱에 들어갔는데 트래픽이 몰려서 n번째라고 표시되고, 순서대로 번호가 줄어들면서 발급을 받을 수 있었습니다. 어떻게 동시에 몰리는 트래픽을 효과적으로 처리하는 지 궁금해서 올리브영의 기술 블로그를 찾아보게 되었습니다. 이 부분을 메세지 큐를 통해 해결했다는 글을 읽으며 메세지 큐에 대해 처음 접하게 되었고 이를 직접 제작해보면서 공부하면 재밌겠다는 생각을 했습니다.
https://oliveyoung.tech/2023-08-07/async-process-of-coupon-issuance-using-redis/
https://oliveyoung.tech/2023-09-18/oliveyoung-coupon-rabbit/

 

쿠폰 발급 RabbitMQ도입기 | 올리브영 테크블로그

쿠폰 발급 프로세스에서 MQ도입과정을 설명합니다.

oliveyoung.tech

 

 

Redis Pub/Sub을 활용한 쿠폰 발급 비동기 처리 | 올리브영 테크블로그

올리브영에서 쿠폰 발급 프로세스를 어떻게 개선 했는지 알아봅시다.

oliveyoung.tech

이번에 오픈 미션의 예시로 제시된 낯선 도구 해커톤과 고난도 해커톤을 참고하며 저만의 주제를 정했습니다. 주제는 ‘소켓 프로그래밍으로 메세지 큐 구현하기’입니다.



[프로젝트 기획하기]

왜 소켓으로 구현하려고 하는가?

일반적으로 RabbitMQ, Kafka, ActiveMQ 같은 메시지 큐는 애플리케이션 계층에서 사용하도록 설계된 고수준 메시징 시스템입니다. 그러나 이를 소켓 기반으로 직접 구현해보면 메시지 큐가 내부적으로 동작하는 구조를 더 깊이 이해할 수 있습니다. 소켓은 전송 계층에 더 가까운 수준에서 동작하기 때문에, 데이터 송수신 방식, 패킷 구조, 버퍼링, 재전송 정책 등 메시지 흐름을 세밀하게 제어할 수 있다는 장점이 있습니다.

따라서 상용 메시지 큐에 의존하지 않고 소켓으로 직접 메시징 시스템을 구현하면, MQ의 개념 이해와 네트워크 레벨의 메시지 처리 경험을 모두 얻을 수 있는 학습적 가치가 있다는 점에서 시도해 보고자 했습니다.

왜 C++을 선택했는가?

C++을 선택한 이유는 단순히 고성능·저지연 같은 기술적 이유만은 아닙니다. 물론 C++은 성능 면에서 강점이 있고 시스템 레벨에서 세밀한 제어가 가능하기 때문에 네트워크 프로그래밍에 적합한 언어입니다. 하지만 그보다도 개인적인 이유가 더 컸습니다.


저는 지난 학기 객체지향 프로그래밍 과목을 망쳤습니다. 그 과목에서는 C++로 수업,실습,과제를 모두 진행했습니다. 당시 외부 프로젝트에 몰두하면서 수업과 과제에 충분히 집중하지 못했습니다. 결국 C+라는 좋지 않은 성적으로 과목을 마무리하게 되었고, 그 이후로 C++뿐만 아니라 프로그래밍 전반에 대한 두려움까지 생겼습니다.

C++ 성적표..


이번에 우테코를 통해 Java를 배우며 프로그래밍 자체에 대한 두려움은 극복할 수 있었지만, C++에 대한 미묘한 부담감과 공포는 여전히 남아 있었습니다. 그래서 이번 오픈 미션을 통해 그 감정을 정면으로 마주하고 극복해 보고 싶었습니다.

C++로 소켓 기반 메시징 시스템을 직접 만들어보면, 성능적으로 의미 있는 결과를 얻는 것은 물론이고 과거에 느꼈던 두려움을 스스로 넘어서는 경험을 만들 수 있을 것이라고 생각했습니다.

[사전학습을 하며 익숙하지 않은 기술 도전하기]

2주라는 시간동안 제가 익숙하지 않은 것들을 배워서 고난이도의 문제를 해결하고자 했습니다. 그래서 무엇보다도 어떤 부분을 공부해야 하는지 정확히 아는 것이 중요하다고 생각했습니다. 발췌독이라는 독서기법이 있는 것처럼 내가 필요한 것을 정확히 파악해서 공부하는 것이 짧은 시간에 목표를 이루는데 좋은 방법이라고 생각했기 때문입니다.

주제를 구현하기 위해서는 두 가지 기술에 대한 이해가 필요했습니다. 사전 학습을 꼼꼼히 진행한 뒤, 기능 구현에 들어가는 것이 중요하다고 생각하여 4~5일 정도를 집중적으로 학습했습니다.

 

C++ 소켓 프로그래밍

https://github.com/kcnsmoothie/socket-chat

 

GitHub - kcnsmoothie/socket-chat

Contribute to kcnsmoothie/socket-chat development by creating an account on GitHub.

github.com

 

익숙한 IDE가 VSCode와 IntelliJ뿐이어서 자연스럽게 VSCode에서 C++ 프로그래밍을 진행했습니다. 이전에 C 프로그래밍을 할 때 작성해둔 컴파일 설정 파일이 있어 초반에는 수월하게 진행했습니다. 하지만 Winsock2를 불러오는 과정에서 컴파일 설정을 새로 해주어야 했습니다. 라이브러리가 추가될 때마다 설정 파일을 직접 관리해야 하는 과정이 불편하고 시간이 많이 소요될 수 있다는 것을 느꼈습니다. 이를 계기로 실제 프로젝트에서는 Visual Studio 2022로 IDE를 변경하기로 했습니다. 사전 학습을 꼼꼼히 진행하다 보니 IDE 선택과 같이 사소한 부분이 프로그래밍의 편의성에 큰 역할을 한다는 것을 몸소 깨달을 수 있었습니다. 언어에 맞는 IDE를 선택하니 프로그래밍 과정에서 의존성이나 추가적인 설정에 소모되는 시간을 줄여줘서 편리했습니다.

 

메세지 큐

다양한 상용 메세지 큐를 공부하고 그 중 C++ 소켓 프로그래밍으로 구현하기에 적합한 것을 모델삼아 개발하고자 했습니다. 상용 메세지 큐에는 대표적으로 RabbitMQ, ActiveMQ, Kafka가 있었습니다.

각각의 특징을 생각하며 프로젝트 적합성을 글로 정리하며 모델을 선택했습니다.

  • RabbitMQ : AMQP에 기반하여 설계하였기 때문에 소켓수준에서 MQ를 설계할 때 이를 기반으로 설계하기 수월할 것 같다.
  • ActiveMQ : JMS에 특화되어있어서 C++을 사용하는 나의 프로젝트에는 적합성이 떨어진다.
  • Kafka : 고성능 이벤트 스트리밍 메시지 브로커라서 시작하는 수준에서 모델로 잡기에는 오버 엔지니어링이다.

따라서 RabbitMQ를 기반으로 구현하기로 결정했습니다. 실제로 RabbitMQ 기능을 학습하고 사용해보며, 메시지 큐가 동작하는 방식과 구조를 몸으로 익혔습니다.

[기능 구현 하기]

RabbitMQ는 다양한 Exchange 타입을 제공하지만 처음부터 모든 기능을 구현하기에는 현실적으로 무리가 있었습니다. 우테코 프리코스를 진행하면서 학습했던 것처럼 최소 기능을 명세하고 나서 추가 기능 구현 사항을 정리하고 추가 구현하는 방향으로 확장해나가기로 했습니다.

RabbitMQ의 AMQP 규격을 기반으로 개발하며 시간적 제약으로 인해 가장 단순한 Direct Exchange를 기준으로 구현할 기능을 정리했습니다.

노션에 정리한 기능 구현 사항 명세

 

뼈대 코드 작성하기

메시지 큐에서 데이터는 크게 서버 → 브로커(Exchange와 Queue) → 클라이언트 순으로 흐릅니다. 이를 송신과 수신 관점에서 바라보면 데이터가 이동하는 과정이 서버에서 브로커로, 브로커에서 클라이언트로 두 번 나뉜다는 것을 알 수 있었습니다. 처음에는 이러한 흐름을 이해하고 구현하는 것이 막연하게 느껴졌지만 각 구간을 독립적인 케이스로 분리하여 생각하자 조금씩 구조가 보이기 시작했습니다.

 

사전 학습 과정에서 작성했던 기본 코드를 변형하여 송수신 과정의 뼈대 구조를 먼저 구현했습니다. 익숙하지 않은 기술을 다루다 보니 처음에는 작은 송수신 기능조차 부담스럽게 느껴졌지만 막상 작게 쪼개어 단계별로 구현하니 전체 흐름을 이해하면서 점진적으로 완성해 나갈 수 있었습니다.

 

이 과정에서 크게 세 가지를 깨달았습니다.

  1. 복잡한 시스템도 작은 단위로 나누면 구현이 가능하다
    처음에는 메시지 큐 전체 구조가 복잡하다고 느껴졌지만, 서버-브로커, 브로커-클라이언트로 나누어 각각의 역할과 책임을 정의하니 구현이 훨씬 명확해졌습니다.

  2. 꼼꼼한 사전 학습의 힘
    사전 학습으로 개념과 예제 코드를 이해하고 뼈대 코드를 준비해두니 실제 구현 단계에서 시행착오를 줄일 수 있었습니다. 익숙하지 않은 기술도 작은 성공 경험을 쌓으며 자신감을 얻는 계기가 되었습니다.

  3. 직접 구현하면서 개념이 몸에 익는다
    단순히 이론으로 메시지 큐 구조를 이해하는 것과, 실제로 서버와 클라이언트 사이에서 데이터가 오가는 흐름을 코딩으로 구현하는 것은 완전히 다른 경험이었습니다. 송수신 과정을 직접 다루면서 브로커의 역할과 메시지 흐름, 오류 처리 등을 체감할 수 있었습니다.

결과적으로, 처음에는 막막하게 느껴졌던 메시지 큐의 데이터 흐름을 작게 나누어 구현하고 반복 학습하면서 익숙하지 않은 기술도 단계적으로 극복할 수 있다는 중요한 경험을 얻었습니다.

Producer는 다양한 데이터를 보내줘야해

Producer를 구현하면서 가장 먼저 부딪힌 문제는 TCP 소켓이 메시지 경계를 보장하지 않는다는 점이었습니다. TCP는 스트림 지향 방식이기 때문에 send()가 한 번 전달한 데이터가 recv()에서 같은 크기나 묶음으로 들어온다는 보장이 없고, 반대로 여러 메시지가 합쳐져 들어올 수도 있습니다. 따라서 단순히 문자열을 직렬화해서 전송하는 방식으로는 메시지를 안정적으로 구분할 수 없었습니다.

 

RabbitMQ같은 경우 바이너리 기반 프로토콜과 메시지 구분 로직을 통해 이 문제를 해결하지만, 이번 프로젝트에서는 로우 레벨이 핵심이 아닌 메시지 큐의 기능 구현이 주 목표입니다. 바이너리 코드 레벨까지 내려가는 것은 후순위라고 판단했습니다. 그래서 소켓 수준에서 직접 프로토콜 구조를 설계했습니다.

메시지 구조는 다음과 같이 설계했습니다.

[헤더 | 바디]
  • 헤더: 바디 길이를 나타내는 4바이트 정수(네트워크 바이트 오더, htonl/ntohl 사용)
  • 바디: 다음 세 가지 필드를 순서대로 담음
    1. Exchange명
    2. Routing Key
    3. Message 본문

각 필드는 길이 + 데이터 형태로 직렬화됩니다. 예를 들어 Exchange명은 [Exchange 길이][Exchange 데이터] 형태로 전송됩니다.

struct StoredMessage {
    std::string exchange;    
    std::string routingKey;  
    std::string message;    
};

 

이 설계를 통해 Producer → Broker(Exchange, Queue) → Consumer로 흐르는 데이터의 구조와 흐름을 명확히 하고, TCP 스트림 특성을 고려한 안정적인 메시지 전송이 가능했습니다.

 

[exchange → queue로 데이터를 저장하기]

단일 exchange라 가정하고 기능 구현에 들어갔습니다.

exchange가 routing key를 확인해서 queue의 자료구조로 데이터를 저장해줘야 합니다.

메세지 저장 기능 구현

 

[프로젝트에서 직면한 어려움과 극복]

레포지토리가 날아가서 커밋메시지들이 모두 사라졌어요

Visual Studio를 이번 프로젝트를 사용하면서 처음 사용하다보니 치명적인 실수를 했습니다.

VSCode는 각각의 파일로 관리했기 때문에 각 .cpp 파일마다 메인 함수를 만들고 서버 - 클라이언트 통신을 실행시킬 수 있었지만, Visual Studio는 프로젝트 단위로 생성을 하기 때문에 한 프로젝트에서 하나의 main함수만 실행시킬 수 있었습니다. 이런 점을 모르고 하나의 프로젝트에서 producer, broker(exchange,queue), consumer를 각각의 서버처럼 생각하고 통신을 시켜줄 수가 없다는 사실을 알았습니다. git에 하나의 프로젝트로 등록해버려서 다 갈아엎어야하는 상황이 발생했습니다.

만약 그때 현명하게 프로젝트를 2개 더 생성하고 각각의 producer, consumer 코드만 옮겼으면 되었는데… 레포를 삭제 해서 작업한 커밋 메세지가 모두 날아가버렸습니다. 거의 모든 기능을 완성한 상태여서 멘탈이 흔들렸지만 정신을 다잡고 내가 할 수 있는 일을 했습니다.

  1. broker 프로젝트를 만들어서 올린다.
  2. consumer와 producer 프로젝트를 만들어서 각각의 레포를 올린다.

세 개의 레포로 분리하고 나니까 접근성이 불편하다는 느낌이 들어서 서브 모듈로 관리해주기로 했습니다. 

 

멀티 스레드 환경으로 전환

메시지 큐의 기능적인 측면에 좀 더 충실하게 구현하기 위해서 브로커에 여러 대의 producer와 consumer가 동시에 접속할 수 있도록 멀티스레드 환경으로 확장했습니다.

 

producer가 queue에 데이터를 삽입하고 있을 때도, consumer는 연결을 유지하면서 queue에 삽입된 데이터를 받아올 수 있어야합니다. producer가 메시지를 보낼 때마다 연결을 생성해야하면 연결에 사용되는 컴퓨팅 리소스가 낭비된다고 생각하여 producer가 연결 종료 요청 전까지 연결 유지하는 형태로 구현하고자 했습니다. 하지만, 여러 개의 연결을 요청해도 잘 처리해낼 수 있어야하는데, t.detach는 백그라운드에서 돌아가도록 해서 다른 producer가 연결을 시도하면 이전에 연결했던 메시지가 재전송되는 문제 발생했습니다.

 

void acceptLoop(SOCKET serverSocket) {
    while (true) {
        sockaddr_in clientAddr{};
        int clientSize = sizeof(clientAddr);

        SOCKET client = accept(serverSocket, (sockaddr*)&clientAddr, &clientSize);
        if (client == INVALID_SOCKET) continue;

        std::thread t(handleProducer, client);
        t.detach();
    }
}

 

detach를 join으로 변경하는 방법으로 해결을 하니 재전송 이슈가 해결되었습니다.

 

브로커가 producer와 consumer를 구분하는 법

초기에는 서버가 클라이언트를 연결 직후 수신되는 첫 4바이트 길이만 보고 Producer와 Consumer를 구분하려고 했습니다. Producer는 메시지를 한 번에 구조체 형태로 전송할 것이라 가정했지만, 실제로는 메시지를 항목 단위로 나누어 보내는 방식이었습니다. 그 결과, 서버는 첫 수신 패킷에서 Exchange 이름만 읽고 전체 메시지로 잘못 해석하게 되었고, 정확한 역할 판별이 어려웠습니다. 즉, 첫 패킷의 길이만으로는 안정적으로 역할을 식별할 수 없다는 문제를 직면했습니다. 이 문제를 해결하기 위해, 다음과 같이 연결 직후 클라이언트가 1바이트 역할 플래그를 전송하도록 설계했습니다.

 

P → Producer

C → Consumer

 

서버는 accept() 후 첫 recv()에서 이 값을 읽고, 바로 Producer 핸들러 또는 Consumer 핸들러로 분기하도록 구현했습니다.

문제 해결을 통해 가정과 현실의 차이를 확인하는 과정의 중요성을 느꼈습니다. “Producer는 한 번에 메시지를 전송할 것”이라는 가정을 기반으로 구조를 설계했지만, 실제 데이터 흐름과 맞지 않아 문제가 발생했습니다. 가정이 실제 상황과 다를 수 있다는 점을 직접 체감하며, 테스트와 검증의 필요성을 깨달았습니다.

이번 미션을 하며 처음으로 Issue를 사용해봤다.

[앞으로의 확장 방향]

다양한 Exchange 타입을 지원하기

현재는 RabbitMQ의 다양한 Exchange 타입 중 Direct Exchange만 구현된 상태입니다. Direct Exchange는 라우팅 키를 기준으로 단일 큐에 메시지를 정확히 전달하는 방식으로, 가장 기본적이고 이해하기 쉬운 구조입니다. 그러나 실제 서비스 환경에서는 메시지 전달 방식이 더 복잡해질 수 있으며, 이를 해결하기 위해 RabbitMQ는 다른 Exchange 타입들을 제공합니다.

앞으로는 다음과 같은 Exchange 타입들을 단계적으로 지원하여 메시징 기능의 유연성을 높이고 싶습니다.

  • Fanout Exchange : 
    주로 브로드캐스팅, 실시간 알림, 이벤트 전파 등에 활용할 수 있다.
    라우팅 키와 상관없이 연결된 모든 큐로 메시지를 전송한다.
  • Topic Exchange :
    다양한 서비스에서 특정 규칙을 기반으로 메시지를 필터링해 전달할 수 있어 마이크로서비스 환경에 적합하다.
    라우팅 키 패턴 매칭(*, #)을 지원해 세밀한 라우팅이 가능하다.
  • Headers Exchange : 
    메시지 형식이나 메타데이터 기반 라우팅이 필요한 경우에 사용할 수 있다.
    라우팅 키 대신 메시지 헤더 값 기반으로 큐를 선택한다.

[프리코스를 마무리하며]

회고에 들어가기 전 내가 오픈 미션 설명회에서 들었던 말 중 가장 마음에 남는 말이 있었다.

“타인과 나를 비교하기보다는, 지금 나에게 얼마나 큰 도전이었는가가 중요하다.”

 

이번 회고에서는 ‘나 자신’이라는 테마로 스스로를 돌아보았다.

나는 프리코스 시작 한 달 전 자바와 스프링을 처음 시작했다. 정말 거짓말 없이 해당 언어와 프레임워크에 대한 경험이 전무했다.

 

그렇지만 나는 3주차 미션까지 자바로 코드를 짜고, MVC 패턴을 적용해보는 등 마음껏 도전했다.

 

오픈 미션에서는 새로운 IDE를 사용하고, 처음 보는 언어로 프로젝트를 구현하며, 메시지 큐의 구조와 프로토콜을 직접 설계하고 구현해보았다. 상용 메시지 큐와 비교하며 내부 동작을 학습하고, C++과 소켓 프로그래밍을 활용해 서버-브로커-클라이언트 구조를 구현하며 복잡한 흐름을 단계적으로 정리했다.

 

누군가와 비교하지 않아도, 내가 해낸 것 자체가 충분히 의미 있는 성장이었다. 작은 성공 경험들을 반복하며, 익숙하지 않은 기술도 점차 자신감을 가지고 다룰 수 있게 되었고, 실패와 시행착오 속에서도 개선점을 찾아가며 문제를 해결하는 나만의 루틴을 확립할 수 있었다. 나는 프리코스를 거치며, 내가 계획한 것보다 훨씬 많은 성장을 경험했다.

 

기능 구현을 넘어 태도의 성장으로

오픈 미션을 진행하며 나도 모르는 사이 치명적인 습관 하나가 고쳐졌다. 바로 “맡은 일을 제대로 마무리하지 못하던 습관”이다. 과거의 나는 학교 수업, 프로젝트뿐만 아니라 일상생활 전체에서 다음과 같은 패턴에 자주 머물렀다.

  1. 마감 기한은 지났는데 결과물이 덜 끝나 있거나
  2. 마무리를 제대로 하지 못해 아쉬움이 남거나
  3. 노력한 만큼 결과물이 완전하지 않게 끝나는 경우

프리코스에서는 짧은 시간 안에 ‘기획 → 구현 → 리팩토링 → 회고 → 상호 코드 리뷰’이 사이클을 계속 반복해야 했다. 이 짧은 주기의 순환 속에서 자연스럽게 두 가지 습관이 자리 잡기 시작했다.

  1. 죽이 되든 밥이 되든 마감 내에 결과물을 마무리하는 개발 습관
  2. 완성된 결과물에서 다시 개선점을 찾고 반영하는 피드백 루틴

사실 미션을 시작하기 전까지만 해도 “이번에도 혹시 마무리를 못 하고 끝나지는 않을까” 하는 걱정이 있었다. 하지만 3주 차 미션까지 진행한 후, 내 약점은 노력과 반복을 통해 습관으로 극복되어 있었다. 오픈 미션에서는 사전 학습부터 설계, 기능 구현, 그리고 추가 기능까지 목표했던 바를 전부 완성했고, 남은 시간에 더 개선할 여유까지 있었다. 나에게 이런 경험은 처음이었다.

 

다음 단계로

6주라는 시간은 길지도 짧지도 않은 기간이었다. 하지만 이 6주 동안 나는 단순히 언어와 기술을 배우는 것을 넘어, 내가 어떤 문제에 열정을 느끼는 사람인지, 어떤 방식으로 성장하는 사람인지, 그리고 어떤 개발자가 되고 싶은지 스스로 더욱 선명하게 확인할 수 있었다.

 

나는 어려운 문제에 마주했을 때 오히려 더 집중하고 몰입하는 사람이라는 것을 알게 되었다. 정답이 정해진 문제보다 스스로 방법을 찾아 해결해야 하는 문제에서 더 큰 동기와 즐거움을 느꼈다. 그래서 어떤 문제가 발생해도 무작정 해결하려 들기보다 결과를 관찰하고, 원인을 분석하고, 구조를 다시 설계하는 나만의 루틴을 견고하게 만들었다. 이 방식은 언어나 프레임워크가 바뀌어도 흔들리지 않는 내 개인의 문제 해결 방식이라는 점에서 큰 의미가 있다.

 

또 한 가지 프리코스를 통해 다시 한 번 강하게 느낀 점은 함께 성장하는 개발자가 되고 싶다는 것이다. 디스코드에서 코드 리뷰할 사람을 찾고 서로의 미션을 리뷰하고 의견을 나누면서 계속 사람들과 함께 성장하고 싶어졌다. 내가 놓친 부분을 다른 사람의 시선에서 확인할 수 있었고, 다른 사람의 코드를 읽고 피드백하면서 나의 사고도 넓어졌다. 개발은 혼자 하는 일이 아니라 함께 더 잘할 수 있는 일이라는 확신이 들었다.

 

그래서 프리코스는 단순한 교육 과정이 아니었다. 나에게는 개발자로서 본격적인 첫 페이지를 넘긴 순간이었다. 물론 성장에는 시행착오도 있고 불안도 있고 때로는 좌절도 따라온다. 하지만 이번 경험을 통해 한 가지 사실을 분명하게 알게 되었다. 진심으로 원하는 일에 도전하고 과정에 몰입하면 반드시 이전의 나보다 더 나아진 모습이 남는다는 것이다. 그 성장은 기술일 수도 있고, 사고 방식일 수도 있고, 태도일 수도 있다.

 

프리코스는 매 순간이 도전이었다. 내가 남긴 회고들을 돌이켜 보면 성장의 흔적이 분명하게 남아 있다. 그리고 나는 안다. 이 6주가 끝이 아니라 시작이라는 것을. 프리코스를 통해 나는 개발을 대하는 방법을 배웠다. 앞으로도 더 깊게 몰입하고, 새로운 문제에 도전하며 계속 성장할 것이다. 프리코스는 나의 여정에서 정말 중요한 출발점이었다.

 

 

'우아한테크코스 8기' 카테고리의 다른 글

[우아한테크코스 8기] 최종 코딩테스트 후기  (3) 2026.02.03
[우아한테크코스 8기] 1차 합격 했어요!  (1) 2025.12.30
[우아한테크코스 8기] 프리코스 3주차 회고  (0) 2025.11.10
[우아한테크코스 8기] 프리코스 2주차 회고  (0) 2025.10.29
[우아한테크코스 8기] 프리코스 1주차 회고  (0) 2025.10.21
'우아한테크코스 8기' 카테고리의 다른 글
  • [우아한테크코스 8기] 최종 코딩테스트 후기
  • [우아한테크코스 8기] 1차 합격 했어요!
  • [우아한테크코스 8기] 프리코스 3주차 회고
  • [우아한테크코스 8기] 프리코스 2주차 회고
kcnsmoothie
kcnsmoothie
얼레벌레
  • kcnsmoothie
    청산가리스무디
    kcnsmoothie
  • 전체
    오늘
    어제
    • 분류 전체보기 (17)
      • 우아한테크코스 8기 (6)
      • 아인슈타인클래스 17기 (3)
  • 블로그 메뉴

    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    K8S
    kata-container
    JVM
    observability
    ttrpc
    Prometheus
    Java
    Grafana
    우아한테크코스8기
    우아한테크코스
    아인슈타인클래스
    grpc
    docker
    kvm
    CI/CD
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
kcnsmoothie
[우아한테크코스 8기] 프리코스 오픈미션 회고
상단으로

티스토리툴바