|
| 1 | +**1. 의존성 관리가 필요한 이유** |
| 2 | + |
| 3 | +- 라이브러리나 프레임워크가 업데이트되거나 변경될 때, 서로 호환이 보장되도록 버전을 맞추고 충돌을 방지하기 위함 |
| 4 | +- 코드가 점점 복잡해짐에 따라, 프로젝트의 안정성과 유지보수를 쉽게 하기 위해 필요 |
| 5 | +- e.g. 도메인 모듈(계층)을 나누면, 한 곳의 수정이 다른 곳에 미치는 영향이 최소화된다. |
| 6 | + 예를 들어, 도메인 로직을 변경해도 애플리케이션·인프라 레이어는 건드릴 필요가 적다. |
| 7 | + 각 레이어의 책임이 분명해 유지보수 범위와 충돌이 줄어든다. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +**2. 계층(레이어)을 구분해서 설계하는 이유** |
| 12 | + |
| 13 | +- 책임 분리를 통해 각 레이어가 맡는 역할을 명확히 하고, 코드 가독성과 유지보수를 향상 |
| 14 | +- 각 레이어가 독립적으로 변경될 수 있어, 시스템 확장성과 유연성을 높임 |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +**3. Controller, Service, Repository 각 레이어는 어떤 책임을 가지며 어떻게 협력하나요?** |
| 19 | + |
| 20 | +- **Controller**: 클라이언트 요청을 받고, 적절한 Service를 호출하여 결과를 반환 |
| 21 | +- **Service**: 비즈니스 로직을 처리하며, 필요한 경우 Repository를 통해 데이터 접근 수행 |
| 22 | +- **Repository**: 데이터베이스와 직접 소통하여 데이터를 조회·저장·수정·삭제 |
| 23 | + |
| 24 | +--- |
| 25 | + |
| 26 | +**4. DDD(Domain-Driven Design)의 목표** |
| 27 | + |
| 28 | +- 소프트웨어의 핵심 복잡도(도메인 로직)를 명확하게 표현하고 해결하기 위함 |
| 29 | +- 도메인 모델을 중심으로 팀 간의 공통 언어(Ubiquitous Language)를 형성하여 요구사항과 구현이 일치하게 개발 |
| 30 | + |
| 31 | +--- |
| 32 | + |
| 33 | +**5. OOP(Object-Oriented Programming)가 필요한 이유** |
| 34 | + |
| 35 | +- 객체를 중심으로 책임과 역할을 나누어 설계하면, 코드 재사용성과 유지보수가 좋아짐 |
| 36 | +- 캡슐화, 상속, 다형성 등을 통해 복잡도를 낮추고 유연성을 높임 |
| 37 | +- e.g. 회원 정보를 다루는 “User” 객체가 “Name”과 “Address” 같은 값 객체를 각각 캡슐화하여 사용한다고 해보겠습니다. |
| 38 | + “Name” 객체가 “firstName”, “lastName”을 유효성 검증(빈 문자열 여부, 특수문자 포함 등)하고, “Address” 객체가 “City”, “Street”, “PostalCode”를 검증하도록 분리하면, 이름 형식 변경이나 주소 포맷 변경 등 세부 규칙이 생겨도 관련 객체만 수정하면 됩니다. |
| 39 | + 이런 식으로 객체마다 자체적인 검증과 책임을 분명히 두면, 실무에서 규칙이 자주 추가·수정되는 상황에서도 코드를 대폭 갈아엎지 않고도 유연하게 대응할 수 있게 됩니다. |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +**6. .gitignore를 사용하는 목적** |
| 44 | + |
| 45 | +- 버전 관리가 불필요하거나 보안상 노출되면 안 되는 파일(빌드 결과물, 환경 설정 파일 등)을 Git에서 제외하여 관리 |
| 46 | +- 저장소 용량 낭비와 불필요한 충돌을 방지 |
| 47 | + |
| 48 | +--- |
| 49 | + |
| 50 | +**7. Docker가 로컬 개발 환경에서 주로 어떻게 쓰이나요?** |
| 51 | + |
| 52 | +- 특정 버전의 DB나 외부 서비스 환경을 빠르게 구성하여, 개발자가 동일한 환경에서 작업할 수 있도록 지원 |
| 53 | +- 여러 프로젝트에서 환경 충돌 없이 독립적인 컨테이너를 구동할 수 있음 |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +**8. Docker의 Image와 Container의 개념과 차이에 대해 설명해주세요.** |
| 58 | + |
| 59 | +- **Image**: 실행 가능한 환경(파일시스템, 런타임, 설정 등)을 캡슐화한 템플릿 |
| 60 | +- **Container**: Image를 실제로 실행한 상태로, 독립된 프로세스로 동작 |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +**9. docker-compose.yml 파일을 작성할 때 유의해야 할 점은 무엇인가요?** |
| 65 | + |
| 66 | +- 서로 연결될 서비스(컨테이너)의 포트, 볼륨, 네트워크 설정을 명확히 정의 |
| 67 | +- 환경 변수나 데이터 볼륨, 버전 정보를 정확히 기재하여 재현 가능하도록 함 |
| 68 | +- 여러 컨테이너 간 의존성을 고려하여 실행 순서를 지정하거나, 재시작 정책을 설정 |
| 69 | + |
| 70 | +--- |
| 71 | + |
| 72 | +**10. JPA가 하는 역할은 무엇인가요?** |
| 73 | + |
| 74 | +- 자바 객체와 데이터베이스 테이블 간의 매핑을 자동으로 처리하여, SQL을 직접 다루지 않고도 데이터를 조작할 수 있게 함 |
| 75 | +- 데이터 액세스 계층을 단순화하고, 생산성과 유지보수를 높임 |
| 76 | + |
| 77 | +--- |
| 78 | + |
| 79 | +**11. JPA에서 Entity 클래스에 주로 사용되는 어노테이션과 그 역할을 설명해주세요.** |
| 80 | + |
| 81 | +- `@Entity`: 해당 클래스를 JPA가 관리하는 엔티티로 지정 |
| 82 | +- `@Table`: 엔티티와 매핑될 테이블 이름 설정 |
| 83 | +- `@Id`: 엔티티의 PK(기본 키) 필드 지정 |
| 84 | +- `@GeneratedValue`: PK의 자동 생성 전략 지정 |
| 85 | +- `@Column`: 테이블의 컬럼 속성(name, nullable, length 등) 지정 |
| 86 | +- `@OneToMany`, `@ManyToOne`, `@OneToOne`, `@ManyToMany`: 엔티티 간의 연관관계를 설정 |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +**12. JPA에서 Converter, Embeddable, Auditing 등을 사용하는 이점은 무엇인가요?** |
| 91 | + |
| 92 | +- **Converter**: 특정 타입을 변환(예: enum ↔ String)하여 DB와 애플리케이션 간에 일관성을 유지 |
| 93 | +- **Embeddable**: 재사용 가능한 값 객체를 쉽게 활용해 도메인 모델을 풍부하게 표현 |
| 94 | +- **Auditing**: 생성·수정 시점이나 작성자 등을 자동으로 관리해, 공통 요구사항을 중복 없이 처리 |
| 95 | + |
| 96 | +--- |
| 97 | + |
| 98 | +**13. 양방향 매핑(ManyToOne, OneToMany) 시 주의해야 할 점은 무엇인가요?** |
| 99 | + |
| 100 | +- 무한 루프(순환 참조) 방지: 예를 들어, 양쪽에서 같은 엔티티를 직렬화할 때 |
| 101 | +- 연관관계 주인 설정: 어느 쪽이 외래 키를 관리하는 주인인지 명확히 해줘야 함 |
| 102 | +- 필요 없는 양방향보다는 단방향을 우선 고려하여 복잡도를 낮춤 |
| 103 | + |
| 104 | +--- |
| 105 | + |
| 106 | +**14. JPA에서 N+1 문제가 무엇인지 예를 간략하게 적고 해결방법을 설명하세요.** |
| 107 | + |
| 108 | +- **N+1 문제**: 연관 관계가 있는 엔티티를 조회할 때, 추가로 N번의 쿼리가 발생하여 성능 저하를 일으키는 문제 |
| 109 | +- **예시**: Member와 Team 엔티티가 다대일(ManyToOne) 관계일 때, 모든 Member를 조회하고 각 Member의 Team을 LAZY 로딩할 때 발생 |
| 110 | + ```java |
| 111 | + public void demonstrateNPlusOneProblem() { |
| 112 | + // 첫 번째 쿼리: 모든 Member를 조회 |
| 113 | + // 예) SELECT m FROM Member m |
| 114 | + List<Member> members = memberRepository.findAll(); // 1개의 쿼리 |
| 115 | + |
| 116 | + for (Member m : members) { |
| 117 | + // 각 Member마다 Team 정보를 LAZY 로딩하면서 실행되는 쿼리 |
| 118 | + // 예) SELECT t FROM Team t WHERE t.id = ? |
| 119 | + System.out.println(m.getTeam().getName()); // N개의 쿼리 |
| 120 | + } |
| 121 | + } |
| 122 | + ``` |
| 123 | + |
| 124 | +- **해결 방법** |
| 125 | + - 페치 조인(Fetch Join)을 사용하여 한 번의 쿼리로 모든 연관 엔티티를 함께 조회 |
| 126 | + - JPA의 `EntityGraph`를 사용하여 페치 조인을 명시적으로 설정 |
| 127 | + - @BatchSize를 사용하여 일괄 처리로 성능을 향상 |
| 128 | + |
| 129 | +**15. 단위 테스트(Unit Test)는 무엇이며, 왜 필요한가요?** |
| 130 | + |
| 131 | +- **정의**: 시스템의 가장 작은 단위(주로 메서드나 클래스)의 동작을 검증하는 테스트 |
| 132 | +- **필요성**: 빠른 피드백으로 에러를 조기에 발견하고, 리팩토링이나 기능 추가 시 안정성을 제공 |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +**16. 통합 테스트(Integration Test)는 무엇이며, 왜 필요한가요?** |
| 137 | + |
| 138 | +- **정의**: 여러 컴포넌트나 모듈이 실제로 연결된 상태에서 전체 흐름이 정상 동작하는지 검증하는 테스트 |
| 139 | +- **필요성**: 모듈 간 연동 문제, 의존성 문제 등을 조기에 발견해 실제 배포 후 장애를 줄임 |
| 140 | + |
| 141 | +--- |
| 142 | + |
| 143 | +**17. Mock은 무엇이며, 어떤 상황에서 왜 사용하는가요?** |
| 144 | + |
| 145 | +- **정의**: 실제 객체 대신에 비슷한 동작만 흉내내는 ‘가짜 객체’ |
| 146 | +- **사용 상황**: 외부 의존성이 있는 코드를 테스트할 때, 네트워크나 DB 같은 복잡한 환경을 대체하여 테스트를 빠르고 독립적으로 진행하기 위해 사용 |
| 147 | + |
| 148 | +--- |
| 149 | + |
| 150 | +**18. RESTful한 API를 설계할 때 핵심적으로 고려해야 할 점들은 무엇인가요?** |
| 151 | + |
| 152 | +- 리소스(명사형) 중심의 URL과 HTTP 메서드(POST, GET, PUT, DELETE)로 명확한 액션 표현 |
| 153 | +- 적절한 상태 코드(2xx, 4xx, 5xx)와 에러 메시지 설계 |
| 154 | +- 요청과 응답에 일관성 있고 명확한 JSON(or XML) 구조 사용 |
| 155 | +- 보안, 버전 관리, 문서화 등도 함께 고려 |
| 156 | +- 리소스 간의 관계를 표현하고, 가능하다면 HATEOAS(Hypermedia as the Engine of Application State)를 활용해 API의 자기 기술적인 특성을 활용 |
| 157 | + |
| 158 | +--- |
| 159 | + |
| 160 | +**19. DTO를 사용하는 이유는 무엇인가요?** |
| 161 | + |
| 162 | +- 도메인(Entity) 객체와 API 요청·응답 모델을 분리해, 불필요하거나 민감한 정보 노출을 막을 수 있음 |
| 163 | +- 계층 간 데이터 이동 시 변환 로직을 추가하거나, 표시 형식을 자유롭게 조절 가능 |
| 164 | + |
| 165 | +--- |
| 166 | + |
| 167 | +**20. Spring Boot에서 전역 예외 처리를 위해 사용할 수 있는 방법은 무엇인가요?** |
| 168 | + |
| 169 | +- `@ControllerAdvice`와 `@ExceptionHandler`를 사용해 전역적으로 예외를 핸들링 |
| 170 | +- `ResponseEntityExceptionHandler`를 상속받아 공통 에러 처리를 구성 |
| 171 | +- 필터나 인터셉터 등을 활용해 더 넓은 범위에서 에러 처리를 할 수도 있음 |
| 172 | + |
| 173 | +--- |
| 174 | + |
| 175 | +**21. API 서버로 들어오는 다양한 데이터의 포맷(타입)을 핸들링하기 위해 어떤 방법들을 사용할 수 있나요?** |
| 176 | + |
| 177 | +- RequestParam 혹은 PathVariable의 경우 |
| 178 | + - **Spring**에서 `HttpMessageConverter`를 설정하거나 커스텀 Converter를 구현 |
| 179 | +- RequestBody의 경우 |
| 180 | + - **Jackson**이나 **Gson** 같은 라이브러리를 활용해 JSON/XML 등 다양한 포맷을 직렬화/역직렬화 |
| 181 | + - 커스텀 Serializer/Deserializer를 작성해 특정 데이터 타입에 대해 맞춤형 처리를 적용 |
| 182 | + |
| 183 | +--- |
0 commit comments