☰ 분류

코드 리뷰 프롬프트

코드를 붙여 넣으면 코드 품질, 버그 가능성, 보안 취약점, 성능 병목, 모범 사례와 테스트 보완점을 항목별로 검토합니다.

분류개발 › 코딩
태그검토분석개발자코드
프롬프트 (영어 본문 · 답은 한국어로 옵니다)
You are an expert AI code reviewer. When I share code with you, analyze it thoroughly and provide:

## Code Quality
- Identify code smells, anti-patterns, and areas for improvement
- Suggest refactoring opportunities
- Check for proper naming conventions and code organization

## Bug Detection
- Find potential bugs and logic errors
- Identify edge cases that may not be handled
- Check for null/undefined handling

## Security Analysis
- Identify security vulnerabilities (SQL injection, XSS, etc.)
- Check for proper input validation
- Review authentication/authorization patterns

## Performance
- Identify performance bottlenecks
- Suggest optimizations
- Check for memory leaks or resource issues

## Best Practices
- Verify adherence to language-specific best practices
- Check for proper error handling
- Review test coverage suggestions

Provide your review in a clear, actionable format with specific line references and code suggestions where applicable.

어떤 프롬프트인가

공유한 코드의 문제와 개선점을 실행 가능한 형식으로 받고 싶을 때 쓰는 리뷰 프롬프트다. 가능한 경우 줄 번호와 코드 제안을 포함하도록 요구한다.

모델 비교

Gemini는 가장 포괄적이지만 장황하고 일부 과장이 있다. ChatGPT는 정확성과 분량의 균형이 가장 좋으며, [C]는 답이 없다.

ChatGPT종합 1위
44/ 50

+ 핵심 위험과 간헐적 실패 원인을 간결히 연결했다.

- 테스트 제안과 코드 품질·성능 검토가 다소 얕다.

Gemini
41/ 50

+ 보안·버그·성능과 개선 코드를 폭넓게 다뤘다.

- 일부 원인을 단정하고 성능 설명도 다소 과장됐다.

기준ChatGPTGemini앞선 모델
지시 준수89Gemini +13%
정확성98ChatGPT +13%
구체성99동점
구성·가독성99동점
분량 적정성96ChatGPT +50%

gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-24). 측정값이 아니라 AI 심사 결과입니다.

답 전문 보기

같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.

넣은 입력
[붙여 넣은 자료]
다음 로그인 API 코드 리뷰 부탁드립니다. Node.js + Express로 짰는데 가끔 로그인 실패 문의가 들어옵니다.

```javascript
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
  db.query(query, (err, result) => {
    if (err) return res.status(500).send(err.stack);
    if (result.length > 0) {
      res.json({ token: jwt.sign({ id: result[0].id }, 'secret123') });
    } else {
      res.status(401).send('Invalid credentials');
    }
  });
});
```
gpt-5.6-luna (codex CLI · 에이전트 하네스) · 실행일 2026-09-24

총평

현재 코드는 SQL 인젝션과 평문 비밀번호 저장/검증 문제가 있어 즉시 수정이 필요합니다. 간헐적인 로그인 실패는 입력값 처리, 중복 사용자, DB 오류, 비밀번호 저장 방식 불일치 등에서 발생할 수 있습니다.

주요 문제

1. SQL 인젝션 — 치명적

const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;

사용자 입력을 SQL 문자열에 직접 삽입하고 있습니다. 공격자가 SQL 조건을 조작할 수 있습니다.

' OR '1'='1

처럼 입력하면 인증 우회가 가능할 수 있습니다.

반드시 파라미터 바인딩을 사용해야 합니다.

2. 평문 비밀번호 비교

DB에 비밀번호를 평문으로 저장하거나 SQL에서 직접 비교하는 구조는 안전하지 않습니다. 비밀번호는 bcrypt 또는 argon2로 해시하고 애플리케이션에서 검증해야 합니다.

3. JWT 비밀키 하드코딩

jwt.sign({ id: result[0].id }, 'secret123')

소스 코드에 노출된 짧은 키는 위조될 수 있습니다. 환경 변수와 충분히 긴 랜덤 키를 사용하고 만료 시간도 지정해야 합니다.

4. DB 오류 정보 노출

return res.status(500).send(err.stack);

스택 트레이스에는 SQL, 테이블명, 경로 등 민감한 정보가 포함될 수 있습니다. 상세 오류는 서버 로그에만 기록해야 합니다.

5. 입력값 검증 부족

req.body, username, password가 없거나 문자열이 아닐 수 있습니다.

  • 빈 문자열
  • 공백 포함 값
  • 지나치게 긴 입력
  • JSON body parser 미설정
  • username의 대소문자/공백 불일치

등이 간헐적인 실패 원인이 될 수 있습니다.

6. 사용자 조회 방식의 문제

username이 중복될 수 있으면 첫 번째 레코드만 사용하게 됩니다.

result[0]

username에 UNIQUE 제약을 설정해야 합니다.

권장 구현

const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');

app.post('/login', async (req, res) => {
  try {
    const { username, password } = req.body ?? {};

    if (
      typeof username !== 'string' ||
      typeof password !== 'string' ||
      username.trim() === '' ||
      password.length === 0 ||
      username.length > 100 ||
      password.length > 200
    ) {
      return res.status(400).json({
        message: '아이디와 비밀번호를 확인해 주세요.'
      });
    }

    const normalizedUsername = username.trim();

    const [rows] = await db.promise().query(
      'SELECT id, password_hash FROM users WHERE username = ? LIMIT 1',
      [normalizedUsername]
    );

    const user = rows[0];

    // 존재 여부를 외부에 구분해서 노출하지 않음
    const isValid = user
      ? await bcrypt.compare(password, user.password_hash)
      : false;

    if (!isValid) {
      return res.status(401).json({
        message: '아이디 또는 비밀번호가 올바르지 않습니다.'
      });
    }

    const token = jwt.sign(
      { sub: String(user.id) },
      process.env.JWT_SECRET,
      {
        algorithm: 'HS256',
        expiresIn: '1h'
      }
    );

    return res.json({ token });
  } catch (err) {
    console.error('Login failed:', err);
    return res.status(500).json({
      message: '일시적인 서버 오류가 발생했습니다.'
    });
  }
});

비밀번호 생성 또는 변경 시:

const passwordHash = await bcrypt.hash(password, 12);

DB에는 password_hash만 저장해야 합니다.

간헐적 실패 점검 항목

다음 로그를 민감정보 없이 확인해 보세요.

  • express.json()이 라우트보다 먼저 등록되어 있는지
  • 요청의 Content-Type: application/json 여부
  • DB 커넥션 풀 고갈 또는 타임아웃
  • DB 오류 발생률 및 연결 끊김
  • 사용자명 앞뒤 공백과 대소문자 처리
  • 중복 username 존재 여부
  • 기존 평문 비밀번호와 해시 비밀번호가 혼재하는지
  • 클라이언트가 만료되었거나 잘못된 토큰을 재사용하는지

추가로 로그인 엔드포인트에는 IP/계정 기준 rate limiting, 감사 로그, HTTPS, 일반화된 오류 메시지를 적용하는 것이 좋습니다.

같은 분류의 프롬프트

방산 CV 12개월 로드맵 프롬프트
2046 퍼즐 게임 제작 프롬프트
React 컴포넌트 통합 프롬프트
3D 아바타 팩토리 요구 프롬프트
3D FPS 게임 개발 프롬프트