Skip to content

Conversation

@pdh0128
Copy link
Member

@pdh0128 pdh0128 commented Oct 21, 2025

RPI 환경에서 크롤링(Selenium) 동작하도록 조정.

  • 크로미움 ARM64 기반 설치
  • 나무위키 클래스 태그 수정

Summary by CodeRabbit

릴리스 노트

  • Bug Fixes

    • 캐릭터 관련 콘텐츠 미발견 시 사용자에 친화적인 404 오류 메시지 제공으로 경험 개선
    • 채팅봇 목록 엔드포인트의 경로 해석을 수정하여 URL 접근성 개선
  • Chores

    • ARM64 기반 컨테이너 및 런타임 환경 최적화 (브라우저 실행 설정 포함)
    • Kafka 설정을 환경 변수로 전환해 배포 유연성 향상
    • 의존성 패키지(nadf) 버전 업데이트

@coderabbitai
Copy link

coderabbitai bot commented Oct 21, 2025

Walkthrough

Dockerfile을 ARM64 Python 3.11-slim 이미지로 전환하고 Chromium 관련 환경변수 및 추가 패키지를 명시했습니다. 누누위키 크롤링 실패 시 404를 던지는 NoContentFoundException을 추가하고, 서비스에서 해당 예외를 검사·로그하며 라우트 경로와 Kafka 설정의 일부가 환경변수 기반으로 변경되었습니다.

Changes

Cohort / File(s) Summary
Infrastructure & Dependencies
Dockerfile, requirements.txt
Dockerfile을 linux/arm64 Python 3.11-slim으로 빌드하도록 변경; CHROME_BIN, CHROMEDRIVER_PATH, CHROMIUM_FLAGS 및 추가 apt 패키지 추가; nadf 버전 0.1.28 → 0.1.30로 업데이트 (requirements.txt)
Exception Handling
app/chatbot/exception/no_content_found_exception.py
콘텐츠 부재 시 한국어 메시지와 HTTP 404를 반환하는 NoContentFoundException 클래스 추가 (BusinessException 상속)
Service Layer
app/chatbot/service/chatbot_service.py
누누위키 크롤링 결과가 비었을 때 NoContentFoundException 발생 로직 및 IndexError 처리, 진단 로그 추가, 미사용 gRPC 보조 함수 삭제
API Route
api/routers/chatbot.py
list_chatbots 엔드포인트의 라우트 데코레이터 경로를 "/" 에서 "" 로 변경
Core Events / Kafka
core/events/deps.py
Kafka 설정의 일부(kafka_bootstrap_servers, kafka_client_id)를 하드코딩에서 os.getenv 기반으로 변경 (환경변수 우선)

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as "API Router"
    participant Service as "ChatbotService"
    participant Crawler
    participant Exception as "NoContentFoundException"

    Client->>API: 요청 (list/generate 등)
    API->>Service: generate(character_id)
    Service->>Service: _crawl_namuwiki()
    Service->>Crawler: get_namuwiki_list()
    alt 크롤링 정상 응답
        Crawler-->>Service: namuwiki_list
        alt 리스트 비어있음
            Service->>Exception: raise NoContentFoundException
            Exception-->>Client: 404 응답 (콘텐츠 없음)
        else 리스트 존재
            Service-->>Client: 정상 처리 결과
        end
    else IndexError 발생
        Crawler-->>Service: IndexError
        Service->>Exception: raise NoContentFoundException
        Exception-->>Client: 404 응답
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 ARM64로 깡충, 이미지 바꾸고,
누누위키 없으면 404로 말해주네.
로그는 소근대고 예외는 단정히,
의존성도 새옷 입었구나.
토끼가 박수 짝짝! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목 "Fix 0.2.2/chromium dockerfile/pw 134"은 PR의 주요 변경사항인 ARM64 기반 Chromium Dockerfile 수정을 명확하게 언급하고 있습니다. 이는 PR 목표에서 강조된 핵심 인프라 변경사항(Raspberry Pi 환경에서 Selenium이 작동하도록 Chromium을 ARM64 기반으로 설치)을 직접 나타냅니다. 다만 PR은 채봇 서비스 예외 처리, Kafka 환경 설정, API 라우트 변경 등 여러 다른 변경사항도 포함하고 있어 전체 범위를 완전히 담지는 못합니다. 그러나 제목은 구체적이고 명확하며 PR의 주요 목표를 정확하게 반영하고 있습니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-0.2.2/chromium-dockerfile/PW-134

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
app/chatbot/service/chatbot_service.py (1)

