-
[Effective Java] item 8 + 9. finalizer와 cleaner 사용을 피하라, try-finally보다는 try-with-resources를 사용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. [ item 8. finalizer와 cleaner 사용을 피하라 ] 자바는 두 가지 객체 소멸자를 제공한다. ☑️ finalizer : 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. ☑️ cleaner : finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로 불필요하다. finalizer와 cleaner는 즉시 수행된다는 보장이 없다. 얼마나 신속하게 수행될지는 전적으로 가비지 컬렉터 알고리즘에 달렸으며, 동작 또한 마찬가지 finalizer를 달아두면 그 인스턴스의 자원 회수가 제멋대로 지연될 수 있다. 수행 여부조차 보장하지 못한다. 따라서 상태를 영구적으로 수정하..
-
[Effective Java] item 6 + 7. 불필요한 객체 생성을 피하라, 다 쓴 객체 참조를 해제하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. [ item 6. 불필요한 객체 생성을 피하라 ] 똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 재사용은 빠르고 세련되다. ☑️ 기존의 인스턴스 재사용하기 String s = new String("bikini") // X String s = "bikini" // O ☑️ 생성자 대신 정적 팩터리 메서드 사용하기 생성자 대신 정적 팩터리 메서드를 제공하는 불변 클래스(item1) → 불필요한 객체 생성을 피할 수 있음 ↔ 생성자는 호출할 때마다 새로운 객체를 만들지만, 팩터리 메서드는 X ex) Boolean(String) 대신 Boolean.valueOf(String) 사용하기 ☑️..
-
[대규모 시스템 설계 기초] ch1. 사용자 수에 따른 규모 확장성
본문은 '가상 면접 사례로 배우는 대규모 시스템 설계 기초’를 읽고 정리한 내용을 기반으로 작성된 글입니다. [단일 서버] ☑️ 단일 서버 구성에서의 사용자 요청 처리 흐름 사용자는 도메인 이름(api.site.com)을 통해 웹사이트에 접속함 이 접속을 위해서는 도메인 이름을 DNS(Domain Name Service)에 질의하여 IP주로 변환하는 과정 필요 DNS는 보통 제 3사업자(third party) ↔ 우리 시스템의 일부는 아님 DNS 조회 결과로 IP주소 반환 (15.123 …) 해당 IP주소로 HTTP(HyperText Transfer Protocol) 요청이 전달됨 요청을 받은 웹 서버는 HTML페이지나 JSON형태의 응답 반환 [데이터베이스] 사용자가 늘면 서버 하나로는 충분하지 않아서..
-
[Effective Java] item 24. 멤버 클래스는 되도록 static으로 만들어라 **
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. ☑️ 중첩 클래스(nested class) : 다른 클래스 안에 정의된 클래스 ↔ 자신을 감싼 바깥 클래스에서만 쓰여야함 정적 멤버 클래스 비정적 멤버 클래스 익명 클래스 지역 클래스 정적 멤버 클래스를 제외한 나머지는 내부 클래스(inner class)에 해당된다. [정적 멤버 클래스 & 비정적 멤버 클래스] ☑️ 정적 멤버 클래스 : 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다 외부 클래스와 독립적으로 존재할 수 있음 → 외부 클래스의 인스턴스에 종속되지 않음 (inner class로 간주되지 않는 이유) ☑️ 비정적 멤버 클래스 구문상으로는 static 있고 없고 차이지만, 비정적..
-
[Effective Java] item 20. 추상 클래스보다는 인터페이스를 우선하라 *
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 추상 클래스 >인터페이스 >인터페이스+추상 골격 구현 클래스 [인터페이스와 추상 클래스] ☑️ 추상 클래스 단일 상속만 가능 구현 → 추상 클래스의 하위 클래스가 된다. 기존 클래스 위에 새로운 추상 클래스를 끼워넣기는 어렵다. ☑️ 인터페이스 다중 상속 가능 구현 → 같은 타입으로 취급된다. 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다. → 믹스인 정의에 안성맞춤 ☑️ 계층구조가 없는 타입 프레임워크 ex) 다음 코드는 아무런 문제가 되지 않는다. public interface Singer { AudioClip sing(Song song); } public interface SongWriter{ Song..
-
[Spring/fairer] 반복 기능 api 설계
반복 기능은 fairer를 개발하며 가장 신경써야할 부분이 많았던 기능이다. 일/주/월 단위로 반복되는 집안일을 관리해야하고, 수정&삭제를 할 때에도 반복 일정 모두 삭제/오늘 일정만 삭제/ 앞으로 예정된 집안일만 삭제 등 선택지가 많았다. 반복기능을 어떻게 개발할 것인지 설계하는 데에만 몇 주를 사용했던 것으로 기억한다. 4명의 의견이 모두 달랐어서 신기했고, 배울점도 많았던 기능이다. 의견1 새로운 테이블을 추가하지 않고, 기존 housework 테이블에 주기 칼럼만 추가 생성 : 기존 집안일 생성과 동일, 주기 칼럼에 주기만 추가하여 생성 조회 : 해당 날짜에 포함되는 집안일(반복x) 조회 반복되는 집안일 중 반복 요일이 같고, 시작 날짜~종료 날짜 안에 해당 날짜가 포함된 집안일 조회 수정 : 집..
-
[Spring/fairer] 반복 기능 api 개발 - 조회
반복 기능 구현 방법을 설계하고, 나는 조회 api를 담당했다. 반복기능 구현 전 집안일 api 에서도 조회를 담당했는데, 굉장히 비효율적으로 구현했던 전적이 있어서 이번에는 개선해 보고자 도전했는데 … fromDate ~ toDate에 속한 집안일을 조회하려면 반복 종류에 따라서 ONCE (반복x) scheduled_date가 조회 범위 안에 속하는지 확인 DAILY (매일 반복) scheduled_date ~ end_date가 조회 범위와 겹치는 구간이 있는지 확인 repeat_exception 테이블에 조회할 날짜가 등록되어 있는지 확인 WEEKLY (요일 반복) scheduled_date ~ end_date가 조회 범위와 겹치는 구간이 있는지 확인 (repeat_pattern에 저장된 요일 == ..
-
[Effective Java] item 8 + 9. finalizer와 cleaner 사용을 피하라, try-finally보다는 try-with-resources를 사용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. [ item 8. finalizer와 cleaner 사용을 피하라 ] 자바는 두 가지 객체 소멸자를 제공한다. ☑️ finalizer : 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. ☑️ cleaner : finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로 불필요하다. finalizer와 cleaner는 즉시 수행된다는 보장이 없다. 얼마나 신속하게 수행될지는 전적으로 가비지 컬렉터 알고리즘에 달렸으며, 동작 또한 마찬가지 finalizer를 달아두면 그 인스턴스의 자원 회수가 제멋대로 지연될 수 있다. 수행 여부조차 보장하지 못한다. 따라서 상태를 영구적으로 수정하..
-
[Effective Java] item 6 + 7. 불필요한 객체 생성을 피하라, 다 쓴 객체 참조를 해제하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. [ item 6. 불필요한 객체 생성을 피하라 ] 똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 재사용은 빠르고 세련되다. ☑️ 기존의 인스턴스 재사용하기 String s = new String("bikini") // X String s = "bikini" // O ☑️ 생성자 대신 정적 팩터리 메서드 사용하기 생성자 대신 정적 팩터리 메서드를 제공하는 불변 클래스(item1) → 불필요한 객체 생성을 피할 수 있음 ↔ 생성자는 호출할 때마다 새로운 객체를 만들지만, 팩터리 메서드는 X ex) Boolean(String) 대신 Boolean.valueOf(String) 사용하기 ☑️..
-
[Effective Java] item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 많은 클래스가 하나 이상의 자원에 의존한다. 하지만 의존관계를 잘못 사용하면 유연하지 않고 테스트가 어렵다. 정적 유틸리티를 잘못 사용한 경우 public class SpellChecker { private static final Lexicon dictionary = ...; // 의존하는 리소스 (의존성) private SpellChecker() {} // 객체 생성 방지 public static boolean isValid(String word) { ... } public static List suggestions(String typo) { ... } } 싱글톤을 잘못 사용한 경우 public class SpellChe..
-
[대규모 시스템 설계 기초] ch1. 사용자 수에 따른 규모 확장성
본문은 '가상 면접 사례로 배우는 대규모 시스템 설계 기초’를 읽고 정리한 내용을 기반으로 작성된 글입니다. [단일 서버] ☑️ 단일 서버 구성에서의 사용자 요청 처리 흐름 사용자는 도메인 이름(api.site.com)을 통해 웹사이트에 접속함 이 접속을 위해서는 도메인 이름을 DNS(Domain Name Service)에 질의하여 IP주로 변환하는 과정 필요 DNS는 보통 제 3사업자(third party) ↔ 우리 시스템의 일부는 아님 DNS 조회 결과로 IP주소 반환 (15.123 …) 해당 IP주소로 HTTP(HyperText Transfer Protocol) 요청이 전달됨 요청을 받은 웹 서버는 HTML페이지나 JSON형태의 응답 반환 [데이터베이스] 사용자가 늘면 서버 하나로는 충분하지 않아서..
-
[Effective Java] item 3+4. private 생성자나 열거 타입으로 싱글턴임을 보증하라, 인스턴스화를 막으려거든 private 생성자를 사용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. item 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 ☑️ 싱글턴 : 인스턴스를 오직 하나만 생성할 수 있는 클래스 클래스를 싱글턴으로 만들면 이를 사용하는 클라이언트를 테스트하기가 어려워질 수 있다. 싱글턴으로 만들어진 클래스에 의존하는 클라이언트 코드는 테스트가 어렵기 때문 의존성 주입을 통해 테스트하도록 설계하는게 바람직함 [싱글턴을 만드는 방법] ☑️ 방법 1) private 생성자 + public static final 필드 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() {} public ..
-
[Effective Java] item 2. 생성자에 매개변수가 많다면 빌더를 고려하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 정적 팩터리와 생성자는 똑같은 제약이 하나 있다. 선택적 매개변수가 많을 때 적절하게 대응하기 어렵다는 점이다. ex) 식품 포장 영양정보 표현 클래스 ↔ 항목이 엄청 많은데 대부분의 값이 0인 경우 [점층적 생성자 패턴 - 확장하기 어렵다!] : 필수 생성자 1개, 선택 매개변수를 늘여가며 생성자를 만드는 패턴 public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private fi..
-
[Effective Java] item 1. 생성자 대신 정적 팩터리 메서드를 고려하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 클라이언트가 클래스의 인스턴스를 얻는 전통적인 수단은 public 생성자지만, 클래스는 생성자와 별도로 정적 팩터리 메서드를 제공할 수 있다. [정적 팩터리 메서드의 장점] ☑️ 이름을 가질 수 있다 : 반환될 객체의 특성을 잘 드러내는 이름을 지어주자 ☑️ 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다 : 반복되는 요청에 같은 객체를 반환하는 식으로, 언제 어디스 인스턴스를 살아있게 할지를 철저히 통제할 수 있다. (인스턴스 통제 클래스) 싱글톤으로 만들 수 있음 인스턴스화 불가로 만들 수도 있음 불변 값 클래스에서 동치인 인스턴스가 단 하나뿐임을 보장할 수 있음 ☑️ 반환 타입의 하위 타입 객체를 반환할 수 있는..
-
[Effective Java] item 25. 톱레벨 클래스는 한 파일에 하나만 담으라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 말 그대로.. ☑️ 톱레벨 클래스 중복정의 예시 Utensil과 Dessert를 참조하는 Main 클래스 public class Main { public static void main(String[] args) { System.out.println(Utensil.NAME + Dessert.NAME); } } Utensil.java class Utensil { static final String NAME = "pan"; } class Dessert { static final String NAME = "cake"; } Main클래스와 Utensil클래스만 있는 상태에서 Main을 실행하면 pancake를 출력한다. Desser..
-
[Effective Java] item 24. 멤버 클래스는 되도록 static으로 만들어라 **
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. ☑️ 중첩 클래스(nested class) : 다른 클래스 안에 정의된 클래스 ↔ 자신을 감싼 바깥 클래스에서만 쓰여야함 정적 멤버 클래스 비정적 멤버 클래스 익명 클래스 지역 클래스 정적 멤버 클래스를 제외한 나머지는 내부 클래스(inner class)에 해당된다. [정적 멤버 클래스 & 비정적 멤버 클래스] ☑️ 정적 멤버 클래스 : 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다 외부 클래스와 독립적으로 존재할 수 있음 → 외부 클래스의 인스턴스에 종속되지 않음 (inner class로 간주되지 않는 이유) ☑️ 비정적 멤버 클래스 구문상으로는 static 있고 없고 차이지만, 비정적..
-
[Effective Java] item 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 태그 달린 클래스는 클래스 계층구조보다 훨씬 나쁘다! [태그 달린 클래스] : 두가지 이상의 의미를 표현할 수 있고, 그 중 현재 표현하는 의미를 태그 값으로 알려주는 클래스 public class Figure { enum Shape {RECTANGLE, CIRCLE}; // 태그 필드 - 현재 모양을 나타낸다. final Shape shape; // 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다. double length; double width; // 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다. double radius; // 원용 생성자 public FigureWithTag(double rad..
-
[Effective Java] item 21+22. 인터페이스는 구현하는 쪽을 생각해 설계하라, 인터페이스는 타입을 정의하는 용도로만 사용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. [item 21. 인터페이스는 구현하는 쪽을 생각해 설계하라] ☑️ 생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기란 어려운 법이다 최대한 범용적으로 구현하더라도 현존하는 모든 Collection 구현체와 잘 어우러지는 것은 아니다 → 컴파일에 성공하더라도 기존 구현체에 런타임 오류 발생시키기 가능 ☑️ 디폴트 메서드라는 도국 생겼더라도, 인터페이스를 설계할 때는 여전히 세심한 주의를 기울여야 한다. 릴리즈 전에 테스트하여 결함 찾아내기 [item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라] ☑️ 인터페이스 : 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할 → 자신의 인..
-
[Effective Java] item 20. 추상 클래스보다는 인터페이스를 우선하라 *
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 추상 클래스 >인터페이스 >인터페이스+추상 골격 구현 클래스 [인터페이스와 추상 클래스] ☑️ 추상 클래스 단일 상속만 가능 구현 → 추상 클래스의 하위 클래스가 된다. 기존 클래스 위에 새로운 추상 클래스를 끼워넣기는 어렵다. ☑️ 인터페이스 다중 상속 가능 구현 → 같은 타입으로 취급된다. 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다. → 믹스인 정의에 안성맞춤 ☑️ 계층구조가 없는 타입 프레임워크 ex) 다음 코드는 아무런 문제가 되지 않는다. public interface Singer { AudioClip sing(Song song); } public interface SongWriter{ Song..
-
[Effective Java] item 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 클래스를 안전하게 상속할 수 있도록 하려면 (상속만 아니었다면 기술하지 않았어야 할) 내부 구현 방식을 설명해야만 한다. [상속을 고려한 설계와 문서화] : 메서드를 정의하면 어떤 일이 일어나는지를 정확히 정리하여 문서로 남겨야 한다. → 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지(자기사용) 문서로 남겨야 한다. 공개된 메서드에서 클래스 자신의 또 다른 메서드를 호출하는데, 그 메서드가 재정의 가능 메서드인 경우 어떤 순서로 API를 호출해야 하는지 각각의 호출 결과가 이어지는 처리에 어떤 영향을 주는지 넓게 말하면, 재정의 가능 메서드를 호출할 수 있는 모든 상황을 문서로 남겨야 한다. ☑️..
-
[Effective Java] item 18. 상속보다는 컴포지션을 사용하라 *
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 상속은 코드를 재사용하는 강력한 수단이지만, 항상 최선은 아니다. 다른 패키지의 구체 클래스를 상속하는 일은 위험하다. [메서드 호출과 달리 상속은 캡슐화를 깨뜨린다] : 상위 클래스가 어떻게 구현되느냐에 따라 하위 클래스가 오동작할 수 있다. ☑️ HashSet를 상속받은 클래스 InstrumentedHashSet public class InstrumentedHashSet extends HashSet { // 추가된 원소의 수 private int addCount = 0; @Override public boolean addAll(Collection
-
[Effective Java] item 17. 변경 가능성을 최소화하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 불변 클래스란 간단히 말해 그 인스턴스의 내부 값을 수정할 수 없는 클래스다. 불변 인스턴스에 간직된 정보는 고정되어 객체가 파괴되는 순간까지 절대 달라지지 않는다. 불변 클래스는 가변 클래스보다 설계하고 구현하고 사용하기 쉬우며, 오류가 생길 여지도 적고 훨씬 안전하다. ☑️ 불변 클래스 생성 규칙 객체의 상태를 변경하는 메서드(변경자)를 제공하지 않는다. 클래스를 확장할 수 없도록 한다. 상속을 막는 대표적인 방법 ↔ 클래스를 final로 선언하기 모든 필드를 final로 선언한다. 시스템이 강제하는 수단을 이용해 설계자의 의도를 명확히 드러내는 방법 모든 필드를 private로 선언한다. 필드가 참조하는 가변 객체를 ..
-
[Effective Java] item 16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 이따금 인스턴스 필드들을 모아놓는 일 외에는 아무 목적도 없는 퇴보한 클래스를 작성하려 할 때가 있다. 이처럼 퇴보한 클래스는 public이어서는 안 된다! [패키지 바깥에서 접근할 수 있는 클래스라면 접근자를 제공해야 한다] : public 클래스에서는 필드를 모두 private으로 바꾸고 public 접근자(getter)를 추가해야 한다. ☑️ 접근자와 변경자 메서드를 활용해 데이터 캡슐화하기 class Point{ public double x; public double y; } 이런 클래스는 데이터 필드에 직접 접근할 수 있으니 캡슐화의 이점을 제공하지 못한다. API를 수정하지 않고는 내부 표현을 바꿀 수 없고, 불..
-
[Effective Java] item 15. 클래스와 멤버의 접근 권한을 최소화하라
본문은 Effective Java를 읽고 정리한 내용을 기반으로 작성된 글입니다. 어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 바로 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐다. 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨, 구현과 API를 깔끔히 분리한다. 오직 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식에는 전혀 개의치 않는다. 정보 은닉, 혹은 캡슐화라고 하는 이 개념은 소프트웨어 설계의 근간이 되는 원리다. [모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다] : 소프트웨어가 올바로 동작하는 한 항상 가장 낮은 접근 수준을 부여해야 한다. ☑️ 톱레벨 클래스, 인터페이스에 부여할 수 있는 접근 수준 public..
-
[Spring/fairer] 반복 기능 api 개발 - 조회
반복 기능 구현 방법을 설계하고, 나는 조회 api를 담당했다. 반복기능 구현 전 집안일 api 에서도 조회를 담당했는데, 굉장히 비효율적으로 구현했던 전적이 있어서 이번에는 개선해 보고자 도전했는데 … fromDate ~ toDate에 속한 집안일을 조회하려면 반복 종류에 따라서 ONCE (반복x) scheduled_date가 조회 범위 안에 속하는지 확인 DAILY (매일 반복) scheduled_date ~ end_date가 조회 범위와 겹치는 구간이 있는지 확인 repeat_exception 테이블에 조회할 날짜가 등록되어 있는지 확인 WEEKLY (요일 반복) scheduled_date ~ end_date가 조회 범위와 겹치는 구간이 있는지 확인 (repeat_pattern에 저장된 요일 == ..
-
[Spring/fairer] 반복 기능 api 설계
반복 기능은 fairer를 개발하며 가장 신경써야할 부분이 많았던 기능이다. 일/주/월 단위로 반복되는 집안일을 관리해야하고, 수정&삭제를 할 때에도 반복 일정 모두 삭제/오늘 일정만 삭제/ 앞으로 예정된 집안일만 삭제 등 선택지가 많았다. 반복기능을 어떻게 개발할 것인지 설계하는 데에만 몇 주를 사용했던 것으로 기억한다. 4명의 의견이 모두 달랐어서 신기했고, 배울점도 많았던 기능이다. 의견1 새로운 테이블을 추가하지 않고, 기존 housework 테이블에 주기 칼럼만 추가 생성 : 기존 집안일 생성과 동일, 주기 칼럼에 주기만 추가하여 생성 조회 : 해당 날짜에 포함되는 집안일(반복x) 조회 반복되는 집안일 중 반복 요일이 같고, 시작 날짜~종료 날짜 안에 해당 날짜가 포함된 집안일 조회 수정 : 집..
-
[TIL/adone] 2022-08-25~26 dto 디렉토리 구조 변경, @Embeddable
1. dto 디렉토리 대규모 수정 서비스에 estimate(견적)에 관련된 기능이 가장 많은데, dto 구조가 필요 이상으로 복잡하고 가독성이 떨어진다 생각이 들었다. 합칠 수 있는 dto는 합치고, request/response 위주로 분리했다. 매우 헷갈리고.. 오래 걸렸지만 훨씬 깔끔해진 것 같아 뿌듯하다. 2. 유저가 디자인한 간판 생성 api 😇 save the transient instance before flushing : FK 로 사용되는 컬럼값이 없는 상태에서 데이터를 넣으려하면 발생하는 에러이다. → 나는 진짜로 데이터가 없어서 발생했는데, 연관 관계 매핑해줄 때 사용하는 @ManyToOne, @OneToOne, @OneToMany 어노테이션에 cascade옵션을 변경하면 해결 할 수 ..