GROWTH LOG STORIES

함께 만든 성장을,
기록으로 연결합니다.

AI와 함께 배우고, 직접 만들고, 서로 나눈
그로스로그 멤버들의 생생한 성장 기록을 만나보세요.

성장 기록
5기+이어진 커뮤니티
HEALTHIO
PROJECT

사진 한 장으로 시작하는 건강 루틴, Health IO

대표 이야기 읽기

ALL STORIES

성장의 순간을
한곳에서 만나보세요.

프로젝트의 시작부터 모임에서 나눈 인사이트까지,
그로스로그가 함께 만든 기록을 모았습니다.
개의 성장 기록

성장일지

[GL 5기 1회차] 약속 대신 구조가 지키게 — CQRS와 의존성 주입 · FSD 아키텍처 🌱

GROWTH LOG🌱 2026. 8. 11. 15:45
GL 5기 성장일지 1회차 큐레이션

안녕하세요! 그로스로그 입니다!😊 🌱

읽기와 쓰기를 갈라놓는 이유, 폴더 순서만으로 import를 막는 이유. 5기 첫 회차는 경계를 긋는 두 편입니다.

5기는 2026년 3월에 시작됐습니다. 첫 회차부터 백엔드 아키텍처프론트엔드 폴더 구조가 나란히 올라왔어요. 분야는 멀지만 두 분이 붙잡고 있는 질문은 같았습니다.

 

01

🧭 Cosmic Python 제2부: CQRS, 의존성 주입, 그리고 에필로그

송영록 님

이런 내용이에요
『Cosmic Python』(아키텍처 패턴 with 파이썬) 2부의 마지막 두 장과 에필로그를 정리한 글입니다. 읽기와 쓰기를 분리하는 CQRS, 그리고 의존성을 한 곳에서 조립하는 부트스트랩을 다룹니다.
읽기 모델을 만드는 네 가지 방법을 코드로 나란히 놓고 각각의 트레이드오프를 표로 정리했어요. 의존성 주입에서는 mock.patch가 왜 문제가 되는지부터 짚습니다.
에필로그가 이 글의 절반입니다. 레거시 위에서 이 패턴들을 어떤 순서로 도입할 것인가를 4단계로 나누고, "쓰지 않아도 되는 경우"까지 적어뒀습니다.

책 정리 글인데 요약이 아니라 판단의 재료를 남기는 쪽으로 썼습니다.

조금 더 들어가 보면

글이 CQRS를 설명하는 방식이 인상적입니다. "읽기와 쓰기를 나누자"는 구호로 시작하지 않고, 왜 나눠야 하는지를 먼저 표로 갈라놓습니다.

  쓰기(Command) 읽기(Query)
목적 상태 변경, 비즈니스 규칙 적용 데이터 조회, 화면 표시
일관성 트랜잭션 일관성 필수 약간의 지연(stale) 허용 가능
캐싱 캐싱 불가 캐싱 가능

그리고 이 문장이 나옵니다.

"사실 완벽하게 동기화된 시스템이라도, 페이지가 렌더링되는 순간 이미 데이터는 과거의 것이다."

이게 CQRS를 정당화하는 가장 짧은 논증입니다. 읽기 데이터가 최신이 아닌 건 분리해서 생긴 부작용이 아니라 원래 그런 것이라는 관찰이죠. 그러니 "어차피 stale할 수밖에 없다면, 그 사실을 인정하고 읽기 쪽을 따로 최적화하자"로 이어집니다.

📚 도메인 모델은 왜 조회에 안 맞는가

글은 도메인 모델의 목적을 이렇게 구분합니다. 도메인 모델은 "비즈니스가 어떻게 동작하는가"를 표현한 것이지 "데이터를 어떻게 보여줄 것인가"를 표현한 게 아니라고요.

그런데 조회에 도메인 모델을 쓰면 어떻게 되느냐 — Aggregate를 통째로 로딩하고, 관계를 탐색하고, 필터링합니다. "주문 목록 보여줘" 한 줄에 그 비용이 전부 붙습니다.

🪜 네 가지 방법을 계단으로 놓은 것

읽기 모델을 만드는 방법을 네 개 늘어놓는데, 이게 단순 나열이 아니라 점점 도메인 모델에서 멀어지는 순서입니다.

· A. Repository 그대로 — 기존 추상화를 재사용하지만 Python 레벨에서 필터링해서 비효율적