183-209: 크롤링 에러 처리가 개선되었으나 코드 스타일 개선이 필요합니다.

try/except를 통한 IndexError 처리와 상세한 로깅이 추가되어 디버깅이 용이해졌습니다. 다만 정적 분석 도구가 지적한 몇 가지 스타일 개선사항이 있습니다:

  1. 불필요한 f-string 접두사: 193-196, 204-208번 라인의 print 문에서 placeholder가 없는 f-string 사용
  2. 구조 개선: 199번 라인의 return 문을 else 블록으로 이동하면 코드 흐름이 더 명확해집니다

다음 diff를 적용하여 스타일을 개선하세요:

         if not namuwiki_list:
-            print(f"Warning: No namuwiki content found for character '{character_name}'")
-            print(f"This could be due to:")
-            print(f"  1. Character name not found in Namuwiki")
-            print(f"  2. Network connectivity issues")
-            print(f"  3. Character name format/encoding issues")
+            print(f"Warning: No namuwiki content found for character '{character_name}'")
+            print("This could be due to:")
+            print("  1. Character name not found in Namuwiki")
+            print("  2. Network connectivity issues")
+            print("  3. Character name format/encoding issues")
             raise NoContentFoundException(character_name=character_name)
-        
-        return namuwiki_list
+        else:
+            return namuwiki_list
     
     except IndexError as e:
         # 크롤러 내부에서 deque가 비어있을 때 발생
         print(f"IndexError caught while crawling Namuwiki for '{character_name}': {e}")
-        print(f"Possible causes:")
-        print(f"  1. No search results found in Namuwiki")
-        print(f"  2. HTML parsing failed (structure changed)")
-        print(f"  3. Network error or access blocked")
-        print(f"  4. Character name encoding issue")
+        print("Possible causes:")
+        print("  1. No search results found in Namuwiki")
+        print("  2. HTML parsing failed (structure changed)")
+        print("  3. Network error or access blocked")
+        print("  4. Character name encoding issue")
         raise NoContentFoundException(character_name=character_name) from e

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b711105 and e0cc6fc.

