(주간일지) 2025-11-03 ~ 2025-11-09

놀았던 날이 없는데 논 것 처럼 블로그에 아무 것도 못써서 올리는 주간일지^_ㅠ


11/03(월)

- 오늘은 회사 모각코 사이드 프로젝트 대략적인 구성을 잡았다.

오프라인으로 모여서 했지만... 원활한 화면 공유를 위해 zep에서 진행하기

- front들은 core쪽 구상했고, 내가 속한 backend는 약간의 코드컨벤션이라거나 패키지 구조를 더 확실하게 잡았다.

root
├─ common                      # 공통(기술) 모듈: 유틸/웹/DB (도메인 규칙 금지)
│  ├─ utils                    # 순수 유틸(String/Time/Id 등)
│  ├─ exception                # 글로벌 예외/에러응답/요청 로깅 등
│  └─ jpa                      # BaseEntity/Auditing/공통 Converter...
│
├─ gateway                  
│`
├─ core                        # 서비스 간 통신
│  ├─ 
│  └─ shared-kernel            # ErrorCode, Result, 중립 값객체(웹/JPA 의존 금지)
│
├─ admin
│  └─ src/main/java/com/farm2pot/admin
│     ├─ product               # 하위 도메인1
│     │  ├─ controller
│     │  │  └─ dto            # ← Controller DTO(요청/응답)
│     │  │ 
│     │  ├─ service
│     │  │  └─ dto            # ← Service DTO(Command/Query/Result: 내부용)
│     │  │ 
│     │  ├─ repository
│     │  │  └─ cutom          # QueryDSL 구현
│     │  │ 
│     │  ├─ entity
│     │  └─ enums             # 도메인 정책형 enum(표시 전용은 controller/dto 내부)
│     │
│     ├─ box                  # 하위 도메인2 (동일 규칙)
│     └─ policy               # 하위 도메인3 (동일 규칙)
│
├─ subscription                # 별도 마이크로서비스(동일 규칙)
│  └─ src/main/java/com/farm2pot/subscription/...
│
└─ user                        # 별도 마이크로서비스(동일 규칙)
   └─ src/main/java/com/farm2pot/user/...
더보기

@ 최소규칙

  • 레이어 의존 방향: controller → service → repository(interface) ← repository/impl
  • DTO 분리
    • controller/dto : 외부 계약(요청·응답). @Valid 등 프레임워크 애노테이션 허용.
    • service/dto : 내부 유즈케이스 파라미터/결과. 프레임워크 의존 금지.
    • DTO : record 사용
    • DTO ↔ Entity 또는 DTO ↔ DTO간 변화는 MapStruct를 사용 ⇒ controller에서 책임을 질 예정이므로 controller\dto\mapper에 위치
    • DTO 네이밍
      • ProductResponse (단건 / 목록 ⇒ List<ProductResponse>)
      • UpdateProductRequest (수정 요청)
      Service
      • 요청 객체 (Service In):
        • 예시: ProductCreateCommand, ProductUpdateCommand, ProductListQuery
        • Service에게 어떤 행위(Command)를 수행하도록 명령하는 데이터라는 의미를 부여
      • 응답 객체 (Service Out):
        • 예시: ProductQueryResult, ProductCreateResult
        • Service가 비즈니스 로직을 처리한 결과(Result) 데이터를 담고 있음을 나타냄
    • Controller
  • Enum 배치
  • Repository
    • 인터페이스는 repository 루트에, QueryDSL의 경우 repository/custom 분리.
  • 서비스 간 호출
    • 항상 gateway 경유(모듈 간 직접 참조 금지).
  • 공통 모듈
    • common: 서비스 호출 등 필요 없는 라이브러리성 모듈만(gradle에서 subProject에 dependecy 할 예정)

- 사이드 프로젝트 fork 떠서 로컬로 갖고오고, commit하는 방법까지 안내했다.

더보기

@ 개인으로 Fork따서 원격 연결하기

 

현재 원격 저장소 확인

git remote -v

원격 저장소 설정

# 기존 origin 제거 (만약 다른 저장소로 연결되어 있다면)
git remote remove origin

# 본인의 fork를 origin으로 추가
git remote add origin <https://github.com/개인계정/개인Repository.git>

# 원본 저장소를 upstream으로 추가
git remote add upstream <https://github.com/공통프로젝트(organization)/공통Repository.git>

upstream dev 브랜치 내용을 본인 main에 동기화

# 모든 원격 정보 가져오기
git fetch origin
git fetch upstream

# main 브랜치로 이동
git checkout main

# upstream의 dev 브랜치 내용을 main에 병합
git merge upstream/dev

# 병합된 내용을 본인 fork에 푸시
git push origin main

작업 후 커밋 및 푸시

# 작업 완료 후
git add .
git commit -m "커밋 메시지"

# 본인 fork의 main에 푸시
git push origin main

 

PR 등록하는 방법까지 알려줌

11/05(수)

- 회사 업무 처리하다가... AppleMail은 본문 이미지 처리 방식이 다르다는걸 알았다😧

일단 확인 요청의 요지는 동일한 메일을 pop3에서 받았는데도, 아웃룩에서 갖고간 건 본문에 이미지가 보이는데 회사포탈 메일에서는 이미지가 안보인다고 한다는 것이었다.

eml 파일 전달 받아서 확인해보니까 구조가 달랐다.. (회사 업무라 공개는 불가능하다 ^_^ㅠ)

문제점
1) 회사포탈에서 보는 메일 본문의 Content-Type은 text/plain 으로 되어있어서 이미지를 삽입할 수 있는 HTML 본문(text/html)이 없음
2) apple계정에서 보낸 이미지 파일은 Content-Disposition: inline으로, 본문에 삽입해달라고 요청하고 있음
   => MIME 표준 규격에 따르면 이미지 본문 삽입 시 본문은 해당 이미지를 이미지 태그 형태로 참조할 수 있는 html 기반이어야 함(text/plain에서는 불가)
3) main 컨테이너가 Content-type: multipart/mixed로 되어있어서 이미지 파일을 본문과 독립된 일반 첨부파일로 인식하는 것으로 추정됨

알고보니까 꽤 이전부터 논쟁(?)이 되었던 내용이라고 한다.

https://discussions.apple.com/thread/3209246?page=5&sortBy=rank
https://discussions.apple.com/thread/2020972

그래서 아웃룩은 이미 이런거에 대한 처리를 했을지도..?🤔

이렇게 inline으로 요청 오는 건들은 샘플 데이터 몇 개 받아서 처리 방식을 변경해야겠다.

(apple.com을 메일 주소로 쓰는 계정은 보통 회사 계정이라고 한다. 우리 회사도 있는데 요청하면 알려 주시려나ㅠㅠ?)


11/06(목)

원래 오늘 회사 모각코 날이긴 한데 고객사 하나 반영 건이 있어서 야근 했다..

 

야근 전에도 업무들이 좀 있어서 후다다닥 헤치웠는데 갑자기 부장님이 오시더니 회사 동기가 담당하는 사이트 검색 도입 건 하나 있는데 가이드라인(이라고 했지만 사실상 초기 구축 + 샘플용 모듈 구축 + 가이드 + 이후 지원)까지 진행해줘야한다고 한다. 일정 되냐면서...

유지보수하면서 추가개발도 하고 개선하는건 맞는데, 내 업무도 갑자기 전조 없이 하루만에 통보로 변경하더니

이건 무슨 지금  업무도 하면서 기존 개발지원 업무도 같이 하라는ㅋㅋㅠ... 이거 한다고 내 현재 업무가 줄어든다거나 그런건 전혀 없다..

내가 너무 귀여운 탓이라고 하자 (๑>؂•̀๑) ꫂ ၴႅၴ

그래도 간만에 즐거울 것 같다. 한 동안 머리 깨지겠지~!

 

❅ *˚̩͙*‧₊̊‧*˚̩͙̩͙*‧₊̊‧*˚̩͙*‧₊̥‧*˚̩͙*‧*˚̩͙̩͙*‧₊̊‧*˚̩͙*‧‧*˚̩͙*‧₊̊‧* ❅

 

야근하고 집 와서는 40분 정도라도 강의 듣기.. 우리 회사는 커머스와는 관계 없기 때문에 실제 상황들을 좀 알고 싶었다.

인프런 - 제미니의 개발실무

다음 주까지 다 들어보자!

 

❅ *˚̩͙*‧₊̊‧*˚̩͙̩͙*‧₊̊‧*˚̩͙*‧₊̥‧*˚̩͙*‧*˚̩͙̩͙*‧₊̊‧*˚̩͙*‧‧*˚̩͙*‧₊̊‧* ❅

 

그리고 다시 모각코 zep으로 참여하기

같이 admin 만드는 프론트 담당 사원이랑ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 티키타카하기


11/07(금)

똑같은 로직인데 로컬은 되고 운영은 안되는 현상을 발견했다.. 설정 값 문제일까 싶어서 확인해봐도 아무리 봐도 모르겠더라.

단순히 데이터를 불러오는 쿼리인데도 로컬은 의도대로 잘 나오고, 운영은 계속 가장 상단의 특정 카테고리만 조회가 되어서 하루 동안은 이것만 본 것 같다^^ㅠ

 SELECT *
 FROM (
 		SELECT /*+ index_desc(idx) */
        		rowid,
                ROW_NUMBER() OVER (ORDER BY date DESC) AS no_
		FROM 테이블
        WHERE (많은 조건 절...)
        AND ROWNUM <= 5
      ) tbl
WHERE 1=1
AND no_ BETWEEN 1 AND 5

대략적인 쿼리는 위와 같다.

권한 쿼리 문제인가? 싶어서 조건절을 하나하나 소거법으로 지워가면서 확인했다.

저기서 발견한건.. ROWNUM 조건이 없어지는 순간 정상적으로 나오길래 이거구나 싶었다.

 

실행 계획을 비교하면 아래와 같았다!

운영

  • SORT (ORDER BY) (Cost: 89): 실행 계획의 최상단 근처에 SORT (ORDER BY)가 있다.
  • WINDOW (SORT PUSHED RANK): VIEW 하위에 WINDOW (SORT PUSHED RANK)가 있고, Oracle이 ROW_NUMBER() 함수를 처리하는 방식인데
    여기서 SORT가 포함되어 있다는 것은 전체 결과를 정렬하려고 시도했거나, 적어도 많은 양의 데이터를 정렬한 후 상위 6건을 추출하려고 했음을 의미한다고 한다.
  • NESTED LOOPS 코스트 증가: 하위 조인 및 필터링 과정에서 NESTED LOOPS의 코스트와 카디널리티가 로컬보다 높게 책정되어 있어, 데이터 접근 및 처리 비용이 높다

로컬

  • WINDOW (NOSORT STOPKEY): VIEW 하위에 WINDOW (NOSORT STOPKEY)
    • NOSORT: 이 환경에서는 ROW_NUMBER()를 계산하는 과정에서 별도의 정렬 작업 없이 바로 데이터를 추출했음을 의미한다고 한다. 데이터 양이 적어서 그런 것 같다.
    • STOPKEY: ROWNUM <= 5 조건을 매우 효율적인 Top-N 필터링으로 사용

로컬 환경에서는 데이터 양이 적고 실행 계획이 효율적이었기 때문에, ROWNUM <= 5 조건이 있음에도 불구하고 운 좋게 정확한 순서에 가까운 5건을 가져와 원하는 결과가 도출되었을 가능성이 높았던 것 같다. 즉, 실행 계획이 효율적이었기 때문에 결과가 '우연히' 맞았던 것.....

그러니까 로컬에서는 잘 나오지ㅠㅠㅠ

 

아무래도 그 이후에 조건 절로 no_ BETWEEN 1 AND 5 으로 따로 있으니까 ROWNUM을 지우는 방향으로 개선을 해봐야할지 검토해봐야겠다ㅜ


11/09(금)

오늘은 늘상 하는 모각코 모임에서, 회사 스터디 프로젝트를 진행했다!

core를 손 보고 admin을 만들고 있는데..

내가 만든 응답 구조 래핑이.. WebMVC 기반으로 만든거라 다른 사람이 만든 gateway에 적용이 안되고 충돌나는게 문제였다(gateway는 webflux로 구현됨ㅠㅠ)

기존 코드 좀 잘 보자............