· B. ORM 쿼리 — 나아졌지만 SELECT N+1이 생기고 복잡한 쿼리는 SQL보다 읽기 어려움

· C. 순수 SQL — 성능을 완전히 제어. 읽기 전용이니 도메인 모델을 거칠 필요가 없음

· D. 비정규화 읽기 테이블 + 이벤트 핸들러 — 조인도 없고 도메인 모델도 안 거치는 단순 SELECT 하나

D가 "CQRS의 진짜 모습"이라고 글은 씁니다. 쓰기가 발생하면 이벤트가 나가고, 이벤트 핸들러가 읽기 전용 테이블을 자동으로 갱신하는 구조입니다.

🔁 "깨지면 어떡하지"에 대한 답

여기서 자연스럽게 걱정이 생깁니다. 읽기 테이블과 쓰기 모델이 어긋나면요?

글의 답이 좋습니다. 읽기 모델은 재구축이 쉽다는 것. 쓰기 모델의 현재 상태로 이벤트를 다시 재생(replay)하면 처음부터 다시 만들 수 있으니까요.

"읽기 모델은 언제든 버리고 다시 만들 수 있는 파생 데이터다."

이 한 문장이 읽기 모델의 성격을 정확히 규정합니다. 원본이 아니라 파생물이라서, 틀어지면 고치는 게 아니라 다시 만들면 됩니다. 저장소를 Redis로 바꾸는 예시도 같은 맥락이에요 — 비즈니스 로직은 그대로 두고 읽기 핸들러만 갈아끼웁니다.

💉 의존성 주입 — 약속을 구조로 바꾸기

13장은 성격이 조금 다릅니다. 문제 상황이 이렇게 제시돼요.

from allocation.adapters import email

def send_out_of_stock_notification(event: events.OutOfStock):
    email.send("...", f"Out of stock for {event.sku}")

핸들러가 email 모듈을 직접 import하고 있습니다. 그러면 테스트할 때 mock.patch를 써야 하고, 글은 그 대가를 셋으로 정리합니다 — 모든 테스트에서 mock해야 하고, import 경로가 바뀌면 모든 mock이 깨지고, mock이 쌓이면 유지보수 비용이 급격히 오릅니다.

해결은 단순합니다. 필요한 걸 파라미터로 받게 바꾸는 것.

📝 원문에서는 이렇게 씁니다

부트스트랩이 이 글의 중심입니다. 의존성을 조립하는 자리를 한 곳으로 모읍니다.

def bootstrap(
    start_orm: bool = True,
    uow = unit_of_work.SqlAlchemyUnitOfWork(),
    send_mail = email.send,
    publish = redis_eventpublisher.publish,
) -> MessageBus:
    if start_orm:
        orm.start_mappers()
    dependencies = {"uow": uow, "send_mail": send_mail, "publish": publish}
    ...

기본값이 프로덕션 의존성이고, 테스트에서는 가짜를 넘깁니다. 그리고 주입하는 쪽이 영리해요.

def inject_dependencies(handler, dependencies):
    params = inspect.signature(handler).parameters
    deps = {
        name: dependency
        for name, dependency in dependencies.items()
        if name in params
    }
    return lambda message: handler(message, **deps)

핸들러의 시그니처를 읽어서 필요한 것만 골라 넣습니다. uow만 받는 핸들러에는 uow만, send_mail도 받으면 그것도요. 핸들러마다 손으로 배선할 필요가 사라집니다.

효과는 테스트에서 드러납니다.

def bootstrap_test_app():
    return bootstrap.bootstrap(
        start_orm=False,
        uow=FakeUnitOfWork(),
        send_mail=lambda *args: None,
        publish=lambda *args: None,
    )

글이 이 코드 아래 적은 한 줄이 요점입니다 — "mock.patch가 한 줄도 없다. 명시적으로 가짜를 넣어줄 뿐이다."

🧗 에필로그 — 이 글에서 가장 실용적인 부분

패턴 설명보다 에필로그가 길다는 게 이 글의 특징입니다. "이미 수년간 쌓인 레거시 코드 위에서 일해야 한다"는 전제로 시작해요.