📒 Files selected for processing (5)
  • Dockerfile (1 hunks)
  • api/routers/chatbot.py (1 hunks)
  • app/chatbot/exception/no_content_found_exception.py (1 hunks)
  • app/chatbot/service/chatbot_service.py (3 hunks)
  • requirements.txt (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
app/chatbot/exception/no_content_found_exception.py (1)
core/exceptions/business_exception.py (1)
  • BusinessException (1-5)
app/chatbot/service/chatbot_service.py (1)
app/chatbot/exception/no_content_found_exception.py (1)
  • NoContentFoundException (4-8)
🪛 Ruff (0.14.1)
app/chatbot/service/chatbot_service.py

193-193: f-string without any placeholders

Remove extraneous f prefix

(F541)


194-194: f-string without any placeholders

Remove extraneous f prefix

(F541)


195-195: f-string without any placeholders

Remove extraneous f prefix

(F541)


196-196: f-string without any placeholders

Remove extraneous f prefix

(F541)


199-199: Consider moving this statement to an else block

(TRY300)


204-204: f-string without any placeholders

Remove extraneous f prefix

(F541)


205-205: f-string without any placeholders

Remove extraneous f prefix

(F541)


206-206: f-string without any placeholders

Remove extraneous f prefix

(F541)


207-207: f-string without any placeholders

Remove extraneous f prefix

(F541)


208-208: f-string without any placeholders

Remove extraneous f prefix

(F541)

🔇 Additional comments (8)
api/routers/chatbot.py (1)

52-52: 라우트 경로 변경이 적절합니다.

@router.get("")로 변경하여 라우터 prefix와 함께 사용할 때 더 명확하고 깔끔한 경로를 제공합니다. 기능적으로는 동일하게 작동합니다.

app/chatbot/exception/no_content_found_exception.py (1)

1-8: 예외 클래스 구현이 올바릅니다.

NoContentFoundException 클래스가 BusinessException을 적절히 상속하고, 404 상태 코드와 함께 명확한 한국어 메시지를 제공합니다. 나무위키 콘텐츠가 없을 때의 에러 처리가 개선되었습니다.

Dockerfile (3)

1-2: ARM64 플랫폼 지정이 올바릅니다.

Raspberry Pi 환경을 위한 ARM64 플랫폼 지정이 적절하게 구성되었습니다. Python 3.11-slim 이미지 선택도 적합합니다.


7-21: Chromium 의존성 설치가 적절합니다.

헤드리스 Chromium 실행에 필요한 모든 라이브러리(libnss3, libxss1, libgbm1 등)가 추가되었습니다. --no-install-recommends 플래그와 캐시 정리를 통해 이미지 크기를 최적화한 점도 좋습니다.


23-26: Chrome 환경 변수 설정이 적절합니다.

Chromium 바이너리 경로와 플래그를 명시적으로 설정했습니다. --headless=new, --no-sandbox, --disable-dev-shm-usage 플래그는 Docker 컨테이너 환경에서 Selenium 크롤링을 안정적으로 실행하는 데 필수적입니다.

app/chatbot/service/chatbot_service.py (2)

21-21: 새로운 예외 클래스 import가 적절합니다.

NoContentFoundException을 import하여 나무위키 콘텐츠 부재 시 명확한 에러 처리를 제공합니다.


147-149: 콘텐츠 검증 로직이 적절합니다.

크롤링 후 namuwiki_list가 비어있는지 확인하고 NoContentFoundException을 발생시켜 명확한 에러 처리를 제공합니다.

requirements.txt (1)

66-66: nadf 패키지 버전 및 보안 확인 완료

nadf 0.1.30 버전은 PyPI에 존재하며 알려진 보안 취약점이 없습니다. 변경사항은 안전합니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
core/events/deps.py (1)

12-13: Pydantic Settings의 기본 기능을 활용하는 것이 좋습니다.

BaseSettings는 자동으로 환경변수를 로드하므로 os.getenv()를 직접 사용하는 것은 중복됩니다. 현재 방식은 Pydantic의 유효성 검사와 타입 변환 기능을 우회하게 됩니다.

특히 kafka_bootstrap_servers의 경우 환경변수 이름이 필드명과 일치하므로 완전히 불필요합니다. kafka_client_id에서 KAFKA_PRODUCER_ID라는 다른 환경변수명을 사용하고 싶다면 Pydantic의 Field를 사용하는 것이 더 적절합니다.

다음과 같이 수정하는 것을 권장합니다:

-import os
+from pydantic import Field
 
 class KafkaSettings(BaseSettings):
     """Kafka 설정"""
-    kafka_bootstrap_servers: str = os.getenv("KAFKA_BOOTSTRAP_SERVERS", "localhost:9092")
-    kafka_client_id: str = os.getenv("KAFKA_PRODUCER_ID", "fastapi-event-publisher")
+    kafka_bootstrap_servers: str = "localhost:9092"
+    kafka_client_id: str = Field(
+        default="fastapi-event-publisher",
+        validation_alias="KAFKA_PRODUCER_ID"
+    )
     kafka_compression_type: str = "gzip"
     kafka_acks: str = "all"

이 방식은 Pydantic Settings의 기능을 완전히 활용하면서도 원하는 환경변수명을 사용할 수 있습니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0cc6fc and 031f094.

📒 Files selected for processing (1)
  • core/events/deps.py (1 hunks)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant