본문 바로가기

Back-End

# Java 개발자를 위한 Python 문법 정리

반응형

Java 개발자를 위한 Python 문법 정리

AI Agent 프로젝트에서 실제로 사용한 문법 중심으로 정리


1. 변수와 타입

# Java: String name = "홍길동";
name = "홍길동"          # 타입 선언 없음, 그냥 대입

# Java: int age = 30;
age = 30

# Java: boolean isActive = true;
is_active = True         # True/False (대문자 시작)

# Java: String text = null;
text = None              # null → None

# 타입 힌트 (선택사항, Java처럼 명시 가능)
# Java: String name = "홍길동";
name: str = "홍길동"
age: int = 30
is_active: bool = True

2. 문자열 (f-string)

# Java: String msg = "안녕 " + name + ", 나이는 " + age + "살";
msg = f"안녕 {name}, 나이는 {age}살"   # f-string: {} 안에 변수 바로 사용

# 계산도 가능
msg = f"10 + 20 = {10 + 20}"           # "10 + 20 = 30"

# Java: String.format("%.2f", 3.14159)
msg = f"{3.14159:.2f}"                 # "3.14"

# 여러 줄 문자열 (Java의 """ """)
prompt = """
당신은 AI 어시스턴트입니다.
한국어로 답변하세요.
"""

3. 리스트 (List)

# Java: List<String> items = new ArrayList<>();
items = []
items = ["사과", "바나나", "포도"]

# 추가
items.append("딸기")           # Java: items.add("딸기")

# 인덱싱
first = items[0]               # "사과"
last = items[-1]               # 마지막 요소 "딸기" (Python만의 기능)

# 슬라이싱
part = items[0:2]              # ["사과", "바나나"] (0번~2번 미만)

# 길이
length = len(items)            # Java: items.size()

# 반복
for item in items:             # Java: for (String item : items)
    print(item)

# 리스트 컴프리헨션 (Java Stream과 유사)
# Java: items.stream().map(s -> s.toUpperCase()).collect(Collectors.toList())
upper = [item.upper() for item in items]

# 조건 필터링
# Java: items.stream().filter(s -> s.length() > 2).collect(...)
long_items = [item for item in items if len(item) > 2]

4. 딕셔너리 (Map)

# Java: Map<String, Object> map = new HashMap<>();
data = {}
data = {"name": "홍길동", "age": 30}

# 값 조회
name = data["name"]            # Java: map.get("name")
name = data.get("name", "기본값")  # 없으면 기본값 반환

# 추가/수정
data["email"] = "hong@test.com"  # Java: map.put("email", "...")

# 키 존재 확인
if "name" in data:             # Java: map.containsKey("name")
    print("있음")

# 반복
for key, value in data.items():  # Java: for (Map.Entry<> entry : map.entrySet())
    print(f"{key}: {value}")

# 자주 쓰는 패턴: 딕셔너리로 결과 반환 (LangGraph Node에서 많이 씀)
def my_node(state):
    return {"messages": [...], "next": "research"}  # 딕셔너리 반환

5. 함수 (def)

# Java: public String greet(String name) { return "안녕 " + name; }
def greet(name: str) -> str:
    return f"안녕 {name}"

# 기본값 파라미터
# Java: public void connect(String host, int port = 8080) → 지원 안 됨
def connect(host: str, port: int = 8080):  # port 기본값 8080
    print(f"{host}:{port}")

connect("localhost")          # port = 8080 자동 적용
connect("localhost", 9090)    # port = 9090

# 키워드 인수 (호출 시 파라미터명 명시)
connect(host="localhost", port=9090)
connect(port=9090, host="localhost")  # 순서 바꿔도 됨

# 여러 값 반환 (Java는 객체 반환해야 함)
def get_range():
    return 10, 20              # 튜플로 반환

start, end = get_range()       # 언패킹

6. 클래스

# Java:
# public class Person {
#     private String name;
#     private int age;
#     public Person(String name, int age) { ... }
# }

class Person:
    def __init__(self, name: str, age: int):  # 생성자 (__init__)
        self.name = name   # self = Java의 this
        self.age = age

    def greet(self) -> str:  # 메서드 첫 파라미터는 항상 self
        return f"안녕, 나는 {self.name}"

# 사용
p = Person("홍길동", 30)   # Java: new Person("홍길동", 30)
print(p.greet())

7. TypedDict (LangGraph State에서 사용)

from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages

# Java의 DTO/Record와 유사
# public record AgentState(List<Message> messages, String next) {}

class AgentState(TypedDict):
    messages: Annotated[list, add_messages]  # 메시지 자동 누적
    next: str                                # 다음 노드 이름
    result: str                              # 처리 결과

# TypedDict는 딕셔너리처럼 사용
state: AgentState = {
    "messages": [],
    "next": "research",
    "result": ""
}

# 값 접근
print(state["next"])         # "research"

8. Optional, Annotated (타입 힌트 고급)

from typing import Optional, Annotated

# Optional: null 가능한 값
# Java: @Nullable String name
def greet(name: Optional[str] = None):
    if name is None:
        return "안녕 손님"
    return f"안녕 {name}"

# Optional[str] = str | None 과 동일
name: Optional[str] = None    # None 가능

# Annotated: 타입 + 메타데이터 추가
# LangGraph에서 add_messages 동작 방식을 지정할 때 사용
messages: Annotated[list, add_messages]
# = "list 타입인데, 값이 추가될 때 add_messages 함수로 처리해"

