3주차 과제에 대한 회고가 우선이지만.. 시간이 많이 지났고 그것보단 자유주제에 대한 회고를 쓰는게 좋을 듯 하여 넘깁니당..
자유주제 정하기
이번 기수는 이전 기수와 다르게 자유 주제가 추가되었다. 말 그래도 자유 주제이다..
음, 프리코스 기간 가장 크게 깨달은 건 기초의 부족이었다. 그러면서 느낀건.. 나는 Spring은 잘 알고 쓰나 라는 생각이었다. 올해 프로젝트에 참여하며 Spring을 사용했지만, 어떤 구조를 가지고 있는지. 어떤 기능을 지원하는지 잘 모른다. 그래서 정한 주제는..
Spring 구현 프로젝트이다! (두둥)
하지만.. 혼자 하긴 양이 방대하다 생각해 프리코스에 참여하지 않는 팀원 한 명과 같이 진행했다. (문의사항에 보니 외부 팀원이어도 상관 없다 해서 함께함)

평소 알던 선배와 진행했다. (많은 걸 알려줘서,, 스승님이라 부름)
일단 분업을 했다. IoC Container는 같이 개발하고, 선배는 Web 나는 DB 연결을 각자 개발하기로 했다.
구현 목록
Spring - IoC Container 개발 (공동 개발)
이 부분이 힘들었다.. 구현은 둘째치고 그냥 개념이 어려웠음. 나는 @Component에 대해 빈 주입을 담당했고, 선배는 @Autowired에 대해 빈을 찾아 의존성 주입을 담당했다.
핵심 클래스는 다음과 같다.
BeanFactory: IoC Container의 핵심 인터페이스로 생명주기 관리를 총괄. 이때 모든 빈은 싱글톤으로 관리됨
SproutApplicationContext: IoC Container의 핵심 클래스로, 빈 관리 기능과 더불어 자동 컴포넌트 스캔 및 애플리케이션 생명주기 제어 기능을 제공
BeanPostProcessor: 컨테이너가 빈을 생성하고 의존성 주입을 마친 후, 초기화 단계 후에 커스텀 로직을 개입시킬 수 있는 기능 제공
(회고 글이니 구현 목록에 대해선 간단하게 적을게요)
Spring - Data Access Layer (단독 개발)
이후엔 따로 개발했다. 나는 사실.. DB를 싫어한다. (사실 성적이 좋지 않아서 일지도..?) 암튼 하지만 이번에는 도전이 필요하다 해서 DB 연결을 맡았다. 근데 DB 개념을 공부하기 보단 proxy나 transaction 구현 방법에 대해 알게 되었다. (어쨌든 얻었잖아?)
핵심 클래스는 다음과 같다.
JdbcTemplate : JDBC API를 사용해 데이터 베이스와 상호 작용
DataSourceUtils: JDBC 커넥션 관리 헬퍼 클래스로 트랜잭션 동기화 기능을 위해 Connection 획득 및 해제하는 메서드
EntityMapper: JDBC의 데이터를 자바 객체로 변환하는 역할
RepositoryHandler: @Repository가 붙은 인터페이스에 대해 JDK Dynamic Proxy를 사용해 레포지토리 메서드 호출을 대신 수행한다
TransactionInterceptor: 컨테이너 초기화 단계에서 Transaction 적용 대상에 대해 CGLIB를 이용해 프록시 객체로 교체한다
TransactionManager: TransactionInterceptor의 요청을 받아 실제 DB와 트랜잭션을 수행한다.
TransactionSynchronizationManager: ThreadLocal을 사용해 DB connection을 실제 실행 중인 스레드에 저장하고 관리한다
프로젝트 구조 (공동 개발)
전반적인 프로젝트 구조는 같이 개발했다.
1. 모듈형 모놀리스 구조
일반적인 모놀리스 구조는 시간이 지남에 따라 무분별하게 서로 의존하게 된다. 선배가 "자동완성도 스파게티 코드를 방지해준다!"란 말을 한 적 있는데 모듈형 모놀리스 구조를 적용하며 크게 와닿았다. Spring Boot가 다양한 라이브러리를 추상화 하듯, 우리 프레임 워크도 모듈로 분리해 설계했다.
├─myproject
└─sprout
├─core
│ ├─bundle
│ └─core-api
├─data
│ ├─data-api
│ └─data-impl
├─global
└─web
├─web-api
└─web-impl
또한 build.gradle의 규칙을 강제해 의존 역전 원칙을 적용했다. 모듈 - impl는 다른 모듈의 구현체를 의존할 수 없고, 무조건 api를 의존해야 한다.
2. 번들
Spring Boot는 단 하나의 번들에 의존하고 내부에 여러 라이브러리를 사용하고 있다. 그래서 우리도 번들을 통해 사용자에게 필요 기능만을 제공하기로 했다. 이러면 순환 참조가 미리 차단되고, 점진적 컴파일이 가능해 빌드 성능이 최적화된다.
plugins {
id 'java-library'
}
dependencies {
// [API] 사용자가 직접 코드에서 Import해서 사용할 모듈들 (외부 노출)
api project(':sprout:global')
api project(':sprout:core-api')
api project(':sprout:data-api')
// [Implementation] 런타임에 실제 기능을 수행할 구현체들 (내부적으로만 사용)
implementation project(':sprout:web-api')
implementation project(':sprout:web-impl')
implementation project(':sprout:data-impl')
}
이렇게 번들을 구성하면
plugins {
id 'application'
}
dependencies {
runtimeOnly 'com.h2database:h2:2.2.224'
runtimeOnly 'com.mysql:mysql-connector-j:8.3.0'
implementation project(':sprout-starter-web')
}
application {
mainClass = 'com.my.project.MyProjectApplication'
}
위 처럼 하나의 프로젝트만 의존해서 개발할 수 있다.
깨달은 점
1. 사람들은 왜 Spring을 사용하는가!
이것 저것 구현하면서,,, Spring이 가지고 있는 편의성에 대해 깨달았다. 개발자는 그저 비즈니스 로직에만 집중하면 된다! 또한 많은 사람들이 Spring을 사용하기에 개발 정보도 찾기 편했고, 에러가 날 때도 구글링이 편했다.
2. 디자인 패턴
@Transactional을 개발하며 프록시 패턴에 대해 이해하게 되었다. 맨날 공부하면 예시가 사소해 이런걸 내가 알아도 쓸 일이 있을까? 라는 생각을 자주하게 되었는데, 이번에 거대 시스템 안에서 어떻게 프록시가 사용되는지. 그래서 어떤 이점을 가지게 되는지 깨달았다.
3. 자바는 매력적이다.
Reflection 구현 중 InaccessibleObjectException가 발생했다. 이는 Java 9 이상에선 모듈 시스템이 강력해서 외부 라이브러리가 JDK 내부 API를 건드리는 것을 방지하기 위해 발생한다. 이때 설정을 하면 해결되긴 한다.
자바는 강력한 타입 시스템을 가지고 있다. 처음 복수전공을 시작하고 사용한 언어가 C++이라 그런지 내겐 파이썬보다 자바가 익숙하다. Reflection이란 높은 자유도를 주는 기능을 제공하지만, 캡슐화를 지키려는 자바 언어의 철직이 매력적이라 생각했다.
4. 모든 규칙에는 이유가 있다!
서비스에는 상태 필드가 존재하면 안된다. 이를 나는 이전까지 객체지향을 위함이라 생각했다. 그러나 이는 스프링이 빈을 싱글톤으로 관리하기 때문이다.
또한 서비스 계층에는 레포지토리 메서드에 @Transactional을 굳이 붙이지 않아도 트랜잭션이 된다. 이는 JpaRepository의 기본 구현체인 SimpleJpaRepository가 이미 @Transactional을 가지고 있기 때문이다.
이런 규칙들은 사실 Spring 설계때문에 생겨났다. 이런 배경이 있다는걸 깨달았다.
프로젝트 소개
Spring은 기존 프레임 워크 개발로 힘들어하던 개발자들에게 봄이 왔단 의미에서 생겼다.
개발자들의 낭만.. 그건 바로 프레임 워크 개발! (지대쩐다..)
암튼 거기서 착안해서 우리 프레임 워크도 새싹이란 의미의 Sprout로 정했다!
혹쉬 궁금하신 분들은 깃허브에서 확인하세요..
https://github.com/SpringSprout
소감 총총..
참 힘들었다.. 흑흑.. 처음 1~2주는 개발이 아닌 개념 공부를 하며 보냈다. 그래서 오히려 개발에 많은 시간을 못보내 아쉽다. 하지만 하길 참 잘했다! 이전까진 Spring에 대해 막연한 두려움이 있었다. 그런데 이젠 한층 가까워진 기분이다!
이 자리를 빌려.. 공부만을 목적으로 프로젝트에 같이 참여해준 나의 스승님께 감사의 인사를 드린다.. 보면서 많이 배워요! (중간중간 징징대며 진상짓 한건 좀 죄송)
'우테코 끄적끄적' 카테고리의 다른 글
| camp.nextstep.edu.missionutils 분석 + utils 패키지는 어떤 역할을 할까? + 난수는 어떤 원리로 생성될까? (0) | 2025.10.25 |
|---|