여기서 아키텍처 세금(architecture tax)이라는 개념을 꺼냅니다. 전체를 다시 쓰겠다고 하면 통과되지 않지만, "6개월 프로젝트에 3주 정도 정리 작업이 필요합니다"는 설득력이 있다는 것. 기능 개발과 함께 아키텍처를 개선하는 방식입니다.

도입 순서도 4단계로 못 박습니다.

1. 서비스 레이어 추출 — 유스케이스를 함수로 분리. "코드가 중복되어도 괜찮다"고 명시합니다

2. 도메인 모델에서 I/O 분리

3. Aggregate와 일관성 경계 식별"양방향 링크는 Aggregate가 잘못 설계되었다는 신호"

4. 이벤트와 메시지 버스 도입

그리고 흔한 오해 항목에 이런 문장이 있습니다.

"CQRS가 항상 필요하지는 않다. Repository로 충분하면 굳이 안 써도 된다."

12장을 통째로 CQRS에 쓰고 나서 마지막에 "안 써도 된다"고 적는 것. 패턴을 소개하는 글에서 보기 드문 태도입니다.

큐레이터 노트

패턴을 소개하면서 그 패턴을 쓰지 않을 조건까지 적은 글이라 뽑았습니다.

기술서 정리 글은 대개 "이 패턴은 이래서 좋습니다"로 끝납니다. 이 글은 장마다 트레이드오프 표를 붙였어요. CQRS 네 가지 방법에 각각 장점과 단점이 달려 있고, 의존성 주입 장의 표에는 "초기에 코드가 다소 장황해 보인다", "Flask 글로벌 bus 인스턴스는 스레드 안전성 고려 필요" 같은 단점이 나란히 적혀 있습니다.

읽고 나서 쓸지 말지 판단할 수 있게 되는 정리입니다. 요약은 아는 것을 줄이지만, 이 글은 고를 수 있게 만들어요.

에필로그를 이렇게 길게 다룬 것도 좋았습니다. 책의 부록 취급받기 쉬운 부분인데, 실무자에게는 여기가 본론이니까요. 인용한 문장 하나가 그 태도를 보여줍니다 — "바다를 끓이려 하지 마세요."

한 편으로 끝나는 글이 아니라 연재의 한 편이라는 점도 짚어두고 싶습니다. Part 1의 Repository·Unit of Work·Aggregate를 거쳐 여기까지 왔고, 그래서 마지막의 「패턴 도입 순서」 도표가 자기 기록의 목차처럼 읽힙니다.

원문 읽으러 가기  ↗youngroknroll.github.io/posts/part2-ch12-epilogue/
 

02

🧱 FSD 아키텍처 정독하기 1편

이승민 님

이런 내용이에요
FSD(Feature-Sliced Design) 공식 문서를 읽고 정리한 글입니다. 프론트엔드 코드를 레이어 · 슬라이스 · 세그먼트 세 단계로 나누는 방법론이에요.
여섯 개 레이어(app · pages · widgets · features · entities · shared)가 각각 무엇을 맡는지, 그리고 상위 레이어만 하위 레이어를 참조할 수 있다는 단방향 규칙을 코드 경로 예시로 설명합니다.
2장이 「당장 적용할 필요가 있는가?」입니다. 도입 조건부터 따지고 들어가요. 두 편으로 나눠 쓸 계획이라 이 글은 개념 정리, 다음 편이 장단점입니다.

공식 문서 정독 기록인데 읽는 순서를 스스로 정해서 들어갔습니다.

조금 더 들어가 보면

FSD의 핵심은 폴더 이름이 아니라 폴더 사이에 방향을 준다는 것입니다. 글이 그걸 정확히 짚습니다.

"총 6개의 레이어가 있으며 아래로 내려갈수록 담당하는 기능과 의존성이 줄어드는 순서다."
app       Routing · EntryPoint · Global Styles · Provider
pages     라우팅 기준 화면 단위
widgets   독립적으로 동작하는 큰 UI 블록
features  사용자에게 가치를 주는 액션
entities  프로젝트가 다루는 비즈니스 개념
shared    모든 레이어에서 재사용되는 코드

여기서 규칙 하나가 나옵니다. 상위는 하위를 참조할 수 있지만, 하위는 상위를 참조할 수 없습니다. pagesfeatures를 쓸 수 있지만 featurespages를 못 씁니다.

🚧 같은 층끼리도 막는다는 점

의외인 건 같은 레이어의 다른 슬라이스끼리도 import가 금지된다는 대목입니다. 글의 예시가 명확해요.

~/features/aaa/api/request.ts가 있을 때

· 같은 레이어의 ~/features/bbb불가능

· 하위 레이어의 ~/entities, ~/shared → 가능

· 같은 슬라이스 안의 ~/features/aaa/lib/cache.ts → 가능

그럼 aaabbb가 같이 일해야 하면 어떻게 하느냐. 글이 답을 적어뒀습니다 — 상위 레이어에서 조합하거나, 예외적으로 @x를 쓴 cross-import를 씁니다.

이게 왜 중요하냐면, 같은 층끼리 자유롭게 부르기 시작하면 층을 나눈 의미가 사라지기 때문입니다. 위아래는 막아놓고 옆은 열어두면 결국 옆으로 얽힌 그물이 되니까요. 조합은 위에서 한다 — 이 한 줄이 FSD가 스파게티를 막는 실제 장치입니다.

🧩 app과 shared만 다르게 생긴 이유

여섯 레이어 중 appshared만 슬라이스 없이 세그먼트가 바로 들어옵니다. 글이 그 이유를 각각 답니다.

· shared비즈니스 도메인이 없기 때문

· app모든 도메인을 묶는 상위 조정자 역할이기 때문

슬라이스는 도메인 단위로 자르는 것이니, 도메인이 없거나(shared) 전부를 아우르는(app) 자리에는 자를 기준이 없다는 뜻이죠. 규칙의 예외가 아니라 규칙에서 자연히 따라 나오는 결과입니다.

🏷️ 이름을 목적으로 짓게 만드는 규칙

세그먼트 이름에 대한 대목이 실무적으로 가장 바로 쓰입니다.

"세그먼트의 이름은 이 폴더가 무엇을 하는지 목적이 드러나는 이름이어야 한다. 그냥 components, hooks, types처럼 모호한 이름은 지양한다."

lib 폴더 설명에서도 같은 이야기를 합니다. 유틸을 모아두는 자루가 아니라 lib/datetime처럼 주제가 드러나야 한다고요.

shared/ui에 대한 구분도 세밀합니다. 비즈니스 로직이 없는 순수 컴포넌트만 두되, UI 자체 로직은 허용한다고 선을 긋고 각각의 예를 답니다.

· 비즈니스 로직 — API 호출, 도메인 데이터 처리, 인증·권한 체크, 비즈니스 규칙 적용

· UI 자체 로직 — 열림/닫힘 상태, 포커스 관리, 키보드 내비게이션, 애니메이션, 입력값 필터링

"공통 컴포넌트는 로직을 넣지 마세요"로 끝내면 모달의 열림 상태를 어디 둘지 매번 헷갈립니다. 두 목록으로 갈라놓으면 그 자리에서 판단이 됩니다.

🙅 만들지 않아도 되는 것들

레이어를 여섯 개 소개하는 글인데, 각 레이어 설명마다 "여기 안 넣어도 된다"는 단서가 따라옵니다. 이게 이 글에서 제일 실무적인 부분입니다.

· features"모든 동작을 무조건 feature로 만들 필요는 없다. feature가 많아지면 중요한 기능이 어디 있는지 찾기 어려워질 수 있다." 여러 페이지에서 재사용될 때 추출을 고려하라고 합니다. 여러 에디터가 같은 댓글 기능을 쓰면 comments로 뽑는 식이죠

· widgets"재사용되지 않고 특정 페이지의 핵심 콘텐츠에만 쓰인다면 굳이 위젯으로 분리하지 말고 페이지 레이어 내부에 두는 것이 좋다"

· pages"다른 페이지에서 재사용하지 않는 컴포넌트는 굳이 widgets나 shared로 분리할 필요 없이 페이지 내부에 두면 된다." 페이지 레이어에는 보통 전용 모델도 두지 않습니다

· 레이어 자체"모든 레이어를 프로젝트에 사용하는 것은 아니고 필요한 레이어만 골라서 쓴다." 새 레이어를 직접 정의하는 것은 권장하지 않는다고도 적혀 있습니다

구조를 도입하면 빈칸을 채우고 싶어집니다. 폴더가 여섯 개 생겼으니 여섯 개를 다 쓰게 되고, features가 있으니 모든 동작을 feature로 만들게 되죠. 그러면 구조가 코드를 정리하는 게 아니라 코드를 늘립니다.

shared에 대한 관찰도 같은 결입니다.

"일반적으로 shared 코드는 미리 계획되지 않고 개발 중에 추출될 여지가 크다. 실제로 어떤 코드 부분이 공유되는지는 개발 중에 명확해지기 때문인데"

공통 컴포넌트를 미리 정해두는 게 아니라 겹치는 게 드러나면 그때 빼내는 것입니다. 순서가 반대면 아무도 안 쓰는 공용 폴더가 생깁니다.

📝 원문에서는 이렇게 정리합니다

슬라이스가 많아졌을 때의 정리법도 다룹니다.

📂 pages/
  📂 home/            # 홈 화면
  📂 profile/         # 프로필 화면
  📂 settings/        # 설정 화면
  📂 product-detail/  # 상품 상세 화면

📂 pages/
  📂 auth/            # 로그인 + 회원가입 (구조가 비슷해서 그룹으로 묶음)
    📂 ui/
      📄 LoginPage.tsx
      📄 RegisterPage.tsx

그러면서 단서를 답니다. 슬라이스 그룹은 정리 목적일 뿐이라 그룹 자체가 index.ts 같은 public API를 가지면 안 되고, 단방향·같은 레이어 금지 규칙은 그대로 적용된다고요.

폴더를 묶는 것과 경계를 만드는 것은 다르다는 구분입니다. 이걸 안 적어두면 그룹 폴더에 index.ts를 만들어 새 슬라이스처럼 쓰기 쉽습니다.

큐레이터 노트

「당장 적용할 필요가 있는가?」를 2장에 둔 글이라 뽑았습니다.

아키텍처 정리 글에서 도입 조건은 보통 맨 뒤에 한 줄로 붙거나 아예 없습니다. 이 글은 개념을 다 설명하기 전에 먼저 물어요.

"현재 프로젝트 구조에 특별한 문제가 없다면 굳이 바꿀 필요는 없으며 모든 프로젝트에 맞는 아키텍처도 아니다."

그리고 언제 필요한지를 두 줄로 좁힙니다 — 프로젝트가 커지면서 유지보수 속도가 느려지는 경우, 기존 폴더 구조를 이해하기 힘든 경우. 기존 구조에서 점진적으로 옮기는 방법도 있다고 덧붙이고요.

읽는 계획을 먼저 밝힌 것도 좋았습니다. 첫 문단에 "두 번에 걸쳐 정리할 예정이며, 이번엔 기본 개념, 다음에 장점과 주의할 점"이라고 적어뒀어요. 실제로 이 기수 안에서 4편까지 이어졌습니다. 한 편으로 끝내지 않겠다고 미리 말하고 지킨 기록이라 뒤에 오는 사람이 어디까지 읽으면 되는지 알 수 있습니다.

공식 문서를 옮기기만 한 게 아니라 자기 언어로 다시 짠 흔적이 곳곳에 있습니다. @x cross-import, 슬라이스 그룹의 단서, UI 로직과 비즈니스 로직의 구분 같은 것들은 문서를 훑기만 해서는 안 걸리는 대목이에요.

원문 읽으러 가기  ↗harubanbo.tistory.com/2

💡 두 편을 겹쳐 읽으며

한쪽은 파이썬 백엔드, 한쪽은 프론트엔드 폴더 구조입니다. 겹칠 데가 없어 보이는데 나란히 놓으면 같은 자리를 짚고 있습니다.

지키자고 약속하는 대신, 구조가 대신 지키게

송영록 님 글의 의존성 주입은 결국 이런 이야기입니다. "테스트할 때 email.send를 mock하기로 합시다"라는 약속을, 파라미터로 받게 만들어 약속이 필요 없는 상태로 바꾸는 것.

이승민 님 글의 레이어 규칙도 같습니다. "상위 레이어를 참조하지 맙시다"라는 약속 대신, 레이어에 순서를 매겨 참조 자체가 성립하지 않게 만듭니다.

둘 다 사람의 주의력을 믿지 않습니다. 주의력은 사람이 바뀌면 사라지고 바쁠 때 제일 먼저 무너지니까요. 그래서 규칙을 문서가 아니라 구조에 넣습니다.

안 써도 되는 조건을 먼저 적었다

더 눈에 띈 공통점은 이겁니다. 두 글 다 "이걸 안 써도 되는 경우"를 명시했습니다.

송영록 님은 CQRS를 한 장 통째로 다룬 다음 "Repository로 충분하면 굳이 안 써도 된다"고 적었고, 이승민 님은 개념 설명에 들어가기 전에 "현재 프로젝트 구조에 특별한 문제가 없다면 굳이 바꿀 필요는 없다"고 적었습니다.

새로 배운 것을 소개할 때 가장 하기 어려운 말입니다. 공들여 읽은 것일수록 필요하다고 말하고 싶어지니까요. 두 분 다 그 자리에서 한 발 물러섰습니다.

경계를 긋되, 그 경계에 값을 매겼다

세 번째는 트레이드오프를 남긴 방식입니다.

송영록 님은 읽기 모델 네 가지에 각각 장단점 표를 붙였습니다. 순수 SQL은 성능을 제어하지만 스키마가 바뀌면 고쳐야 하고, 비정규화 테이블은 읽기가 빠르지만 쓰기에 비용이 붙습니다.

이승민 님은 슬라이스 그룹을 소개하면서 "단순히 정리 목적일 뿐이라서 그룹 자체가 public API를 가지면 안 된다"는 단서를 달았습니다. 편해 보이는 선택지에 값이 붙어 있다는 걸 같이 적은 거죠.

경계는 공짜가 아닙니다. 나누면 관리할 것이 늘고, 규칙을 만들면 예외 처리가 따라옵니다. 두 글 다 그 값을 숨기지 않았습니다.

이번 회차에서 가져갈 것

1. 읽기 데이터는 원래 과거다.

페이지가 렌더링되는 순간 이미 상태는 지나간 것입니다. 그러니 "읽기와 쓰기를 분리하면 데이터가 안 맞을까 봐"는 분리해서 생기는 문제가 아니라 원래 있던 조건입니다. 인정하고 나면 읽기 쪽을 따로 최적화할 길이 열립니다.

2. 읽기 모델은 버리고 다시 만들 수 있는 것으로 설계하기.

파생 데이터라는 성격을 살리면 틀어졌을 때 고치는 게 아니라 재생(replay)하면 됩니다. 저장소를 Redis로 바꾸는 것도 읽기 핸들러 교체로 끝납니다.

3. 테스트에 mock이 쌓이면 설계 신호로 읽기.

mock.patch가 늘어난다는 건 의존성을 몰래 들여오고 있다는 뜻입니다. 파라미터로 받게 바꾸면 가짜를 넘기는 것으로 끝나고, import 경로가 바뀌어도 테스트가 안 깨집니다.

4. 같은 층끼리도 막고, 조합은 위에서 하기.

위아래만 막고 옆을 열어두면 결국 옆으로 얽힙니다. FSD가 같은 레이어 슬라이스 간 import를 금지하고 상위에서 조합하게 한 이유입니다.

5. 폴더 이름은 목적이 드러나게.

components hooks types 대신 lib/datetime처럼요. 이름이 모호하면 그 안에 무엇이든 들어가고, 그때부터 폴더는 자루가 됩니다.

6. 새로 배운 것을 소개할 때 「안 써도 되는 조건」을 같이 적기.

이건 두 글이 함께 보여준 태도입니다. 그 한 줄이 있으면 읽는 사람이 자기 상황에 대입할 수 있고, 없으면 그냥 좋아 보이는 것이 하나 더 늘 뿐입니다.


성장일지는 멤버들이 2주에 한 번씩 자신의 성장을 기록하는 활동이에요. 매 회차 운영진이 모든 글을 읽고, 그중 특히 마음에 남은 글을 함께 골라 큐레이션합니다.

좋은 글 남겨주신 송영록 님, 이승민 님께 감사드립니다! 😊

다음 큐레이션으로 다시 찾아오겠습니다! 🌱

- 에디터 · 성장일지 큐레이터 -


※ 본 큐레이션은 각 저자가 공개한 글을 소개하는 것이며, 모든 원문의 저작권은 저자에게 있습니다. 저자 본인의 요청이 있을 경우 즉시 수정 또는 삭제합니다.

WRITE YOUR GROWTH

오늘의 배움을
내일의 성장으로.

기록은 나를 돌아보게 하고, 공유는 우리를 연결합니다.
당신의 다음 성장 이야기도 그로스로그에서 시작해보세요.

커뮤니티 둘러보기