9. 데코레이터 (@)

# Java의 어노테이션(@)과 유사하지만 더 강력
# 함수를 감싸서 기능을 추가하는 패턴

# LangChain @tool
from langchain_core.tools import tool

@tool
def get_stock_price(ticker: str) -> str:
    """주식 현재가를 조회합니다."""
    return f"{ticker} 주가: $100"

# FastAPI @app.post
from fastapi import FastAPI
app = FastAPI()

@app.post("/chat")
def chat(request):
    return {"answer": "안녕"}

# 데코레이터 원리 (참고)
# @tool 은 아래와 동일
# get_stock_price = tool(get_stock_price)

10. import (모듈 시스템)

# Java: import com.example.service.UserService;
from langchain_core.tools import tool          # 특정 클래스/함수만
from langchain_core.messages import HumanMessage, AIMessage  # 여러 개

import os                                      # 모듈 전체
import json

# 사용
os.getenv("API_KEY")                           # Java: System.getenv("API_KEY")
json.dumps({"key": "value"})                   # JSON 직렬화

# 같은 프로젝트 내 파일 임포트
from tools.search_tools import search_news     # tools/search_tools.py 의 search_news
from agents.multi_agent import build_multi_agent

11. 환경변수 (.env)

import os
from dotenv import load_dotenv

load_dotenv()  # .env 파일 로드

# Java: System.getenv("GOOGLE_API_KEY")
api_key = os.getenv("GOOGLE_API_KEY")
api_key = os.getenv("GOOGLE_API_KEY", "기본값")  # 없으면 기본값
# .env 파일
GOOGLE_API_KEY=AIza...
DB_HOST=localhost

12. HTTP 요청 (requests)

import requests

# GET 요청
# Java: restTemplate.getForObject(url, Map.class)
response = requests.get("http://api.example.com/logs", params={
    "date": "2025-05-23",
    "type": "swift"
})
data = response.json()        # JSON 파싱 (Java: objectMapper.readValue)
status = response.status_code  # 200, 404 등

# POST 요청
# Java: restTemplate.postForEntity(url, body, Map.class)
response = requests.post("http://api.example.com/search",
    json={"keyword": "error", "date": "2025-05-23"},  # body
    headers={"Authorization": f"Bearer {token}"}       # 헤더
)

# 에러 처리
if response.status_code == 200:
    return response.json()
else:
    raise Exception(f"API 오류: {response.status_code}")

13. 예외 처리

# Java:
# try {
#     ...
# } catch (Exception e) {
#     ...
# } finally {
#     ...
# }

try:
    result = api_call()
except ValueError as e:          # 특정 예외
    print(f"값 오류: {e}")
except Exception as e:            # 모든 예외
    print(f"오류 발생: {e}")
finally:
    print("항상 실행")

# 예외 발생
raise ValueError("잘못된 입력입니다")  # Java: throw new IllegalArgumentException(...)

14. async / await

import asyncio

# Java의 CompletableFuture와 유사
# 동기 (블로킹)
def sync_call():
    result = requests.get(url)  # 여기서 대기
    return result

# 비동기 (논블로킹)
async def async_call():
    result = await some_async_function()  # await: 완료될 때까지 대기하되 다른 작업 가능
    return result

# FastAPI에서 스트리밍할 때 사용
@app.post("/chat/stream")
async def chat_stream(request):
    async def generate():
        async for chunk in agent.astream(...):  # 비동기 반복
            yield chunk
    return StreamingResponse(generate())

15. 자주 쓰는 패턴 모음

# ── 딕셔너리 병합 ─────────────────────────────────────────
base = {"a": 1, "b": 2}
extra = {"c": 3}
merged = {**base, **extra}    # {"a": 1, "b": 2, "c": 3}
# Java: Map.putAll()

# ── 조건부 표현식 (삼항 연산자) ───────────────────────────
# Java: String result = condition ? "yes" : "no";
result = "yes" if condition else "no"

# ── 리스트에서 조건 확인 ──────────────────────────────────
messages = [HumanMessage("안녕"), AIMessage("반가워")]

# 특정 타입 메시지가 있는지 확인
has_system = any(isinstance(m, SystemMessage) for m in messages)
# Java: messages.stream().anyMatch(m -> m instanceof SystemMessage)

# ── 문자열 포함 확인 ──────────────────────────────────────
text = "오늘 15시 스위프트 로그"
if "스위프트" in text:         # Java: text.contains("스위프트")
    print("스위프트 관련 질문")

# ── 역방향 반복 ───────────────────────────────────────────
for msg in reversed(messages):  # 뒤에서부터 순회
    if isinstance(msg, HumanMessage):
        last_user_msg = msg.content
        break

프로젝트에서 쓴 라이브러리 요약

라이브러리 역할 Java 유사
langchain_core LLM/Tool/Message 기본 타입 Spring Core
langchain_google_genai Gemini LLM 연동 Spring AI
langgraph Agent 그래프 실행 엔진 Spring Batch
fastapi REST API 서버 Spring MVC
uvicorn ASGI 서버 Tomcat
pydantic 데이터 검증/직렬화 Jackson + Bean Validation
python-dotenv .env 파일 로드 Spring @Value
requests HTTP 클라이언트 RestTemplate
chromadb 벡터 DB H2/PostgreSQL
반응형